Merge "Support query active microphones in MediaRecorder."
diff --git a/Android.bp b/Android.bp
index 9645ba6..d5e04f9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -212,6 +212,11 @@
"core/java/android/nfc/INfcUnlockHandler.aidl",
"core/java/android/nfc/INfcDta.aidl",
"core/java/android/nfc/ITagRemovedCallback.aidl",
+ "core/java/android/se/omapi/ISecureElementService.aidl",
+ "core/java/android/se/omapi/ISecureElementListener.aidl",
+ "core/java/android/se/omapi/ISecureElementChannel.aidl",
+ "core/java/android/se/omapi/ISecureElementReader.aidl",
+ "core/java/android/se/omapi/ISecureElementSession.aidl",
"core/java/android/os/IBatteryPropertiesListener.aidl",
"core/java/android/os/IBatteryPropertiesRegistrar.aidl",
"core/java/android/os/ICancellationSignal.aidl",
@@ -314,6 +319,10 @@
"core/java/android/service/chooser/IChooserTargetResult.aidl",
"core/java/android/service/resolver/IResolverRankerService.aidl",
"core/java/android/service/resolver/IResolverRankerResult.aidl",
+ "core/java/android/service/textclassifier/ITextClassificationCallback.aidl",
+ "core/java/android/service/textclassifier/ITextClassifierService.aidl",
+ "core/java/android/service/textclassifier/ITextLinksCallback.aidl",
+ "core/java/android/service/textclassifier/ITextSelectionCallback.aidl",
"core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl",
"core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl",
"core/java/android/view/accessibility/IAccessibilityManager.aidl",
@@ -332,6 +341,8 @@
"core/java/android/view/IPinnedStackController.aidl",
"core/java/android/view/IPinnedStackListener.aidl",
"core/java/android/view/IRemoteAnimationRunner.aidl",
+ "core/java/android/view/IRecentsAnimationController.aidl",
+ "core/java/android/view/IRecentsAnimationRunner.aidl",
"core/java/android/view/IRemoteAnimationFinishedCallback.aidl",
"core/java/android/view/IRotationWatcher.aidl",
"core/java/android/view/IWallpaperVisibilityListener.aidl",
@@ -412,9 +423,9 @@
"location/java/android/location/IGpsGeofenceHardware.aidl",
"location/java/android/location/INetInitiatedListener.aidl",
"location/java/com/android/internal/location/ILocationProvider.aidl",
- "media/java/android/media/IAudioService.aidl",
"media/java/android/media/IAudioFocusDispatcher.aidl",
"media/java/android/media/IAudioRoutesObserver.aidl",
+ "media/java/android/media/IAudioService.aidl",
"media/java/android/media/IMediaHTTPConnection.aidl",
"media/java/android/media/IMediaHTTPService.aidl",
"media/java/android/media/IMediaResourceMonitor.aidl",
@@ -422,9 +433,8 @@
"media/java/android/media/IMediaRouterService.aidl",
"media/java/android/media/IMediaScannerListener.aidl",
"media/java/android/media/IMediaScannerService.aidl",
- "media/java/android/media/IMediaSession2.aidl",
- "media/java/android/media/IMediaSession2Callback.aidl",
"media/java/android/media/IPlaybackConfigDispatcher.aidl",
+ "media/java/android/media/ISessionTokensListener.aidl",
":libaudioclient_aidl",
"media/java/android/media/IRecordingConfigDispatcher.aidl",
"media/java/android/media/IRemoteDisplayCallback.aidl",
@@ -477,16 +487,19 @@
"telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl",
"telephony/java/android/telephony/data/IDataService.aidl",
"telephony/java/android/telephony/data/IDataServiceCallback.aidl",
- "telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl",
- "telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl",
- "telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl",
- "telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl",
- "telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl",
- "telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl",
- "telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl",
- "telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl",
- "telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl",
- "telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsConfig.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl",
+ "telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl",
+ "telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
"telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
"telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl",
"telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl",
@@ -504,13 +517,10 @@
"telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl",
"telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl",
"telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl",
- "telephony/java/com/android/ims/internal/IImsRegistration.aidl",
- "telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl",
"telephony/java/com/android/ims/internal/IImsRcsFeature.aidl",
"telephony/java/com/android/ims/internal/IImsService.aidl",
"telephony/java/com/android/ims/internal/IImsServiceController.aidl",
"telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl",
- "telephony/java/com/android/ims/internal/IImsSmsListener.aidl",
"telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl",
"telephony/java/com/android/ims/internal/IImsUt.aidl",
"telephony/java/com/android/ims/internal/IImsUtListener.aidl",
@@ -595,6 +605,7 @@
"core/java/android/speech/tts/EventLogTags.logtags",
"core/java/android/net/EventLogTags.logtags",
"core/java/android/webkit/EventLogTags.logtags",
+ "core/java/com/android/internal/app/EventLogTags.logtags",
"core/java/com/android/internal/logging/EventLogTags.logtags",
"core/java/com/android/server/DropboxLogTags.logtags",
"core/java/org/chromium/arc/EventLogTags.logtags",
@@ -636,8 +647,10 @@
],
},
- // See comment on framework-oahl-backward-compatibility module below
exclude_srcs: [
+ // See comment on framework-atb-backward-compatibility module below
+ "core/java/android/content/pm/AndroidTestBaseUpdater.java",
+ // See comment on framework-oahl-backward-compatibility module below
"core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java",
],
@@ -663,6 +676,7 @@
"android.hardware.vibrator-V1.1-java-constants",
"android.hardware.wifi-V1.0-java-constants",
"android.hardware.radio-V1.0-java",
+ "android.hardware.usb.gadget-V1.0-java",
],
// Loaded with System.loadLibrary by android.view.textclassifier
@@ -690,6 +704,18 @@
],
}
+// A temporary build target that is conditionally included on the bootclasspath if
+// android.test.base library has been removed and which provides support for
+// maintaining backwards compatibility for APKs that target pre-P and depend on
+// android.test.base classes. This is used iff REMOVE_ATB_FROM_BCP=true is
+// specified on the build command line.
+java_library {
+ name: "framework-atb-backward-compatibility",
+ srcs: [
+ "core/java/android/content/pm/AndroidTestBaseUpdater.java",
+ ],
+}
+
genrule {
name: "framework-statslog-gen",
tools: ["stats-log-api-gen"],
diff --git a/Android.mk b/Android.mk
index 32e4bfa..d72e398 100644
--- a/Android.mk
+++ b/Android.mk
@@ -821,10 +821,22 @@
LOCAL_SRC_FILES := \
$(call all-proto-files-under, core/proto) \
$(call all-proto-files-under, libs/incident/proto/android/os)
+# Protos have lots of MissingOverride and similar.
+LOCAL_ERROR_PRONE_FLAGS := -XepDisableAllChecks
include $(BUILD_STATIC_JAVA_LIBRARY)
# ==== hiddenapi lists =======================================
+# Copy blacklist and dark greylist over into the build folder.
+# This is for ART buildbots which need to mock these lists and have alternative
+# rules for building them. Other rules in the build system should depend on the
+# files in the build folder.
+
+$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-blacklist.txt,\
+ $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)))
+$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-dark-greylist.txt,\
+ $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST)))
+
# Generate light greylist as private API minus (blacklist plus dark greylist).
$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
diff --git a/apct-tests/perftests/core/src/android/text/MeasuredTextMemoryUsageTest.java b/apct-tests/perftests/core/src/android/text/MeasuredTextMemoryUsageTest.java
new file mode 100644
index 0000000..fc6302e
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/text/MeasuredTextMemoryUsageTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.text;
+
+import static android.text.TextDirectionHeuristics.LTR;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.test.InstrumentationRegistry;
+import android.content.res.ColorStateList;
+import android.graphics.Canvas;
+import android.graphics.Typeface;
+import android.text.Layout;
+import android.text.style.TextAppearanceSpan;
+import android.view.DisplayListCanvas;
+import android.view.RenderNode;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.CharBuffer;
+import java.util.Random;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class MeasuredTextMemoryUsageTest {
+ private static final int WORD_LENGTH = 9; // Random word has 9 characters.
+ private static final boolean NO_STYLE_TEXT = false;
+
+ private static TextPaint PAINT = new TextPaint();
+
+ private static int TRIAL_COUNT = 100;
+
+ public MeasuredTextMemoryUsageTest() {}
+
+ private TextPerfUtils mTextUtil = new TextPerfUtils();
+
+ @Before
+ public void setUp() {
+ mTextUtil.resetRandom(0 /* seed */);
+ }
+
+ private void reportMemoryUsage(int memoryUsage, String key) {
+ Bundle status = new Bundle();
+ status.putInt(key + "_median", memoryUsage);
+ InstrumentationRegistry.getInstrumentation().sendStatus(Activity.RESULT_OK, status);
+ }
+
+ private int median(int[] values) {
+ return values.length % 2 == 0 ?
+ (values[values.length / 2] + values[values.length / 2 - 1]) / 2:
+ values[values.length / 2];
+ }
+
+ @Test
+ public void testMemoryUsage_NoHyphenation() {
+ int[] memories = new int[TRIAL_COUNT];
+ // Report median of randomly generated MeasuredText.
+ for (int i = 0; i < TRIAL_COUNT; ++i) {
+ memories[i] = new MeasuredText.Builder(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+ .build().getMemoryUsage();
+ }
+ reportMemoryUsage(median(memories), "MemoryUsage_NoHyphenation");
+ }
+
+ @Test
+ public void testMemoryUsage_Hyphenation() {
+ int[] memories = new int[TRIAL_COUNT];
+ // Report median of randomly generated MeasuredText.
+ for (int i = 0; i < TRIAL_COUNT; ++i) {
+ memories[i] = new MeasuredText.Builder(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .build().getMemoryUsage();
+ }
+ reportMemoryUsage(median(memories), "MemoryUsage_Hyphenation");
+ }
+
+ @Test
+ public void testMemoryUsage_NoHyphenation_WidthOnly() {
+ int[] memories = new int[TRIAL_COUNT];
+ // Report median of randomly generated MeasuredText.
+ for (int i = 0; i < TRIAL_COUNT; ++i) {
+ memories[i] = new MeasuredText.Builder(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+ .build(false /* width only */).getMemoryUsage();
+ }
+ reportMemoryUsage(median(memories), "MemoryUsage_NoHyphenation_WidthOnly");
+ }
+
+ @Test
+ public void testMemoryUsage_Hyphenatation_WidthOnly() {
+ int[] memories = new int[TRIAL_COUNT];
+ // Report median of randomly generated MeasuredText.
+ for (int i = 0; i < TRIAL_COUNT; ++i) {
+ memories[i] = new MeasuredText.Builder(
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .build(false /* width only */).getMemoryUsage();
+ }
+ reportMemoryUsage(median(memories), "MemoryUsage_Hyphenation_WidthOnly");
+ }
+}
diff --git a/apct-tests/perftests/core/src/android/text/MeasuredTextPerfTest.java b/apct-tests/perftests/core/src/android/text/MeasuredTextPerfTest.java
new file mode 100644
index 0000000..98f2bd5
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/text/MeasuredTextPerfTest.java
@@ -0,0 +1,185 @@
+/*
+ * 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.text;
+
+import static android.text.TextDirectionHeuristics.LTR;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import android.content.res.ColorStateList;
+import android.graphics.Canvas;
+import android.graphics.Typeface;
+import android.text.Layout;
+import android.text.style.TextAppearanceSpan;
+import android.view.DisplayListCanvas;
+import android.view.RenderNode;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.CharBuffer;
+import java.util.Random;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class MeasuredTextPerfTest {
+ 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 MeasuredTextPerfTest() {}
+
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ private TextPerfUtils mTextUtil = new TextPerfUtils();
+
+ @Before
+ public void setUp() {
+ mTextUtil.resetRandom(0 /* seed */);
+ }
+
+ @Test
+ public void testCreate_NoStyled_Hyphenation() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ state.resumeTiming();
+
+ new MeasuredText.Builder(text, PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .build(true /* do full layout */);
+ }
+ }
+
+ @Test
+ public void testCreate_NoStyled_NoHyphenation() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ state.resumeTiming();
+
+ new MeasuredText.Builder(text, PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+ .build(true /* do full layout */);
+ }
+ }
+
+ @Test
+ public void testCreate_NoStyled_Hyphenation_WidthOnly() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ state.resumeTiming();
+
+ new MeasuredText.Builder(text, PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .build(false /* width only */);
+ }
+ }
+
+ @Test
+ public void testCreate_NoStyled_NoHyphenation_WidthOnly() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ state.resumeTiming();
+
+ new MeasuredText.Builder(text, PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+ .build(false /* width only */);
+ }
+ }
+
+ @Test
+ public void testCreate_Styled_Hyphenation() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
+ state.resumeTiming();
+
+ new MeasuredText.Builder(text, PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .build(true /* do full layout */);
+ }
+ }
+
+ @Test
+ public void testCreate_Styled_NoHyphenation() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
+ state.resumeTiming();
+
+ new MeasuredText.Builder(text, PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+ .build(true /* do full layout */);
+ }
+ }
+
+ @Test
+ public void testCreate_Styled_Hyphenation_WidthOnly() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
+ state.resumeTiming();
+
+ new MeasuredText.Builder(text, PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+ .build(false /* width only */);
+ }
+ }
+
+ @Test
+ public void testCreate_Styled_NoHyphenation_WidthOnly() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
+ state.resumeTiming();
+
+ new MeasuredText.Builder(text, PAINT)
+ .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+ .build(false /* width only */);
+ }
+ }
+}
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
index 682885b..bab2a85 100644
--- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
@@ -43,74 +43,30 @@
@LargeTest
@RunWith(AndroidJUnit4.class)
public class StaticLayoutPerfTest {
+ 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 StaticLayoutPerfTest() {}
@Rule
public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
- 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 int PARA_LENGTH = 500; // Number of characters in a paragraph.
-
- private static final boolean NO_STYLE_TEXT = false;
- private static final boolean STYLE_TEXT = true;
-
- private Random mRandom;
-
- private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
- private static final int ALPHABET_LENGTH = ALPHABET.length();
-
- private static final ColorStateList TEXT_COLOR = ColorStateList.valueOf(0x00000000);
- private static final String[] FAMILIES = { "sans-serif", "serif", "monospace" };
- private static final int[] STYLES = {
- Typeface.NORMAL, Typeface.BOLD, Typeface.ITALIC, Typeface.BOLD_ITALIC
- };
-
- private final char[] mBuffer = new char[PARA_LENGTH];
-
- private static TextPaint PAINT = new TextPaint();
- private static final int TEXT_WIDTH = WORDS_IN_LINE * WORD_LENGTH * (int) PAINT.getTextSize();
-
- private CharSequence generateRandomParagraph(int wordLen, boolean applyRandomStyle) {
- for (int i = 0; i < PARA_LENGTH; i++) {
- if (i % (wordLen + 1) == wordLen) {
- mBuffer[i] = ' ';
- } else {
- mBuffer[i] = ALPHABET.charAt(mRandom.nextInt(ALPHABET_LENGTH));
- }
- }
-
- CharSequence cs = CharBuffer.wrap(mBuffer);
- if (!applyRandomStyle) {
- return cs;
- }
-
- SpannableStringBuilder ssb = new SpannableStringBuilder(cs);
- for (int i = 0; i < ssb.length(); i += WORD_LENGTH) {
- final int spanStart = i;
- final int spanEnd = (i + WORD_LENGTH) > ssb.length() ? ssb.length() : i + WORD_LENGTH;
-
- final TextAppearanceSpan span = new TextAppearanceSpan(
- FAMILIES[mRandom.nextInt(FAMILIES.length)],
- STYLES[mRandom.nextInt(STYLES.length)],
- 24 + mRandom.nextInt(32), // text size. min 24 max 56
- TEXT_COLOR, TEXT_COLOR);
-
- ssb.setSpan(span, spanStart, spanEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- }
- return ssb;
- }
+ private TextPerfUtils mTextUtil = new TextPerfUtils();
@Before
public void setUp() {
- mRandom = new Random(0);
+ mTextUtil.resetRandom(0 /* seed */);
}
@Test
public void testCreate_FixedText_NoStyle_Greedy_NoHyphenation() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
while (state.keepRunning()) {
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
@@ -124,7 +80,7 @@
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
state.pauseTiming();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
state.resumeTiming();
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -139,7 +95,7 @@
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
state.pauseTiming();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
state.resumeTiming();
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -154,7 +110,7 @@
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
state.pauseTiming();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
state.resumeTiming();
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -169,7 +125,7 @@
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
state.pauseTiming();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
state.resumeTiming();
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -184,7 +140,7 @@
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
state.pauseTiming();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
state.resumeTiming();
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -200,7 +156,7 @@
while (state.keepRunning()) {
state.pauseTiming();
final MeasuredText text = new MeasuredText.Builder(
- generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
.build();
@@ -219,7 +175,7 @@
while (state.keepRunning()) {
state.pauseTiming();
final MeasuredText text = new MeasuredText.Builder(
- generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
.build();
@@ -238,7 +194,7 @@
while (state.keepRunning()) {
state.pauseTiming();
final MeasuredText text = new MeasuredText.Builder(
- generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
.build();
@@ -257,7 +213,7 @@
while (state.keepRunning()) {
state.pauseTiming();
final MeasuredText text = new MeasuredText.Builder(
- generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
.build();
@@ -276,7 +232,7 @@
while (state.keepRunning()) {
state.pauseTiming();
final MeasuredText text = new MeasuredText.Builder(
- generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
.build();
@@ -292,7 +248,7 @@
@Test
public void testDraw_FixedText_NoStyled() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
final RenderNode node = RenderNode.create("benchmark", null);
while (state.keepRunning()) {
state.pauseTiming();
@@ -311,7 +267,7 @@
final RenderNode node = RenderNode.create("benchmark", null);
while (state.keepRunning()) {
state.pauseTiming();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
final DisplayListCanvas c = node.start(1200, 200);
@@ -327,7 +283,7 @@
final RenderNode node = RenderNode.create("benchmark", null);
while (state.keepRunning()) {
state.pauseTiming();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
final DisplayListCanvas c = node.start(1200, 200);
@@ -343,7 +299,7 @@
final RenderNode node = RenderNode.create("benchmark", null);
while (state.keepRunning()) {
state.pauseTiming();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
final DisplayListCanvas c = node.start(1200, 200);
@@ -360,7 +316,7 @@
final RenderNode node = RenderNode.create("benchmark", null);
while (state.keepRunning()) {
state.pauseTiming();
- final CharSequence text = generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
final DisplayListCanvas c = node.start(1200, 200);
@@ -378,7 +334,7 @@
while (state.keepRunning()) {
state.pauseTiming();
final MeasuredText text = new MeasuredText.Builder(
- generateRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT).build();
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT).build();
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
final DisplayListCanvas c = node.start(1200, 200);
@@ -395,7 +351,7 @@
while (state.keepRunning()) {
state.pauseTiming();
final MeasuredText text = new MeasuredText.Builder(
- generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT).build();
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT).build();
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
final DisplayListCanvas c = node.start(1200, 200);
@@ -412,7 +368,7 @@
while (state.keepRunning()) {
state.pauseTiming();
final MeasuredText text = new MeasuredText.Builder(
- generateRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT).build();
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT).build();
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
final DisplayListCanvas c = node.start(1200, 200);
@@ -430,7 +386,7 @@
while (state.keepRunning()) {
state.pauseTiming();
final MeasuredText text = new MeasuredText.Builder(
- generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT).build();
+ mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT).build();
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
final DisplayListCanvas c = node.start(1200, 200);
diff --git a/apct-tests/perftests/core/src/android/text/TextPerfUtils.java b/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
new file mode 100644
index 0000000..dccb34b
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
@@ -0,0 +1,93 @@
+/*
+ * 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.text;
+
+import static android.text.TextDirectionHeuristics.LTR;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import android.content.res.ColorStateList;
+import android.graphics.Canvas;
+import android.graphics.Typeface;
+import android.text.Layout;
+import android.text.style.TextAppearanceSpan;
+import android.view.DisplayListCanvas;
+import android.view.RenderNode;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.CharBuffer;
+import java.util.Random;
+
+public class TextPerfUtils {
+
+ private static final int PARA_LENGTH = 500; // Number of characters in a paragraph.
+
+ private Random mRandom = new Random(0);
+
+ private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ private static final int ALPHABET_LENGTH = ALPHABET.length();
+
+ private static final ColorStateList TEXT_COLOR = ColorStateList.valueOf(0x00000000);
+ private static final String[] FAMILIES = { "sans-serif", "serif", "monospace" };
+ private static final int[] STYLES = {
+ Typeface.NORMAL, Typeface.BOLD, Typeface.ITALIC, Typeface.BOLD_ITALIC
+ };
+
+ private final char[] mBuffer = new char[PARA_LENGTH];
+
+ public void resetRandom(long seed) {
+ mRandom = new Random(seed);
+ }
+
+ public CharSequence nextRandomParagraph(int wordLen, boolean applyRandomStyle) {
+ for (int i = 0; i < PARA_LENGTH; i++) {
+ if (i % (wordLen + 1) == wordLen) {
+ mBuffer[i] = ' ';
+ } else {
+ mBuffer[i] = ALPHABET.charAt(mRandom.nextInt(ALPHABET_LENGTH));
+ }
+ }
+
+ CharSequence cs = CharBuffer.wrap(mBuffer);
+ if (!applyRandomStyle) {
+ return cs;
+ }
+
+ SpannableStringBuilder ssb = new SpannableStringBuilder(cs);
+ for (int i = 0; i < ssb.length(); i += wordLen) {
+ final int spanStart = i;
+ final int spanEnd = (i + wordLen) > ssb.length() ? ssb.length() : i + wordLen;
+
+ final TextAppearanceSpan span = new TextAppearanceSpan(
+ FAMILIES[mRandom.nextInt(FAMILIES.length)],
+ STYLES[mRandom.nextInt(STYLES.length)],
+ 24 + mRandom.nextInt(32), // text size. min 24 max 56
+ TEXT_COLOR, TEXT_COLOR);
+
+ ssb.setSpan(span, spanStart, spanEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ }
+ return ssb;
+ }
+}
diff --git a/api/current.txt b/api/current.txt
index 1cea3d6..bbe3c49 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -73,7 +73,6 @@
field public static final java.lang.String DUMP = "android.permission.DUMP";
field public static final java.lang.String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST";
- field public static final java.lang.String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
@@ -95,6 +94,7 @@
field public static final java.lang.String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
field public static final java.lang.String NFC = "android.permission.NFC";
+ field public static final java.lang.String NFC_TRANSACTION_EVENT = "android.permission.NFC_TRANSACTION_EVENT";
field public static final java.lang.String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
field public static final deprecated java.lang.String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
field public static final java.lang.String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
@@ -969,7 +969,9 @@
field public static final int orderingFromXml = 16843239; // 0x10101e7
field public static final int orientation = 16842948; // 0x10100c4
field public static final int outAnimation = 16843128; // 0x1010178
+ field public static final int outlineAmbientShadowColor = 16844162; // 0x1010582
field public static final int outlineProvider = 16843960; // 0x10104b8
+ field public static final int outlineSpotShadowColor = 16844161; // 0x1010581
field public static final int overScrollFooter = 16843459; // 0x10102c3
field public static final int overScrollHeader = 16843458; // 0x10102c2
field public static final int overScrollMode = 16843457; // 0x10102c1
@@ -1903,6 +1905,7 @@
field public static final int decelerate_cubic = 17563651; // 0x10c0003
field public static final int decelerate_quad = 17563649; // 0x10c0001
field public static final int decelerate_quint = 17563653; // 0x10c0005
+ field public static final int fast_out_extra_slow_in = 17563674; // 0x10c001a
field public static final int fast_out_linear_in = 17563663; // 0x10c000f
field public static final int fast_out_slow_in = 17563661; // 0x10c000d
field public static final int linear = 17563659; // 0x10c000b
@@ -6084,16 +6087,16 @@
method public android.os.ParcelFileDescriptor executeShellCommand(java.lang.String);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
- method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+ method public android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
method public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats();
method public android.view.WindowContentFrameStats getWindowContentFrameStats(int);
method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
method public boolean injectInputEvent(android.view.InputEvent, boolean);
- method public final boolean performGlobalAction(int);
+ method public boolean performGlobalAction(int);
method public void setOnAccessibilityEventListener(android.app.UiAutomation.OnAccessibilityEventListener);
method public boolean setRotation(int);
method public void setRunAsMonkey(boolean);
- method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
+ method public void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
method public android.graphics.Bitmap takeScreenshot();
method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException;
field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1
@@ -6390,7 +6393,7 @@
method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
method public void addUserRestriction(android.content.ComponentName, java.lang.String);
method public boolean bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle);
- method public boolean clearApplicationUserData(android.content.ComponentName, java.lang.String, java.util.concurrent.Executor, android.app.admin.DevicePolicyManager.OnClearApplicationUserDataListener);
+ method public void clearApplicationUserData(android.content.ComponentName, java.lang.String, java.util.concurrent.Executor, android.app.admin.DevicePolicyManager.OnClearApplicationUserDataListener);
method public void clearCrossProfileIntentFilters(android.content.ComponentName);
method public deprecated void clearDeviceOwnerApp(java.lang.String);
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
@@ -6497,7 +6500,7 @@
method public boolean isUsingUnifiedPassword(android.content.ComponentName);
method public void lockNow();
method public void lockNow(int);
- method public boolean logoutUser(android.content.ComponentName);
+ method public int logoutUser(android.content.ComponentName);
method public void reboot(android.content.ComponentName);
method public void removeActiveAdmin(android.content.ComponentName);
method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -6582,8 +6585,8 @@
method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
method public void setUserIcon(android.content.ComponentName, android.graphics.Bitmap);
- method public boolean startUserInBackground(android.content.ComponentName, android.os.UserHandle);
- method public boolean stopUser(android.content.ComponentName, android.os.UserHandle);
+ method public int startUserInBackground(android.content.ComponentName, android.os.UserHandle);
+ method public int stopUser(android.content.ComponentName, android.os.UserHandle);
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
method public void transferOwnership(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
method public void uninstallAllUserCaCerts(android.content.ComponentName);
@@ -6697,6 +6700,11 @@
field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
field public static final int SKIP_SETUP_WIZARD = 1; // 0x1
+ field public static final int USER_OPERATION_ERROR_CURRENT_USER = 4; // 0x4
+ field public static final int USER_OPERATION_ERROR_MANAGED_PROFILE = 2; // 0x2
+ field public static final int USER_OPERATION_ERROR_MAX_RUNNING_USERS = 3; // 0x3
+ field public static final int USER_OPERATION_ERROR_UNKNOWN = 1; // 0x1
+ field public static final int USER_OPERATION_SUCCESS = 0; // 0x0
field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
}
@@ -6723,20 +6731,46 @@
public class SecurityLog {
ctor public SecurityLog();
+ field public static final int LEVEL_ERROR = 3; // 0x3
+ field public static final int LEVEL_INFO = 1; // 0x1
+ field public static final int LEVEL_WARNING = 2; // 0x2
field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+ field public static final int TAG_CERT_AUTHORITY_INSTALLED = 210029; // 0x3346d
+ field public static final int TAG_CERT_AUTHORITY_REMOVED = 210030; // 0x3346e
+ field public static final int TAG_KEYGUARD_DISABLED_FEATURES_SET = 210021; // 0x33465
field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
+ field public static final int TAG_KEY_DESTRUCTION = 210026; // 0x3346a
+ field public static final int TAG_KEY_GENERATED = 210024; // 0x33468
+ field public static final int TAG_KEY_IMPORT = 210025; // 0x33469
+ field public static final int TAG_LOGGING_STARTED = 210011; // 0x3345b
+ field public static final int TAG_LOGGING_STOPPED = 210012; // 0x3345c
+ field public static final int TAG_LOG_BUFFER_SIZE_CRITICAL = 210015; // 0x3345f
+ field public static final int TAG_MAX_PASSWORD_ATTEMPTS_SET = 210020; // 0x33464
+ field public static final int TAG_MAX_SCREEN_LOCK_TIMEOUT_SET = 210019; // 0x33463
+ field public static final int TAG_MEDIA_MOUNT = 210013; // 0x3345d
+ field public static final int TAG_MEDIA_UNMOUNT = 210014; // 0x3345e
+ field public static final int TAG_OS_SHUTDOWN = 210010; // 0x3345a
+ field public static final int TAG_OS_STARTUP = 210009; // 0x33459
+ field public static final int TAG_PASSWORD_COMPLEXITY_SET = 210017; // 0x33461
+ field public static final int TAG_PASSWORD_EXPIRATION_SET = 210016; // 0x33460
+ field public static final int TAG_PASSWORD_HISTORY_LENGTH_SET = 210018; // 0x33462
+ field public static final int TAG_REMOTE_LOCK = 210022; // 0x33466
field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
+ field public static final int TAG_USER_RESTRICTION_ADDED = 210027; // 0x3346b
+ field public static final int TAG_USER_RESTRICTION_REMOVED = 210028; // 0x3346c
+ field public static final int TAG_WIPE_FAILURE = 210023; // 0x33467
}
public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
method public int describeContents();
method public java.lang.Object getData();
method public long getId();
+ method public int getLogLevel();
method public int getTag();
method public long getTimeNanos();
method public void writeToParcel(android.os.Parcel, int);
@@ -6759,9 +6793,11 @@
method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
method public static android.app.admin.SystemUpdatePolicy createWindowedInstallPolicy(int, int);
method public int describeContents();
+ method public java.util.List<android.util.Pair<java.lang.Integer, java.lang.Integer>> getFreezePeriods();
method public int getInstallWindowEnd();
method public int getInstallWindowStart();
method public int getPolicyType();
+ method public android.app.admin.SystemUpdatePolicy setFreezePeriods(java.util.List<android.util.Pair<java.lang.Integer, java.lang.Integer>>);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.admin.SystemUpdatePolicy> CREATOR;
field public static final int TYPE_INSTALL_AUTOMATIC = 1; // 0x1
@@ -6769,6 +6805,18 @@
field public static final int TYPE_POSTPONE = 3; // 0x3
}
+ public static final class SystemUpdatePolicy.ValidationFailedException extends java.lang.IllegalArgumentException implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getErrorCode();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.SystemUpdatePolicy.ValidationFailedException> CREATOR;
+ field public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE = 5; // 0x5
+ field public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG = 4; // 0x4
+ field public static final int ERROR_DUPLICATE_OR_OVERLAP = 1; // 0x1
+ field public static final int ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE = 3; // 0x3
+ field public static final int ERROR_NEW_FREEZE_PERIOD_TOO_LONG = 2; // 0x2
+ }
+
}
package android.app.assist {
@@ -7120,6 +7168,8 @@
method public android.net.Uri getUri();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.slice.Slice> CREATOR;
+ field public static final java.lang.String EXTRA_RANGE_VALUE = "android.app.slice.extra.RANGE_VALUE";
+ field public static final deprecated java.lang.String EXTRA_SLIDER_VALUE = "android.app.slice.extra.SLIDER_VALUE";
field public static final java.lang.String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE";
field public static final java.lang.String HINT_ACTIONS = "actions";
field public static final java.lang.String HINT_CALLER_NEEDED = "caller_needed";
@@ -7127,7 +7177,6 @@
field public static final java.lang.String HINT_LARGE = "large";
field public static final java.lang.String HINT_LIST = "list";
field public static final java.lang.String HINT_LIST_ITEM = "list_item";
- field public static final java.lang.String HINT_MAX = "max";
field public static final java.lang.String HINT_NO_TINT = "no_tint";
field public static final java.lang.String HINT_PARTIAL = "partial";
field public static final java.lang.String HINT_SEE_MORE = "see_more";
@@ -7137,11 +7186,14 @@
field public static final java.lang.String HINT_TITLE = "title";
field public static final java.lang.String SUBTYPE_COLOR = "color";
field public static final java.lang.String SUBTYPE_CONTENT_DESCRIPTION = "content_description";
+ field public static final java.lang.String SUBTYPE_MAX = "max";
field public static final java.lang.String SUBTYPE_MESSAGE = "message";
field public static final java.lang.String SUBTYPE_PRIORITY = "priority";
- field public static final java.lang.String SUBTYPE_SLIDER = "slider";
+ field public static final java.lang.String SUBTYPE_RANGE = "range";
+ field public static final deprecated java.lang.String SUBTYPE_SLIDER = "slider";
field public static final java.lang.String SUBTYPE_SOURCE = "source";
field public static final java.lang.String SUBTYPE_TOGGLE = "toggle";
+ field public static final java.lang.String SUBTYPE_VALUE = "value";
}
public static class Slice.Builder {
@@ -7200,6 +7252,7 @@
method public android.app.slice.Slice bindSlice(android.content.Intent, java.util.List<android.app.slice.SliceSpec>);
method public java.util.List<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri);
method public java.util.Collection<android.net.Uri> getSliceDescendants(android.net.Uri);
+ method public android.net.Uri mapIntentToUri(android.content.Intent);
method public void pinSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
method public deprecated void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>);
method public deprecated void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>, java.util.concurrent.Executor);
@@ -10000,6 +10053,7 @@
field public static final int FLAG_ACTIVITY_FORWARD_RESULT = 33554432; // 0x2000000
field public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 1048576; // 0x100000
field public static final int FLAG_ACTIVITY_LAUNCH_ADJACENT = 4096; // 0x1000
+ field public static final int FLAG_ACTIVITY_MATCH_EXTERNAL = 2048; // 0x800
field public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 134217728; // 0x8000000
field public static final int FLAG_ACTIVITY_NEW_DOCUMENT = 524288; // 0x80000
field public static final int FLAG_ACTIVITY_NEW_TASK = 268435456; // 0x10000000
@@ -11562,15 +11616,15 @@
public final class AssetManager implements java.lang.AutoCloseable {
method public void close();
- method public java.lang.String[] getLocales();
- method public java.lang.String[] list(java.lang.String) throws java.io.IOException;
- method public java.io.InputStream open(java.lang.String) throws java.io.IOException;
- method public java.io.InputStream open(java.lang.String, int) throws java.io.IOException;
- method public android.content.res.AssetFileDescriptor openFd(java.lang.String) throws java.io.IOException;
- method public android.content.res.AssetFileDescriptor openNonAssetFd(java.lang.String) throws java.io.IOException;
- method public android.content.res.AssetFileDescriptor openNonAssetFd(int, java.lang.String) throws java.io.IOException;
- method public android.content.res.XmlResourceParser openXmlResourceParser(java.lang.String) throws java.io.IOException;
- method public android.content.res.XmlResourceParser openXmlResourceParser(int, java.lang.String) throws java.io.IOException;
+ method public final java.lang.String[] getLocales();
+ method public final java.lang.String[] list(java.lang.String) throws java.io.IOException;
+ method public final java.io.InputStream open(java.lang.String) throws java.io.IOException;
+ method public final java.io.InputStream open(java.lang.String, int) throws java.io.IOException;
+ method public final android.content.res.AssetFileDescriptor openFd(java.lang.String) throws java.io.IOException;
+ method public final android.content.res.AssetFileDescriptor openNonAssetFd(java.lang.String) throws java.io.IOException;
+ method public final android.content.res.AssetFileDescriptor openNonAssetFd(int, java.lang.String) throws java.io.IOException;
+ method public final android.content.res.XmlResourceParser openXmlResourceParser(java.lang.String) throws java.io.IOException;
+ method public final android.content.res.XmlResourceParser openXmlResourceParser(int, java.lang.String) throws java.io.IOException;
field public static final int ACCESS_BUFFER = 3; // 0x3
field public static final int ACCESS_RANDOM = 1; // 0x1
field public static final int ACCESS_STREAMING = 2; // 0x2
@@ -11578,15 +11632,9 @@
}
public final class AssetManager.AssetInputStream extends java.io.InputStream {
- method public final int available() throws java.io.IOException;
- method public final void close() throws java.io.IOException;
- method public final void mark(int);
- method public final boolean markSupported();
- method public final int read() throws java.io.IOException;
- method public final int read(byte[]) throws java.io.IOException;
- method public final int read(byte[], int, int) throws java.io.IOException;
- method public final void reset() throws java.io.IOException;
- method public final long skip(long) throws java.io.IOException;
+ method public void mark(int);
+ method public int read() throws java.io.IOException;
+ method public void reset() throws java.io.IOException;
}
public class ColorStateList implements android.os.Parcelable {
@@ -12348,7 +12396,7 @@
method public java.util.List<android.util.Pair<java.lang.String, java.lang.String>> getAttachedDbs();
method public long getMaximumSize();
method public long getPageSize();
- method public final java.lang.String getPath();
+ method public java.lang.String getPath();
method public deprecated java.util.Map<java.lang.String, java.lang.String> getSyncedTables();
method public int getVersion();
method public boolean inTransaction();
@@ -13005,29 +13053,29 @@
method public void eraseColor(int);
method public android.graphics.Bitmap extractAlpha();
method public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]);
- method public final int getAllocationByteCount();
- method public final int getByteCount();
- method public final android.graphics.ColorSpace getColorSpace();
- method public final android.graphics.Bitmap.Config getConfig();
+ method public int getAllocationByteCount();
+ method public int getByteCount();
+ method public android.graphics.ColorSpace getColorSpace();
+ method public android.graphics.Bitmap.Config getConfig();
method public int getDensity();
method public int getGenerationId();
- method public final int getHeight();
+ method public int getHeight();
method public byte[] getNinePatchChunk();
method public int getPixel(int, int);
method public void getPixels(int[], int, int, int, int, int, int);
- method public final int getRowBytes();
+ method public int getRowBytes();
method public int getScaledHeight(android.graphics.Canvas);
method public int getScaledHeight(android.util.DisplayMetrics);
method public int getScaledHeight(int);
method public int getScaledWidth(android.graphics.Canvas);
method public int getScaledWidth(android.util.DisplayMetrics);
method public int getScaledWidth(int);
- method public final int getWidth();
- method public final boolean hasAlpha();
- method public final boolean hasMipMap();
- method public final boolean isMutable();
- method public final boolean isPremultiplied();
- method public final boolean isRecycled();
+ method public int getWidth();
+ method public boolean hasAlpha();
+ method public boolean hasMipMap();
+ method public boolean isMutable();
+ method public boolean isPremultiplied();
+ method public boolean isRecycled();
method public void prepareToDraw();
method public void reconfigure(int, int, android.graphics.Bitmap.Config);
method public void recycle();
@@ -13035,11 +13083,11 @@
method public void setConfig(android.graphics.Bitmap.Config);
method public void setDensity(int);
method public void setHasAlpha(boolean);
- method public final void setHasMipMap(boolean);
+ method public void setHasMipMap(boolean);
method public void setHeight(int);
method public void setPixel(int, int, int);
method public void setPixels(int[], int, int, int, int, int, int);
- method public final void setPremultiplied(boolean);
+ method public void setPremultiplied(boolean);
method public void setWidth(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.graphics.Bitmap> CREATOR;
@@ -13111,7 +13159,7 @@
method public android.graphics.Bitmap decodeRegion(android.graphics.Rect, android.graphics.BitmapFactory.Options);
method public int getHeight();
method public int getWidth();
- method public final boolean isRecycled();
+ method public boolean isRecycled();
method public static android.graphics.BitmapRegionDecoder newInstance(byte[], int, int, boolean) throws java.io.IOException;
method public static android.graphics.BitmapRegionDecoder newInstance(java.io.FileDescriptor, boolean) throws java.io.IOException;
method public static android.graphics.BitmapRegionDecoder newInstance(java.io.InputStream, boolean) throws java.io.IOException;
@@ -13570,6 +13618,7 @@
public static class ImageDecoder.ImageInfo {
method public java.lang.String getMimeType();
method public android.util.Size getSize();
+ method public boolean isAnimated();
}
public static class ImageDecoder.IncompleteException extends java.io.IOException {
@@ -14170,22 +14219,22 @@
ctor public Rect();
ctor public Rect(int, int, int, int);
ctor public Rect(android.graphics.Rect);
- method public final int centerX();
- method public final int centerY();
+ method public int centerX();
+ method public int centerY();
method public boolean contains(int, int);
method public boolean contains(int, int, int, int);
method public boolean contains(android.graphics.Rect);
method public int describeContents();
- method public final float exactCenterX();
- method public final float exactCenterY();
+ method public float exactCenterX();
+ method public float exactCenterY();
method public java.lang.String flattenToString();
- method public final int height();
+ method public int height();
method public void inset(int, int);
method public boolean intersect(int, int, int, int);
method public boolean intersect(android.graphics.Rect);
method public boolean intersects(int, int, int, int);
method public static boolean intersects(android.graphics.Rect, android.graphics.Rect);
- method public final boolean isEmpty();
+ method public boolean isEmpty();
method public void offset(int, int);
method public void offsetTo(int, int);
method public void readFromParcel(android.os.Parcel);
@@ -14199,7 +14248,7 @@
method public void union(int, int, int, int);
method public void union(android.graphics.Rect);
method public void union(int, int);
- method public final int width();
+ method public int width();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.graphics.Rect> CREATOR;
field public int bottom;
@@ -14440,6 +14489,22 @@
method public void onAnimationStart(android.graphics.drawable.Drawable);
}
+ public class AnimatedImageDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable2 {
+ ctor public AnimatedImageDrawable();
+ method public void clearAnimationCallbacks();
+ method public void draw(android.graphics.Canvas);
+ method public int getOpacity();
+ method public boolean isRunning();
+ method public void registerAnimationCallback(android.graphics.drawable.Animatable2.AnimationCallback);
+ method public void setAlpha(int);
+ method public void setColorFilter(android.graphics.ColorFilter);
+ method public void setLoopCount(int);
+ method public void start();
+ method public void stop();
+ method public boolean unregisterAnimationCallback(android.graphics.drawable.Animatable2.AnimationCallback);
+ field public static final int LOOP_INFINITE = -1; // 0xffffffff
+ }
+
public class AnimatedStateListDrawable extends android.graphics.drawable.StateListDrawable {
ctor public AnimatedStateListDrawable();
method public void addState(int[], android.graphics.drawable.Drawable, int);
@@ -15752,9 +15817,7 @@
}
public static final class CameraCharacteristics.Key<T> {
- method public final boolean equals(java.lang.Object);
method public java.lang.String getName();
- method public final int hashCode();
}
public abstract class CameraConstrainedHighSpeedCaptureSession extends android.hardware.camera2.CameraCaptureSession {
@@ -16116,9 +16179,7 @@
}
public static final class CaptureRequest.Key<T> {
- method public final boolean equals(java.lang.Object);
method public java.lang.String getName();
- method public final int hashCode();
}
public class CaptureResult extends android.hardware.camera2.CameraMetadata {
@@ -16211,9 +16272,7 @@
}
public static final class CaptureResult.Key<T> {
- method public final boolean equals(java.lang.Object);
method public java.lang.String getName();
- method public final int hashCode();
}
public final class DngCreator implements java.lang.AutoCloseable {
@@ -16307,7 +16366,7 @@
method public void addSurface(android.view.Surface);
method public int describeContents();
method public void enableSurfaceSharing();
- method public static int getMaxSharedSurfaceCount();
+ method public int getMaxSharedSurfaceCount();
method public android.view.Surface getSurface();
method public int getSurfaceGroupId();
method public java.util.List<android.view.Surface> getSurfaces();
@@ -16325,7 +16384,7 @@
method public float getComponent(int);
method public float getGreenEven();
method public float getGreenOdd();
- method public final float getRed();
+ method public float getRed();
field public static final int BLUE = 3; // 0x3
field public static final int COUNT = 4; // 0x4
field public static final int GREEN_EVEN = 1; // 0x1
@@ -16353,16 +16412,16 @@
method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRangesFor(android.util.Size);
method public android.util.Size[] getHighSpeedVideoSizes();
method public android.util.Size[] getHighSpeedVideoSizesFor(android.util.Range<java.lang.Integer>);
- method public final int[] getInputFormats();
+ method public int[] getInputFormats();
method public android.util.Size[] getInputSizes(int);
- method public final int[] getOutputFormats();
+ method public int[] getOutputFormats();
method public long getOutputMinFrameDuration(int, android.util.Size);
method public <T> long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
method public <T> android.util.Size[] getOutputSizes(java.lang.Class<T>);
method public android.util.Size[] getOutputSizes(int);
method public long getOutputStallDuration(int, android.util.Size);
method public <T> long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
- method public final int[] getValidOutputFormatsForInput(int);
+ method public int[] getValidOutputFormatsForInput(int);
method public boolean isOutputSupportedFor(int);
method public static <T> boolean isOutputSupportedFor(java.lang.Class<T>);
method public boolean isOutputSupportedFor(android.view.Surface);
@@ -16670,12 +16729,12 @@
public final class UCharacter implements android.icu.lang.UCharacterEnums.ECharacterCategory android.icu.lang.UCharacterEnums.ECharacterDirection {
method public static int charCount(int);
- method public static final int codePointAt(java.lang.CharSequence, int);
- method public static final int codePointAt(char[], int);
- method public static final int codePointAt(char[], int, int);
- method public static final int codePointBefore(java.lang.CharSequence, int);
- method public static final int codePointBefore(char[], int);
- method public static final int codePointBefore(char[], int, int);
+ method public static int codePointAt(java.lang.CharSequence, int);
+ method public static int codePointAt(char[], int);
+ method public static int codePointAt(char[], int, int);
+ method public static int codePointBefore(java.lang.CharSequence, int);
+ method public static int codePointBefore(char[], int);
+ method public static int codePointBefore(char[], int, int);
method public static int codePointCount(java.lang.CharSequence, int, int);
method public static int codePointCount(char[], int, int);
method public static int digit(int, int);
@@ -16683,7 +16742,7 @@
method public static int foldCase(int, boolean);
method public static java.lang.String foldCase(java.lang.String, boolean);
method public static int foldCase(int, int);
- method public static final java.lang.String foldCase(java.lang.String, int);
+ method public static java.lang.String foldCase(java.lang.String, int);
method public static char forDigit(int, int);
method public static android.icu.util.VersionInfo getAge(int);
method public static int getBidiPairedBracket(int);
@@ -16735,8 +16794,8 @@
method public static boolean isPrintable(int);
method public static boolean isSpaceChar(int);
method public static boolean isSupplementary(int);
- method public static final boolean isSupplementaryCodePoint(int);
- method public static final boolean isSurrogatePair(char, char);
+ method public static boolean isSupplementaryCodePoint(int);
+ method public static boolean isSurrogatePair(char, char);
method public static boolean isTitleCase(int);
method public static boolean isUAlphabetic(int);
method public static boolean isULowercase(int);
@@ -16745,13 +16804,13 @@
method public static boolean isUnicodeIdentifierPart(int);
method public static boolean isUnicodeIdentifierStart(int);
method public static boolean isUpperCase(int);
- method public static final boolean isValidCodePoint(int);
+ method public static boolean isValidCodePoint(int);
method public static boolean isWhitespace(int);
method public static int offsetByCodePoints(java.lang.CharSequence, int, int);
method public static int offsetByCodePoints(char[], int, int, int, int);
- method public static final int toChars(int, char[], int);
- method public static final char[] toChars(int);
- method public static final int toCodePoint(char, char);
+ method public static int toChars(int, char[], int);
+ method public static char[] toChars(int);
+ method public static int toCodePoint(char, char);
method public static int toLowerCase(int);
method public static java.lang.String toLowerCase(java.lang.String);
method public static java.lang.String toLowerCase(java.util.Locale, java.lang.String);
@@ -17041,7 +17100,7 @@
}
public static final class UCharacter.UnicodeBlock extends java.lang.Character.Subset {
- method public static final android.icu.lang.UCharacter.UnicodeBlock forName(java.lang.String);
+ method public static android.icu.lang.UCharacter.UnicodeBlock forName(java.lang.String);
method public int getID();
method public static android.icu.lang.UCharacter.UnicodeBlock getInstance(int);
method public static android.icu.lang.UCharacter.UnicodeBlock of(int);
@@ -17848,20 +17907,20 @@
}
public final class UScript {
- method public static final boolean breaksBetweenLetters(int);
- method public static final int[] getCode(java.util.Locale);
- method public static final int[] getCode(android.icu.util.ULocale);
- method public static final int[] getCode(java.lang.String);
- method public static final int getCodeFromName(java.lang.String);
- method public static final java.lang.String getName(int);
- method public static final java.lang.String getSampleString(int);
- method public static final int getScript(int);
- method public static final int getScriptExtensions(int, java.util.BitSet);
- method public static final java.lang.String getShortName(int);
- method public static final android.icu.lang.UScript.ScriptUsage getUsage(int);
- method public static final boolean hasScript(int, int);
- method public static final boolean isCased(int);
- method public static final boolean isRightToLeft(int);
+ method public static boolean breaksBetweenLetters(int);
+ method public static int[] getCode(java.util.Locale);
+ method public static int[] getCode(android.icu.util.ULocale);
+ method public static int[] getCode(java.lang.String);
+ method public static int getCodeFromName(java.lang.String);
+ method public static java.lang.String getName(int);
+ method public static java.lang.String getSampleString(int);
+ method public static int getScript(int);
+ method public static int getScriptExtensions(int, java.util.BitSet);
+ method public static java.lang.String getShortName(int);
+ method public static android.icu.lang.UScript.ScriptUsage getUsage(int);
+ method public static boolean hasScript(int, int);
+ method public static boolean isCased(int);
+ method public static boolean isRightToLeft(int);
field public static final int ADLAM = 167; // 0xa7
field public static final int AFAKA = 147; // 0x93
field public static final int AHOM = 161; // 0xa1
@@ -18276,14 +18335,14 @@
method public deprecated int hashCode();
method public int next();
method public int previous();
- method public static final int primaryOrder(int);
+ method public static int primaryOrder(int);
method public void reset();
- method public static final int secondaryOrder(int);
+ method public static int secondaryOrder(int);
method public void setOffset(int);
method public void setText(java.lang.String);
method public void setText(android.icu.text.UCharacterIterator);
method public void setText(java.text.CharacterIterator);
- method public static final int tertiaryOrder(int);
+ method public static int tertiaryOrder(int);
field public static final int IGNORABLE = 0; // 0x0
field public static final int NULLORDER = -1; // 0xffffffff
}
@@ -19510,7 +19569,7 @@
method public boolean isUpperCaseFirst();
method public void setAlternateHandlingDefault();
method public void setAlternateHandlingShifted(boolean);
- method public final void setCaseFirstDefault();
+ method public void setCaseFirstDefault();
method public void setCaseLevel(boolean);
method public void setCaseLevelDefault();
method public void setDecompositionDefault();
@@ -20483,11 +20542,11 @@
public final class LocaleData {
method public static android.icu.util.VersionInfo getCLDRVersion();
method public java.lang.String getDelimiter(int);
- method public static final android.icu.util.LocaleData getInstance(android.icu.util.ULocale);
- method public static final android.icu.util.LocaleData getInstance();
- method public static final android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale);
+ method public static android.icu.util.LocaleData getInstance(android.icu.util.ULocale);
+ method public static android.icu.util.LocaleData getInstance();
+ method public static android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale);
method public boolean getNoSubstitute();
- method public static final android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale);
+ method public static android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale);
method public void setNoSubstitute(boolean);
field public static final int ALT_QUOTATION_END = 3; // 0x3
field public static final int ALT_QUOTATION_START = 2; // 0x2
@@ -22761,40 +22820,40 @@
method public static android.media.MediaCodec createByCodecName(java.lang.String) throws java.io.IOException;
method public static android.media.MediaCodec createDecoderByType(java.lang.String) throws java.io.IOException;
method public static android.media.MediaCodec createEncoderByType(java.lang.String) throws java.io.IOException;
- method public final android.view.Surface createInputSurface();
+ method public android.view.Surface createInputSurface();
method public static android.view.Surface createPersistentInputSurface();
- method public final int dequeueInputBuffer(long);
- method public final int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long);
+ method public int dequeueInputBuffer(long);
+ method public int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long);
method protected void finalize();
- method public final void flush();
+ method public void flush();
method public android.media.MediaCodecInfo getCodecInfo();
method public java.nio.ByteBuffer getInputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getInputBuffers();
- method public final android.media.MediaFormat getInputFormat();
+ method public android.media.MediaFormat getInputFormat();
method public android.media.Image getInputImage(int);
method public android.os.PersistableBundle getMetrics();
- method public final java.lang.String getName();
+ method public java.lang.String getName();
method public java.nio.ByteBuffer getOutputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
- method public final android.media.MediaFormat getOutputFormat();
- method public final android.media.MediaFormat getOutputFormat(int);
+ method public android.media.MediaFormat getOutputFormat();
+ method public android.media.MediaFormat getOutputFormat(int);
method public android.media.Image getOutputImage(int);
- method public final void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException;
- method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException;
- method public final void release();
- method public final void releaseOutputBuffer(int, boolean);
- method public final void releaseOutputBuffer(int, long);
- method public final void reset();
+ method public void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException;
+ method public void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException;
+ method public void release();
+ method public void releaseOutputBuffer(int, boolean);
+ method public void releaseOutputBuffer(int, long);
+ method public void reset();
method public void setCallback(android.media.MediaCodec.Callback, android.os.Handler);
method public void setCallback(android.media.MediaCodec.Callback);
method public void setInputSurface(android.view.Surface);
method public void setOnFrameRenderedListener(android.media.MediaCodec.OnFrameRenderedListener, android.os.Handler);
method public void setOutputSurface(android.view.Surface);
- method public final void setParameters(android.os.Bundle);
- method public final void setVideoScalingMode(int);
- method public final void signalEndOfInputStream();
- method public final void start();
- method public final void stop();
+ method public void setParameters(android.os.Bundle);
+ method public void setVideoScalingMode(int);
+ method public void signalEndOfInputStream();
+ method public void start();
+ method public void stop();
field public static final int BUFFER_FLAG_CODEC_CONFIG = 2; // 0x2
field public static final int BUFFER_FLAG_END_OF_STREAM = 4; // 0x4
field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
@@ -22888,10 +22947,10 @@
}
public final class MediaCodecInfo {
- method public final android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String);
- method public final java.lang.String getName();
- method public final java.lang.String[] getSupportedTypes();
- method public final boolean isEncoder();
+ method public android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String);
+ method public java.lang.String getName();
+ method public java.lang.String[] getSupportedTypes();
+ method public boolean isEncoder();
}
public static final class MediaCodecInfo.AudioCapabilities {
@@ -22911,9 +22970,9 @@
method public int getMaxSupportedInstances();
method public java.lang.String getMimeType();
method public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities();
- method public final boolean isFeatureRequired(java.lang.String);
- method public final boolean isFeatureSupported(java.lang.String);
- method public final boolean isFormatSupported(android.media.MediaFormat);
+ method public boolean isFeatureRequired(java.lang.String);
+ method public boolean isFeatureSupported(java.lang.String);
+ method public boolean isFormatSupported(android.media.MediaFormat);
field public static final deprecated int COLOR_Format12bitRGB444 = 3; // 0x3
field public static final deprecated int COLOR_Format16bitARGB1555 = 5; // 0x5
field public static final deprecated int COLOR_Format16bitARGB4444 = 4; // 0x4
@@ -23171,11 +23230,11 @@
public final class MediaCodecList {
ctor public MediaCodecList(int);
- method public final java.lang.String findDecoderForFormat(android.media.MediaFormat);
- method public final java.lang.String findEncoderForFormat(android.media.MediaFormat);
- method public static final deprecated int getCodecCount();
- method public static final deprecated android.media.MediaCodecInfo getCodecInfoAt(int);
- method public final android.media.MediaCodecInfo[] getCodecInfos();
+ method public java.lang.String findDecoderForFormat(android.media.MediaFormat);
+ method public java.lang.String findEncoderForFormat(android.media.MediaFormat);
+ method public static deprecated int getCodecCount();
+ method public static deprecated android.media.MediaCodecInfo getCodecInfoAt(int);
+ method public android.media.MediaCodecInfo[] getCodecInfos();
field public static final int ALL_CODECS = 1; // 0x1
field public static final int REGULAR_CODECS = 0; // 0x0
}
@@ -23183,10 +23242,10 @@
public final class MediaCrypto {
ctor public MediaCrypto(java.util.UUID, byte[]) throws android.media.MediaCryptoException;
method protected void finalize();
- method public static final boolean isCryptoSchemeSupported(java.util.UUID);
- method public final void release();
- method public final boolean requiresSecureDecoderComponent(java.lang.String);
- method public final void setMediaDrmSession(byte[]) throws android.media.MediaCryptoException;
+ method public static boolean isCryptoSchemeSupported(java.util.UUID);
+ method public void release();
+ method public boolean requiresSecureDecoderComponent(java.lang.String);
+ method public void setMediaDrmSession(byte[]) throws android.media.MediaCryptoException;
}
public final class MediaCryptoException extends java.lang.Exception {
@@ -23202,10 +23261,10 @@
public final class MediaDescrambler implements java.lang.AutoCloseable {
ctor public MediaDescrambler(int) throws android.media.MediaCasException.UnsupportedCasException;
method public void close();
- method public final int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo);
+ method public int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo);
method protected void finalize();
- method public final boolean requiresSecureDecoderComponent(java.lang.String);
- method public final void setMediaCasSession(android.media.MediaCas.Session);
+ method public boolean requiresSecureDecoderComponent(java.lang.String);
+ method public void setMediaCasSession(android.media.MediaCas.Session);
}
public class MediaDescription implements android.os.Parcelable {
@@ -23258,18 +23317,21 @@
method public java.lang.String getPropertyString(java.lang.String);
method public android.media.MediaDrm.ProvisionRequest getProvisionRequest();
method public byte[] getSecureStop(byte[]);
+ method public java.util.List<byte[]> getSecureStopIds();
method public java.util.List<byte[]> getSecureStops();
method public int getSecurityLevel(byte[]);
- method public static final boolean isCryptoSchemeSupported(java.util.UUID);
- method public static final boolean isCryptoSchemeSupported(java.util.UUID, java.lang.String);
+ method public static boolean isCryptoSchemeSupported(java.util.UUID);
+ method public static boolean isCryptoSchemeSupported(java.util.UUID, java.lang.String);
method public byte[] openSession() throws android.media.NotProvisionedException, android.media.ResourceBusyException;
method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.NotProvisionedException;
method public void provideProvisionResponse(byte[]) throws android.media.DeniedByServerException;
method public java.util.HashMap<java.lang.String, java.lang.String> queryKeyStatus(byte[]);
method public deprecated void release();
- method public void releaseAllSecureStops();
+ method public deprecated void releaseAllSecureStops();
method public void releaseSecureStops(byte[]);
+ method public void removeAllSecureStops();
method public void removeKeys(byte[]);
+ method public void removeSecureStop(byte[]);
method public void restoreKeys(byte[], byte[]);
method public void setOnEventListener(android.media.MediaDrm.OnEventListener);
method public void setOnExpirationUpdateListener(android.media.MediaDrm.OnExpirationUpdateListener, android.os.Handler);
@@ -23420,21 +23482,21 @@
method public long getSampleSize();
method public long getSampleTime();
method public int getSampleTrackIndex();
- method public final int getTrackCount();
+ method public int getTrackCount();
method public android.media.MediaFormat getTrackFormat(int);
method public boolean hasCacheReachedEndOfStream();
method public int readSampleData(java.nio.ByteBuffer, int);
- method public final void release();
+ method public void release();
method public void seekTo(long, int);
method public void selectTrack(int);
- method public final void setDataSource(android.media.MediaDataSource) throws java.io.IOException;
- method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
- method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
- method public final void setDataSource(java.lang.String) throws java.io.IOException;
- method public final void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
- method public final void setDataSource(java.io.FileDescriptor) throws java.io.IOException;
- method public final void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException;
- method public final void setMediaCas(android.media.MediaCas);
+ method public void setDataSource(android.media.MediaDataSource) throws java.io.IOException;
+ method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
+ method public void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
+ method public void setDataSource(java.lang.String) throws java.io.IOException;
+ method public void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+ method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException;
+ method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException;
+ method public void setMediaCas(android.media.MediaCas);
method public void unselectTrack(int);
field public static final int SAMPLE_FLAG_ENCRYPTED = 2; // 0x2
field public static final int SAMPLE_FLAG_PARTIAL_FRAME = 4; // 0x4
@@ -23457,22 +23519,22 @@
public final class MediaFormat {
ctor public MediaFormat();
- method public final boolean containsKey(java.lang.String);
- method public static final android.media.MediaFormat createAudioFormat(java.lang.String, int, int);
- method public static final android.media.MediaFormat createSubtitleFormat(java.lang.String, java.lang.String);
- method public static final android.media.MediaFormat createVideoFormat(java.lang.String, int, int);
- method public final java.nio.ByteBuffer getByteBuffer(java.lang.String);
+ method public boolean containsKey(java.lang.String);
+ method public static android.media.MediaFormat createAudioFormat(java.lang.String, int, int);
+ method public static android.media.MediaFormat createSubtitleFormat(java.lang.String, java.lang.String);
+ method public static android.media.MediaFormat createVideoFormat(java.lang.String, int, int);
+ method public java.nio.ByteBuffer getByteBuffer(java.lang.String);
method public boolean getFeatureEnabled(java.lang.String);
- method public final float getFloat(java.lang.String);
- method public final int getInteger(java.lang.String);
- method public final long getLong(java.lang.String);
- method public final java.lang.String getString(java.lang.String);
- method public final void setByteBuffer(java.lang.String, java.nio.ByteBuffer);
+ method public float getFloat(java.lang.String);
+ method public int getInteger(java.lang.String);
+ method public long getLong(java.lang.String);
+ method public java.lang.String getString(java.lang.String);
+ method public void setByteBuffer(java.lang.String, java.nio.ByteBuffer);
method public void setFeatureEnabled(java.lang.String, boolean);
- method public final void setFloat(java.lang.String, float);
- method public final void setInteger(java.lang.String, int);
- method public final void setLong(java.lang.String, long);
- method public final void setString(java.lang.String, java.lang.String);
+ method public void setFloat(java.lang.String, float);
+ method public void setInteger(java.lang.String, int);
+ method public void setLong(java.lang.String, long);
+ method public void setString(java.lang.String, java.lang.String);
field public static final int COLOR_RANGE_FULL = 1; // 0x1
field public static final int COLOR_RANGE_LIMITED = 2; // 0x2
field public static final int COLOR_STANDARD_BT2020 = 6; // 0x6
@@ -24372,14 +24434,14 @@
public final class MediaSync {
ctor public MediaSync();
- method public final android.view.Surface createInputSurface();
+ method public android.view.Surface createInputSurface();
method protected void finalize();
method public void flush();
method public android.media.PlaybackParams getPlaybackParams();
method public android.media.SyncParams getSyncParams();
method public android.media.MediaTimestamp getTimestamp();
method public void queueAudio(java.nio.ByteBuffer, int, long);
- method public final void release();
+ method public void release();
method public void setAudioTrack(android.media.AudioTrack);
method public void setCallback(android.media.MediaSync.Callback, android.os.Handler);
method public void setOnErrorListener(android.media.MediaSync.OnErrorListener, android.os.Handler);
@@ -25369,7 +25431,7 @@
public final class MidiInputPort extends android.media.midi.MidiReceiver implements java.io.Closeable {
method public void close() throws java.io.IOException;
- method public final int getPortNumber();
+ method public int getPortNumber();
method public void onSend(byte[], int, int, long) throws java.io.IOException;
}
@@ -25394,7 +25456,7 @@
public final class MidiOutputPort extends android.media.midi.MidiSender implements java.io.Closeable {
method public void close() throws java.io.IOException;
- method public final int getPortNumber();
+ method public int getPortNumber();
method public void onConnect(android.media.midi.MidiReceiver);
method public void onDisconnect(android.media.midi.MidiReceiver);
}
@@ -25669,7 +25731,7 @@
package android.media.tv {
public final class TvContentRating {
- method public final boolean contains(android.media.tv.TvContentRating);
+ method public boolean contains(android.media.tv.TvContentRating);
method public static android.media.tv.TvContentRating createRating(java.lang.String, java.lang.String, java.lang.String, java.lang.String...);
method public java.lang.String flattenToString();
method public java.lang.String getDomain();
@@ -25719,7 +25781,7 @@
}
public static final class TvContract.Channels implements android.media.tv.TvContract.BaseTvColumns {
- method public static final java.lang.String getVideoResolution(java.lang.String);
+ method public static java.lang.String getVideoResolution(java.lang.String);
field public static final java.lang.String COLUMN_APP_LINK_COLOR = "app_link_color";
field public static final java.lang.String COLUMN_APP_LINK_ICON_URI = "app_link_icon_uri";
field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
@@ -26244,18 +26306,18 @@
public final class TvTrackInfo implements android.os.Parcelable {
method public int describeContents();
- method public final int getAudioChannelCount();
- method public final int getAudioSampleRate();
- method public final java.lang.CharSequence getDescription();
- method public final android.os.Bundle getExtra();
- method public final java.lang.String getId();
- method public final java.lang.String getLanguage();
- method public final int getType();
- method public final byte getVideoActiveFormatDescription();
- method public final float getVideoFrameRate();
- method public final int getVideoHeight();
- method public final float getVideoPixelAspectRatio();
- method public final int getVideoWidth();
+ method public int getAudioChannelCount();
+ method public int getAudioSampleRate();
+ method public java.lang.CharSequence getDescription();
+ method public android.os.Bundle getExtra();
+ method public java.lang.String getId();
+ method public java.lang.String getLanguage();
+ method public int getType();
+ method public byte getVideoActiveFormatDescription();
+ method public float getVideoFrameRate();
+ method public int getVideoHeight();
+ method public float getVideoPixelAspectRatio();
+ method public int getVideoWidth();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.media.tv.TvTrackInfo> CREATOR;
field public static final int TYPE_AUDIO = 0; // 0x0
@@ -26266,16 +26328,16 @@
public static final class TvTrackInfo.Builder {
ctor public TvTrackInfo.Builder(int, java.lang.String);
method public android.media.tv.TvTrackInfo build();
- method public final android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int);
- method public final android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
- method public final android.media.tv.TvTrackInfo.Builder setDescription(java.lang.CharSequence);
- method public final android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
- method public final android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String);
- method public final android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte);
- method public final android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
- method public final android.media.tv.TvTrackInfo.Builder setVideoHeight(int);
- method public final android.media.tv.TvTrackInfo.Builder setVideoPixelAspectRatio(float);
- method public final android.media.tv.TvTrackInfo.Builder setVideoWidth(int);
+ method public android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int);
+ method public android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
+ method public android.media.tv.TvTrackInfo.Builder setDescription(java.lang.CharSequence);
+ method public android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
+ method public android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String);
+ method public android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte);
+ method public android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
+ method public android.media.tv.TvTrackInfo.Builder setVideoHeight(int);
+ method public android.media.tv.TvTrackInfo.Builder setVideoPixelAspectRatio(float);
+ method public android.media.tv.TvTrackInfo.Builder setVideoWidth(int);
}
public class TvView extends android.view.ViewGroup {
@@ -26506,34 +26568,34 @@
}
public final class MtpObjectInfo {
- method public final int getAssociationDesc();
- method public final int getAssociationType();
- method public final int getCompressedSize();
- method public final long getCompressedSizeLong();
- method public final long getDateCreated();
- method public final long getDateModified();
- method public final int getFormat();
- method public final int getImagePixDepth();
- method public final long getImagePixDepthLong();
- method public final int getImagePixHeight();
- method public final long getImagePixHeightLong();
- method public final int getImagePixWidth();
- method public final long getImagePixWidthLong();
- method public final java.lang.String getKeywords();
- method public final java.lang.String getName();
- method public final int getObjectHandle();
- method public final int getParent();
- method public final int getProtectionStatus();
- method public final int getSequenceNumber();
- method public final long getSequenceNumberLong();
- method public final int getStorageId();
- method public final int getThumbCompressedSize();
- method public final long getThumbCompressedSizeLong();
- method public final int getThumbFormat();
- method public final int getThumbPixHeight();
- method public final long getThumbPixHeightLong();
- method public final int getThumbPixWidth();
- method public final long getThumbPixWidthLong();
+ method public int getAssociationDesc();
+ method public int getAssociationType();
+ method public int getCompressedSize();
+ method public long getCompressedSizeLong();
+ method public long getDateCreated();
+ method public long getDateModified();
+ method public int getFormat();
+ method public int getImagePixDepth();
+ method public long getImagePixDepthLong();
+ method public int getImagePixHeight();
+ method public long getImagePixHeightLong();
+ method public int getImagePixWidth();
+ method public long getImagePixWidthLong();
+ method public java.lang.String getKeywords();
+ method public java.lang.String getName();
+ method public int getObjectHandle();
+ method public int getParent();
+ method public int getProtectionStatus();
+ method public int getSequenceNumber();
+ method public long getSequenceNumberLong();
+ method public int getStorageId();
+ method public int getThumbCompressedSize();
+ method public long getThumbCompressedSizeLong();
+ method public int getThumbFormat();
+ method public int getThumbPixHeight();
+ method public long getThumbPixHeightLong();
+ method public int getThumbPixWidth();
+ method public long getThumbPixWidthLong();
}
public static class MtpObjectInfo.Builder {
@@ -26563,11 +26625,11 @@
}
public final class MtpStorageInfo {
- method public final java.lang.String getDescription();
- method public final long getFreeSpace();
- method public final long getMaxCapacity();
- method public final int getStorageId();
- method public final java.lang.String getVolumeIdentifier();
+ method public java.lang.String getDescription();
+ method public long getFreeSpace();
+ method public long getMaxCapacity();
+ method public int getStorageId();
+ method public java.lang.String getVolumeIdentifier();
}
}
@@ -27000,10 +27062,10 @@
public final class Proxy {
ctor public Proxy();
- method public static final deprecated java.lang.String getDefaultHost();
- method public static final deprecated int getDefaultPort();
- method public static final deprecated java.lang.String getHost(android.content.Context);
- method public static final deprecated int getPort(android.content.Context);
+ method public static deprecated java.lang.String getDefaultHost();
+ method public static deprecated int getDefaultPort();
+ method public static deprecated java.lang.String getHost(android.content.Context);
+ method public static deprecated int getPort(android.content.Context);
field public static final deprecated java.lang.String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO";
field public static final java.lang.String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
}
@@ -32030,9 +32092,9 @@
method public static void dumpHprofData(java.lang.String) throws java.io.IOException;
method public static boolean dumpService(java.lang.String, java.io.FileDescriptor, java.lang.String[]);
method public static void enableEmulatorTraceOutput();
- method public static final int getBinderDeathObjectCount();
- method public static final int getBinderLocalObjectCount();
- method public static final int getBinderProxyObjectCount();
+ method public static int getBinderDeathObjectCount();
+ method public static int getBinderLocalObjectCount();
+ method public static int getBinderProxyObjectCount();
method public static int getBinderReceivedTransactions();
method public static int getBinderSentTransactions();
method public static deprecated int getGlobalAllocCount();
@@ -32441,114 +32503,114 @@
}
public final class Parcel {
- method public final void appendFrom(android.os.Parcel, int, int);
- method public final android.os.IBinder[] createBinderArray();
- method public final java.util.ArrayList<android.os.IBinder> createBinderArrayList();
- method public final boolean[] createBooleanArray();
- method public final byte[] createByteArray();
- method public final char[] createCharArray();
- method public final double[] createDoubleArray();
- method public final float[] createFloatArray();
- method public final int[] createIntArray();
- method public final long[] createLongArray();
- method public final java.lang.String[] createStringArray();
- method public final java.util.ArrayList<java.lang.String> createStringArrayList();
- method public final <T> T[] createTypedArray(android.os.Parcelable.Creator<T>);
- method public final <T> java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
- method public final int dataAvail();
- method public final int dataCapacity();
- method public final int dataPosition();
- method public final int dataSize();
- method public final void enforceInterface(java.lang.String);
- method public final boolean hasFileDescriptors();
- method public final byte[] marshall();
+ method public void appendFrom(android.os.Parcel, int, int);
+ method public android.os.IBinder[] createBinderArray();
+ method public java.util.ArrayList<android.os.IBinder> createBinderArrayList();
+ method public boolean[] createBooleanArray();
+ method public byte[] createByteArray();
+ method public char[] createCharArray();
+ method public double[] createDoubleArray();
+ method public float[] createFloatArray();
+ method public int[] createIntArray();
+ method public long[] createLongArray();
+ method public java.lang.String[] createStringArray();
+ method public java.util.ArrayList<java.lang.String> createStringArrayList();
+ method public <T> T[] createTypedArray(android.os.Parcelable.Creator<T>);
+ method public <T> java.util.ArrayList<T> createTypedArrayList(android.os.Parcelable.Creator<T>);
+ method public int dataAvail();
+ method public int dataCapacity();
+ method public int dataPosition();
+ method public int dataSize();
+ method public void enforceInterface(java.lang.String);
+ method public boolean hasFileDescriptors();
+ method public byte[] marshall();
method public static android.os.Parcel obtain();
- method public final java.lang.Object[] readArray(java.lang.ClassLoader);
- method public final java.util.ArrayList readArrayList(java.lang.ClassLoader);
- method public final void readBinderArray(android.os.IBinder[]);
- method public final void readBinderList(java.util.List<android.os.IBinder>);
- method public final void readBooleanArray(boolean[]);
- method public final android.os.Bundle readBundle();
- method public final android.os.Bundle readBundle(java.lang.ClassLoader);
- method public final byte readByte();
- method public final void readByteArray(byte[]);
- method public final void readCharArray(char[]);
- method public final double readDouble();
- method public final void readDoubleArray(double[]);
- method public final void readException();
- method public final void readException(int, java.lang.String);
- method public final android.os.ParcelFileDescriptor readFileDescriptor();
- method public final float readFloat();
- method public final void readFloatArray(float[]);
- method public final java.util.HashMap readHashMap(java.lang.ClassLoader);
- method public final int readInt();
- method public final void readIntArray(int[]);
- method public final void readList(java.util.List, java.lang.ClassLoader);
- method public final long readLong();
- method public final void readLongArray(long[]);
- method public final void readMap(java.util.Map, java.lang.ClassLoader);
- method public final <T extends android.os.Parcelable> T readParcelable(java.lang.ClassLoader);
- method public final android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
- method public final android.os.PersistableBundle readPersistableBundle();
- method public final android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
- method public final java.io.Serializable readSerializable();
- method public final android.util.Size readSize();
- method public final android.util.SizeF readSizeF();
- method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader);
- method public final android.util.SparseBooleanArray readSparseBooleanArray();
- method public final java.lang.String readString();
- method public final void readStringArray(java.lang.String[]);
- method public final void readStringList(java.util.List<java.lang.String>);
- method public final android.os.IBinder readStrongBinder();
- method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
- method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
- method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
- method public final java.lang.Object readValue(java.lang.ClassLoader);
- method public final void recycle();
- method public final void setDataCapacity(int);
- method public final void setDataPosition(int);
- method public final void setDataSize(int);
- method public final void unmarshall(byte[], int, int);
- method public final void writeArray(java.lang.Object[]);
- method public final void writeBinderArray(android.os.IBinder[]);
- method public final void writeBinderList(java.util.List<android.os.IBinder>);
- method public final void writeBooleanArray(boolean[]);
- method public final void writeBundle(android.os.Bundle);
- method public final void writeByte(byte);
- method public final void writeByteArray(byte[]);
- method public final void writeByteArray(byte[], int, int);
- method public final void writeCharArray(char[]);
- method public final void writeDouble(double);
- method public final void writeDoubleArray(double[]);
- method public final void writeException(java.lang.Exception);
- method public final void writeFileDescriptor(java.io.FileDescriptor);
- method public final void writeFloat(float);
- method public final void writeFloatArray(float[]);
- method public final void writeInt(int);
- method public final void writeIntArray(int[]);
- method public final void writeInterfaceToken(java.lang.String);
- method public final void writeList(java.util.List);
- method public final void writeLong(long);
- method public final void writeLongArray(long[]);
- method public final void writeMap(java.util.Map);
- method public final void writeNoException();
- method public final void writeParcelable(android.os.Parcelable, int);
- method public final <T extends android.os.Parcelable> void writeParcelableArray(T[], int);
- method public final void writePersistableBundle(android.os.PersistableBundle);
- method public final void writeSerializable(java.io.Serializable);
- method public final void writeSize(android.util.Size);
- method public final void writeSizeF(android.util.SizeF);
- method public final void writeSparseArray(android.util.SparseArray<java.lang.Object>);
- method public final void writeSparseBooleanArray(android.util.SparseBooleanArray);
- method public final void writeString(java.lang.String);
- method public final void writeStringArray(java.lang.String[]);
- method public final void writeStringList(java.util.List<java.lang.String>);
- method public final void writeStrongBinder(android.os.IBinder);
- method public final void writeStrongInterface(android.os.IInterface);
- method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
- method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
- method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
- method public final void writeValue(java.lang.Object);
+ method public java.lang.Object[] readArray(java.lang.ClassLoader);
+ method public java.util.ArrayList readArrayList(java.lang.ClassLoader);
+ method public void readBinderArray(android.os.IBinder[]);
+ method public void readBinderList(java.util.List<android.os.IBinder>);
+ method public void readBooleanArray(boolean[]);
+ method public android.os.Bundle readBundle();
+ method public android.os.Bundle readBundle(java.lang.ClassLoader);
+ method public byte readByte();
+ method public void readByteArray(byte[]);
+ method public void readCharArray(char[]);
+ method public double readDouble();
+ method public void readDoubleArray(double[]);
+ method public void readException();
+ method public void readException(int, java.lang.String);
+ method public android.os.ParcelFileDescriptor readFileDescriptor();
+ method public float readFloat();
+ method public void readFloatArray(float[]);
+ method public java.util.HashMap readHashMap(java.lang.ClassLoader);
+ method public int readInt();
+ method public void readIntArray(int[]);
+ method public void readList(java.util.List, java.lang.ClassLoader);
+ method public long readLong();
+ method public void readLongArray(long[]);
+ method public void readMap(java.util.Map, java.lang.ClassLoader);
+ method public <T extends android.os.Parcelable> T readParcelable(java.lang.ClassLoader);
+ method public android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
+ method public android.os.PersistableBundle readPersistableBundle();
+ method public android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
+ method public java.io.Serializable readSerializable();
+ method public android.util.Size readSize();
+ method public android.util.SizeF readSizeF();
+ method public android.util.SparseArray readSparseArray(java.lang.ClassLoader);
+ method public android.util.SparseBooleanArray readSparseBooleanArray();
+ method public java.lang.String readString();
+ method public void readStringArray(java.lang.String[]);
+ method public void readStringList(java.util.List<java.lang.String>);
+ method public android.os.IBinder readStrongBinder();
+ method public <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
+ method public <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
+ method public <T> T readTypedObject(android.os.Parcelable.Creator<T>);
+ method public java.lang.Object readValue(java.lang.ClassLoader);
+ method public void recycle();
+ method public void setDataCapacity(int);
+ method public void setDataPosition(int);
+ method public void setDataSize(int);
+ method public void unmarshall(byte[], int, int);
+ method public void writeArray(java.lang.Object[]);
+ method public void writeBinderArray(android.os.IBinder[]);
+ method public void writeBinderList(java.util.List<android.os.IBinder>);
+ method public void writeBooleanArray(boolean[]);
+ method public void writeBundle(android.os.Bundle);
+ method public void writeByte(byte);
+ method public void writeByteArray(byte[]);
+ method public void writeByteArray(byte[], int, int);
+ method public void writeCharArray(char[]);
+ method public void writeDouble(double);
+ method public void writeDoubleArray(double[]);
+ method public void writeException(java.lang.Exception);
+ method public void writeFileDescriptor(java.io.FileDescriptor);
+ method public void writeFloat(float);
+ method public void writeFloatArray(float[]);
+ method public void writeInt(int);
+ method public void writeIntArray(int[]);
+ method public void writeInterfaceToken(java.lang.String);
+ method public void writeList(java.util.List);
+ method public void writeLong(long);
+ method public void writeLongArray(long[]);
+ method public void writeMap(java.util.Map);
+ method public void writeNoException();
+ method public void writeParcelable(android.os.Parcelable, int);
+ method public <T extends android.os.Parcelable> void writeParcelableArray(T[], int);
+ method public void writePersistableBundle(android.os.PersistableBundle);
+ method public void writeSerializable(java.io.Serializable);
+ method public void writeSize(android.util.Size);
+ method public void writeSizeF(android.util.SizeF);
+ method public void writeSparseArray(android.util.SparseArray<java.lang.Object>);
+ method public void writeSparseBooleanArray(android.util.SparseBooleanArray);
+ method public void writeString(java.lang.String);
+ method public void writeStringArray(java.lang.String[]);
+ method public void writeStringList(java.util.List<java.lang.String>);
+ method public void writeStrongBinder(android.os.IBinder);
+ method public void writeStrongInterface(android.os.IInterface);
+ method public <T extends android.os.Parcelable> void writeTypedArray(T[], int);
+ method public <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
+ method public <T extends android.os.Parcelable> void writeTypedObject(T, int);
+ method public void writeValue(java.lang.Object);
field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
}
@@ -34202,7 +34264,7 @@
}
public static final class CalendarContract.Attendees implements android.provider.BaseColumns android.provider.CalendarContract.AttendeesColumns android.provider.CalendarContract.EventsColumns {
- method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+ method public static android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
field public static final android.net.Uri CONTENT_URI;
}
@@ -34331,7 +34393,7 @@
}
public static final class CalendarContract.EventDays implements android.provider.CalendarContract.EventDaysColumns {
- method public static final android.database.Cursor query(android.content.ContentResolver, int, int, java.lang.String[]);
+ method public static android.database.Cursor query(android.content.ContentResolver, int, int, java.lang.String[]);
field public static final android.net.Uri CONTENT_URI;
}
@@ -34424,8 +34486,8 @@
}
public static final class CalendarContract.Instances implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns {
- method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long);
- method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long, java.lang.String);
+ method public static android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long);
+ method public static android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long, java.lang.String);
field public static final java.lang.String BEGIN = "begin";
field public static final android.net.Uri CONTENT_BY_DAY_URI;
field public static final android.net.Uri CONTENT_SEARCH_BY_DAY_URI;
@@ -34440,7 +34502,7 @@
}
public static final class CalendarContract.Reminders implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.RemindersColumns {
- method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+ method public static android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
field public static final android.net.Uri CONTENT_URI;
}
@@ -34549,7 +34611,7 @@
method public static deprecated java.lang.Object decodeImProtocol(java.lang.String);
method public static deprecated java.lang.String encodeCustomImProtocol(java.lang.String);
method public static deprecated java.lang.String encodePredefinedImProtocol(int);
- method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, int, java.lang.CharSequence);
+ method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, int, java.lang.CharSequence);
field public static final deprecated java.lang.String CONTENT_EMAIL_ITEM_TYPE = "vnd.android.cursor.item/email";
field public static final deprecated java.lang.String CONTENT_EMAIL_TYPE = "vnd.android.cursor.dir/email";
field public static final deprecated android.net.Uri CONTENT_EMAIL_URI;
@@ -34699,7 +34761,7 @@
}
public static final deprecated class Contacts.Organizations implements android.provider.BaseColumns android.provider.Contacts.OrganizationColumns {
- method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence);
+ method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence);
field public static final deprecated java.lang.String CONTENT_DIRECTORY = "organizations";
field public static final deprecated android.net.Uri CONTENT_URI;
field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "company, title, isprimary ASC";
@@ -34756,8 +34818,8 @@
}
public static final deprecated class Contacts.Phones implements android.provider.BaseColumns android.provider.Contacts.PeopleColumns android.provider.Contacts.PhonesColumns {
- method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence, java.lang.CharSequence[]);
- method public static final deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence);
+ method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence, java.lang.CharSequence[]);
+ method public static deprecated java.lang.CharSequence getDisplayLabel(android.content.Context, int, java.lang.CharSequence);
field public static final deprecated android.net.Uri CONTENT_FILTER_URL;
field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone";
field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone";
@@ -34897,8 +34959,8 @@
}
public static final class ContactsContract.CommonDataKinds.Email implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String ADDRESS = "data1";
field public static final android.net.Uri CONTENT_FILTER_URI;
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2";
@@ -34918,7 +34980,7 @@
}
public static final class ContactsContract.CommonDataKinds.Event implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static int getTypeResource(java.lang.Integer);
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
@@ -34949,10 +35011,10 @@
}
public static final class ContactsContract.CommonDataKinds.Im implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getProtocolLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getProtocolLabelResource(int);
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getProtocolLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getProtocolLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im";
field public static final java.lang.String CUSTOM_PROTOCOL = "data6";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
@@ -34997,8 +35059,8 @@
}
public static final class ContactsContract.CommonDataKinds.Organization implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String COMPANY = "data1";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization";
field public static final java.lang.String DEPARTMENT = "data5";
@@ -35016,8 +35078,8 @@
}
public static final class ContactsContract.CommonDataKinds.Phone implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final android.net.Uri CONTENT_FILTER_URI;
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2";
@@ -35062,8 +35124,8 @@
}
public static final class ContactsContract.CommonDataKinds.Relation implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
@@ -35086,8 +35148,8 @@
}
public static final class ContactsContract.CommonDataKinds.SipAddress implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sip_address";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
@@ -35117,8 +35179,8 @@
}
public static final class ContactsContract.CommonDataKinds.StructuredPostal implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
- method public static final int getTypeLabelResource(int);
+ method public static java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
+ method public static int getTypeLabelResource(int);
field public static final java.lang.String CITY = "data7";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/postal-address_v2";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2";
@@ -35945,7 +36007,7 @@
public static final class MediaStore.Audio.Artists.Albums implements android.provider.MediaStore.Audio.AlbumColumns {
ctor public MediaStore.Audio.Artists.Albums();
- method public static final android.net.Uri getContentUri(java.lang.String, long);
+ method public static android.net.Uri getContentUri(java.lang.String, long);
}
public static abstract interface MediaStore.Audio.AudioColumns implements android.provider.MediaStore.MediaColumns {
@@ -35981,7 +36043,7 @@
public static final class MediaStore.Audio.Genres.Members implements android.provider.MediaStore.Audio.AudioColumns {
ctor public MediaStore.Audio.Genres.Members();
- method public static final android.net.Uri getContentUri(java.lang.String, long);
+ method public static android.net.Uri getContentUri(java.lang.String, long);
field public static final java.lang.String AUDIO_ID = "audio_id";
field public static final java.lang.String CONTENT_DIRECTORY = "members";
field public static final java.lang.String DEFAULT_SORT_ORDER = "title_key";
@@ -36017,8 +36079,8 @@
public static final class MediaStore.Audio.Playlists.Members implements android.provider.MediaStore.Audio.AudioColumns {
ctor public MediaStore.Audio.Playlists.Members();
- method public static final android.net.Uri getContentUri(java.lang.String, long);
- method public static final boolean moveItem(android.content.ContentResolver, long, int, int);
+ method public static android.net.Uri getContentUri(java.lang.String, long);
+ method public static boolean moveItem(android.content.ContentResolver, long, int, int);
field public static final java.lang.String AUDIO_ID = "audio_id";
field public static final java.lang.String CONTENT_DIRECTORY = "members";
field public static final java.lang.String DEFAULT_SORT_ORDER = "play_order";
@@ -36041,7 +36103,7 @@
public static final class MediaStore.Files {
ctor public MediaStore.Files();
method public static android.net.Uri getContentUri(java.lang.String);
- method public static final android.net.Uri getContentUri(java.lang.String, long);
+ method public static android.net.Uri getContentUri(java.lang.String, long);
}
public static abstract interface MediaStore.Files.FileColumns implements android.provider.MediaStore.MediaColumns {
@@ -36075,13 +36137,13 @@
public static final class MediaStore.Images.Media implements android.provider.MediaStore.Images.ImageColumns {
ctor public MediaStore.Images.Media();
- method public static final android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException;
+ method public static android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException;
method public static android.net.Uri getContentUri(java.lang.String);
- method public static final java.lang.String insertImage(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
- method public static final java.lang.String insertImage(android.content.ContentResolver, android.graphics.Bitmap, java.lang.String, java.lang.String);
- method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
- method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String);
- method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+ method public static java.lang.String insertImage(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
+ method public static java.lang.String insertImage(android.content.ContentResolver, android.graphics.Bitmap, java.lang.String, java.lang.String);
+ method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
+ method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String);
+ method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/image";
field public static final java.lang.String DEFAULT_SORT_ORDER = "bucket_display_name";
field public static final android.net.Uri EXTERNAL_CONTENT_URI;
@@ -36126,7 +36188,7 @@
public static final class MediaStore.Video {
ctor public MediaStore.Video();
- method public static final android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
+ method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[]);
field public static final java.lang.String DEFAULT_SORT_ORDER = "_display_name";
}
@@ -36358,12 +36420,12 @@
method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
method public static android.net.Uri getUriFor(java.lang.String);
- method public static final deprecated boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String);
+ method public static deprecated boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String);
method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
method public static boolean putInt(android.content.ContentResolver, java.lang.String, int);
method public static boolean putLong(android.content.ContentResolver, java.lang.String, long);
method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String);
- method public static final deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
+ method public static deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
field public static final java.lang.String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED = "accessibility_display_inversion_enabled";
field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled";
field public static final deprecated java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
@@ -38106,6 +38168,59 @@
}
+package android.se.omapi {
+
+ public class Channel {
+ method public void close();
+ method public byte[] getSelectResponse();
+ method public android.se.omapi.Session getSession();
+ method public boolean isBasicChannel();
+ method public boolean isClosed();
+ method public boolean selectNext() throws java.io.IOException;
+ method public byte[] transmit(byte[]) throws java.io.IOException;
+ }
+
+ public abstract interface ISecureElementListener implements android.os.IInterface {
+ method public abstract void serviceConnected() throws android.os.RemoteException;
+ }
+
+ public static abstract class ISecureElementListener.Stub extends android.os.Binder implements android.se.omapi.ISecureElementListener {
+ ctor public ISecureElementListener.Stub();
+ method public android.os.IBinder asBinder();
+ method public static android.se.omapi.ISecureElementListener asInterface(android.os.IBinder);
+ method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+ }
+
+ public class Reader {
+ method public void closeSessions();
+ method public java.lang.String getName();
+ method public android.se.omapi.SEService getSEService();
+ method public boolean isSecureElementPresent();
+ method public android.se.omapi.Session openSession() throws java.io.IOException;
+ }
+
+ public class SEService {
+ ctor public SEService(android.content.Context, android.se.omapi.ISecureElementListener);
+ method public android.se.omapi.Reader[] getReaders();
+ method public java.lang.String getVersion();
+ method public boolean isConnected();
+ method public void shutdown();
+ }
+
+ public class Session {
+ method public void close();
+ method public void closeChannels();
+ method public byte[] getATR();
+ method public android.se.omapi.Reader getReader();
+ method public boolean isClosed();
+ method public android.se.omapi.Channel openBasicChannel(byte[], byte) throws java.io.IOException;
+ method public android.se.omapi.Channel openBasicChannel(byte[]) throws java.io.IOException;
+ method public android.se.omapi.Channel openLogicalChannel(byte[], byte) throws java.io.IOException;
+ method public android.se.omapi.Channel openLogicalChannel(byte[]) throws java.io.IOException;
+ }
+
+}
+
package android.security {
public final class AttestedKeyPair {
@@ -38113,6 +38228,37 @@
method public java.security.KeyPair getKeyPair();
}
+ public class ConfirmationAlreadyPresentingException extends java.lang.Exception {
+ ctor public ConfirmationAlreadyPresentingException();
+ ctor public ConfirmationAlreadyPresentingException(java.lang.String);
+ }
+
+ public abstract class ConfirmationCallback {
+ ctor public ConfirmationCallback();
+ method public void onConfirmedByUser(byte[]);
+ method public void onDismissedByApplication();
+ method public void onDismissedByUser();
+ method public void onError(java.lang.Exception);
+ }
+
+ public class ConfirmationDialog {
+ method public void cancelPrompt();
+ method public static boolean isSupported();
+ method public void presentPrompt(java.util.concurrent.Executor, android.security.ConfirmationCallback) throws android.security.ConfirmationAlreadyPresentingException, android.security.ConfirmationNotAvailableException;
+ }
+
+ public static class ConfirmationDialog.Builder {
+ ctor public ConfirmationDialog.Builder();
+ method public android.security.ConfirmationDialog build(android.content.Context);
+ method public android.security.ConfirmationDialog.Builder setExtraData(byte[]);
+ method public android.security.ConfirmationDialog.Builder setPromptText(java.lang.CharSequence);
+ }
+
+ public class ConfirmationNotAvailableException extends java.lang.Exception {
+ ctor public ConfirmationNotAvailableException();
+ ctor public ConfirmationNotAvailableException(java.lang.String);
+ }
+
public final class KeyChain {
ctor public KeyChain();
method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
@@ -38222,6 +38368,7 @@
method public boolean isTrustedUserPresenceRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
+ method public boolean isUserConfirmationRequired();
}
public static final class KeyGenParameterSpec.Builder {
@@ -38249,6 +38396,7 @@
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
+ method public android.security.keystore.KeyGenParameterSpec.Builder setUserConfirmationRequired(boolean);
}
public class KeyInfo implements java.security.spec.KeySpec {
@@ -38270,6 +38418,7 @@
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
method public boolean isUserAuthenticationValidWhileOnBody();
+ method public boolean isUserConfirmationRequired();
}
public class KeyNotYetValidException extends java.security.InvalidKeyException {
@@ -38337,6 +38486,7 @@
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
+ method public boolean isUserConfirmationRequired();
}
public static final class KeyProtection.Builder {
@@ -38355,6 +38505,7 @@
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
+ method public android.security.keystore.KeyProtection.Builder setUserConfirmationRequired(boolean);
}
public class StrongBoxUnavailableException extends java.security.ProviderException {
@@ -38452,6 +38603,20 @@
method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, java.util.regex.Pattern, android.widget.RemoteViews);
}
+ public final class DateTransformation implements android.os.Parcelable android.service.autofill.Transformation {
+ ctor public DateTransformation(android.view.autofill.AutofillId, java.text.DateFormat);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.DateTransformation> CREATOR;
+ }
+
+ public final class DateValueSanitizer implements android.os.Parcelable android.service.autofill.Sanitizer {
+ ctor public DateValueSanitizer(java.text.DateFormat);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.DateValueSanitizer> CREATOR;
+ }
+
public final class FieldClassification {
method public java.util.List<android.service.autofill.FieldClassification.Match> getMatches();
}
@@ -38621,6 +38786,7 @@
public final class UserData implements android.os.Parcelable {
method public int describeContents();
method public java.lang.String getFieldClassificationAlgorithm();
+ method public java.lang.String getId();
method public static int getMaxFieldClassificationIdsSize();
method public static int getMaxUserDataSize();
method public static int getMaxValueLength();
@@ -38630,7 +38796,7 @@
}
public static final class UserData.Builder {
- ctor public UserData.Builder(java.lang.String, java.lang.String);
+ ctor public UserData.Builder(java.lang.String, java.lang.String, java.lang.String);
method public android.service.autofill.UserData.Builder add(java.lang.String, java.lang.String);
method public android.service.autofill.UserData build();
method public android.service.autofill.UserData.Builder setFieldClassificationAlgorithm(java.lang.String, android.os.Bundle);
@@ -40291,12 +40457,12 @@
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
method public void pullExternalCall();
- method public final void putExtras(android.os.Bundle);
+ method public void putExtras(android.os.Bundle);
method public void registerCallback(android.telecom.Call.Callback);
method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
method public void reject(boolean, java.lang.String);
- method public final void removeExtras(java.util.List<java.lang.String>);
- method public final void removeExtras(java.lang.String...);
+ method public void removeExtras(java.util.List<java.lang.String>);
+ method public void removeExtras(java.lang.String...);
method public void respondToRttRequest(int, boolean);
method public void sendCallEvent(java.lang.String, android.os.Bundle);
method public void sendRttRequest();
@@ -40865,23 +41031,23 @@
public final class RemoteConference {
method public void disconnect();
method public java.util.List<android.telecom.RemoteConnection> getConferenceableConnections();
- method public final int getConnectionCapabilities();
- method public final int getConnectionProperties();
- method public final java.util.List<android.telecom.RemoteConnection> getConnections();
+ method public int getConnectionCapabilities();
+ method public int getConnectionProperties();
+ method public java.util.List<android.telecom.RemoteConnection> getConnections();
method public android.telecom.DisconnectCause getDisconnectCause();
- method public final android.os.Bundle getExtras();
- method public final int getState();
+ method public android.os.Bundle getExtras();
+ method public int getState();
method public void hold();
method public void merge();
method public void playDtmfTone(char);
- method public final void registerCallback(android.telecom.RemoteConference.Callback);
- method public final void registerCallback(android.telecom.RemoteConference.Callback, android.os.Handler);
+ method public void registerCallback(android.telecom.RemoteConference.Callback);
+ method public void registerCallback(android.telecom.RemoteConference.Callback, android.os.Handler);
method public void separate(android.telecom.RemoteConnection);
method public void setCallAudioState(android.telecom.CallAudioState);
method public void stopDtmfTone();
method public void swap();
method public void unhold();
- method public final void unregisterCallback(android.telecom.RemoteConference.Callback);
+ method public void unregisterCallback(android.telecom.RemoteConference.Callback);
}
public static abstract class RemoteConference.Callback {
@@ -40910,10 +41076,10 @@
method public int getConnectionCapabilities();
method public int getConnectionProperties();
method public android.telecom.DisconnectCause getDisconnectCause();
- method public final android.os.Bundle getExtras();
+ method public android.os.Bundle getExtras();
method public int getState();
method public android.telecom.StatusHints getStatusHints();
- method public final android.telecom.RemoteConnection.VideoProvider getVideoProvider();
+ method public android.telecom.RemoteConnection.VideoProvider getVideoProvider();
method public int getVideoState();
method public void hold();
method public boolean isRingbackRequested();
@@ -42366,11 +42532,11 @@
}
public final deprecated class SmsManager {
- method public final deprecated java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
- method public static final deprecated android.telephony.gsm.SmsManager getDefault();
- method public final deprecated void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
- method public final deprecated void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
- method public final deprecated void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
+ method public deprecated java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
+ method public static deprecated android.telephony.gsm.SmsManager getDefault();
+ method public deprecated void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
+ method public deprecated void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
+ method public deprecated void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
field public static final deprecated int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1
field public static final deprecated int RESULT_ERROR_NO_SERVICE = 4; // 0x4
field public static final deprecated int RESULT_ERROR_NULL_PDU = 3; // 0x3
@@ -43832,13 +43998,19 @@
public class QuoteSpan implements android.text.style.LeadingMarginSpan android.text.ParcelableSpan {
ctor public QuoteSpan();
ctor public QuoteSpan(int);
+ ctor public QuoteSpan(int, int, int);
ctor public QuoteSpan(android.os.Parcel);
method public int describeContents();
method public void drawLeadingMargin(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, boolean, android.text.Layout);
method public int getColor();
+ method public int getGapWidth();
method public int getLeadingMargin(boolean);
method public int getSpanTypeId();
+ method public int getStripeWidth();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int STANDARD_COLOR = -16776961; // 0xff0000ff
+ field public static final int STANDARD_GAP_WIDTH_PX = 2; // 0x2
+ field public static final int STANDARD_STRIPE_WIDTH_PX = 2; // 0x2
}
public class RelativeSizeSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
@@ -44236,6 +44408,11 @@
method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String);
method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
+ method public static java.util.concurrent.Future<java.lang.Void> addLinksAsync(android.widget.TextView, android.view.textclassifier.TextLinks.Options);
+ method public static java.util.concurrent.Future<java.lang.Void> addLinksAsync(android.widget.TextView, android.view.textclassifier.TextLinks.Options, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>);
+ method public static java.util.concurrent.Future<java.lang.Void> addLinksAsync(android.text.Spannable, android.view.textclassifier.TextClassifier, android.view.textclassifier.TextLinks.Options);
+ method public static java.util.concurrent.Future<java.lang.Void> addLinksAsync(android.text.Spannable, android.view.textclassifier.TextClassifier, int);
+ method public static java.util.concurrent.Future<java.lang.Void> addLinksAsync(android.text.Spannable, android.view.textclassifier.TextClassifier, android.view.textclassifier.TextLinks.Options, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>);
field public static final int ALL = 15; // 0xf
field public static final int EMAIL_ADDRESSES = 2; // 0x2
field public static final int MAP_ADDRESSES = 8; // 0x8
@@ -46418,76 +46595,76 @@
public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
method public static java.lang.String actionToString(int);
- method public final void addBatch(long, float, float, float, float, int);
- method public final void addBatch(long, android.view.MotionEvent.PointerCoords[], int);
+ method public void addBatch(long, float, float, float, float, int);
+ method public void addBatch(long, android.view.MotionEvent.PointerCoords[], int);
method public static int axisFromString(java.lang.String);
method public static java.lang.String axisToString(int);
- method public final int findPointerIndex(int);
- method public final int getAction();
- method public final int getActionButton();
- method public final int getActionIndex();
- method public final int getActionMasked();
- method public final float getAxisValue(int);
- method public final float getAxisValue(int, int);
- method public final int getButtonState();
- method public final int getDeviceId();
- method public final long getDownTime();
- method public final int getEdgeFlags();
- method public final long getEventTime();
- method public final int getFlags();
- method public final float getHistoricalAxisValue(int, int);
- method public final float getHistoricalAxisValue(int, int, int);
- method public final long getHistoricalEventTime(int);
- method public final float getHistoricalOrientation(int);
- method public final float getHistoricalOrientation(int, int);
- method public final void getHistoricalPointerCoords(int, int, android.view.MotionEvent.PointerCoords);
- method public final float getHistoricalPressure(int);
- method public final float getHistoricalPressure(int, int);
- method public final float getHistoricalSize(int);
- method public final float getHistoricalSize(int, int);
- method public final float getHistoricalToolMajor(int);
- method public final float getHistoricalToolMajor(int, int);
- method public final float getHistoricalToolMinor(int);
- method public final float getHistoricalToolMinor(int, int);
- method public final float getHistoricalTouchMajor(int);
- method public final float getHistoricalTouchMajor(int, int);
- method public final float getHistoricalTouchMinor(int);
- method public final float getHistoricalTouchMinor(int, int);
- method public final float getHistoricalX(int);
- method public final float getHistoricalX(int, int);
- method public final float getHistoricalY(int);
- method public final float getHistoricalY(int, int);
- method public final int getHistorySize();
- method public final int getMetaState();
- method public final float getOrientation();
- method public final float getOrientation(int);
- method public final void getPointerCoords(int, android.view.MotionEvent.PointerCoords);
- method public final int getPointerCount();
- method public final int getPointerId(int);
- method public final void getPointerProperties(int, android.view.MotionEvent.PointerProperties);
- method public final float getPressure();
- method public final float getPressure(int);
- method public final float getRawX();
- method public final float getRawY();
- method public final float getSize();
- method public final float getSize(int);
- method public final int getSource();
- method public final float getToolMajor();
- method public final float getToolMajor(int);
- method public final float getToolMinor();
- method public final float getToolMinor(int);
- method public final int getToolType(int);
- method public final float getTouchMajor();
- method public final float getTouchMajor(int);
- method public final float getTouchMinor();
- method public final float getTouchMinor(int);
- method public final float getX();
- method public final float getX(int);
- method public final float getXPrecision();
- method public final float getY();
- method public final float getY(int);
- method public final float getYPrecision();
- method public final boolean isButtonPressed(int);
+ method public int findPointerIndex(int);
+ method public int getAction();
+ method public int getActionButton();
+ method public int getActionIndex();
+ method public int getActionMasked();
+ method public float getAxisValue(int);
+ method public float getAxisValue(int, int);
+ method public int getButtonState();
+ method public int getDeviceId();
+ method public long getDownTime();
+ method public int getEdgeFlags();
+ method public long getEventTime();
+ method public int getFlags();
+ method public float getHistoricalAxisValue(int, int);
+ method public float getHistoricalAxisValue(int, int, int);
+ method public long getHistoricalEventTime(int);
+ method public float getHistoricalOrientation(int);
+ method public float getHistoricalOrientation(int, int);
+ method public void getHistoricalPointerCoords(int, int, android.view.MotionEvent.PointerCoords);
+ method public float getHistoricalPressure(int);
+ method public float getHistoricalPressure(int, int);
+ method public float getHistoricalSize(int);
+ method public float getHistoricalSize(int, int);
+ method public float getHistoricalToolMajor(int);
+ method public float getHistoricalToolMajor(int, int);
+ method public float getHistoricalToolMinor(int);
+ method public float getHistoricalToolMinor(int, int);
+ method public float getHistoricalTouchMajor(int);
+ method public float getHistoricalTouchMajor(int, int);
+ method public float getHistoricalTouchMinor(int);
+ method public float getHistoricalTouchMinor(int, int);
+ method public float getHistoricalX(int);
+ method public float getHistoricalX(int, int);
+ method public float getHistoricalY(int);
+ method public float getHistoricalY(int, int);
+ method public int getHistorySize();
+ method public int getMetaState();
+ method public float getOrientation();
+ method public float getOrientation(int);
+ method public void getPointerCoords(int, android.view.MotionEvent.PointerCoords);
+ method public int getPointerCount();
+ method public int getPointerId(int);
+ method public void getPointerProperties(int, android.view.MotionEvent.PointerProperties);
+ method public float getPressure();
+ method public float getPressure(int);
+ method public float getRawX();
+ method public float getRawY();
+ method public float getSize();
+ method public float getSize(int);
+ method public int getSource();
+ method public float getToolMajor();
+ method public float getToolMajor(int);
+ method public float getToolMinor();
+ method public float getToolMinor(int);
+ method public int getToolType(int);
+ method public float getTouchMajor();
+ method public float getTouchMajor(int);
+ method public float getTouchMinor();
+ method public float getTouchMinor(int);
+ method public float getX();
+ method public float getX(int);
+ method public float getXPrecision();
+ method public float getY();
+ method public float getY(int);
+ method public float getYPrecision();
+ method public boolean isButtonPressed(int);
method public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int);
method public static deprecated android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent.PointerCoords[], int, float, float, int, int, int, int);
method public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int);
@@ -46495,13 +46672,13 @@
method public static android.view.MotionEvent obtain(long, long, int, float, float, int);
method public static android.view.MotionEvent obtain(android.view.MotionEvent);
method public static android.view.MotionEvent obtainNoHistory(android.view.MotionEvent);
- method public final void offsetLocation(float, float);
- method public final void recycle();
- method public final void setAction(int);
- method public final void setEdgeFlags(int);
- method public final void setLocation(float, float);
- method public final void setSource(int);
- method public final void transform(android.graphics.Matrix);
+ method public void offsetLocation(float, float);
+ method public void recycle();
+ method public void setAction(int);
+ method public void setEdgeFlags(int);
+ method public void setLocation(float, float);
+ method public void setSource(int);
+ method public void transform(android.graphics.Matrix);
method public void writeToParcel(android.os.Parcel, int);
field public static final int ACTION_BUTTON_PRESS = 11; // 0xb
field public static final int ACTION_BUTTON_RELEASE = 12; // 0xc
@@ -47062,7 +47239,9 @@
method public int getNextFocusRightId();
method public int getNextFocusUpId();
method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
+ method public int getOutlineAmbientShadowColor();
method public android.view.ViewOutlineProvider getOutlineProvider();
+ method public int getOutlineSpotShadowColor();
method public int getOverScrollMode();
method public android.view.ViewOverlay getOverlay();
method public int getPaddingBottom();
@@ -47384,7 +47563,9 @@
method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener);
method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
method public void setOnTouchListener(android.view.View.OnTouchListener);
+ method public void setOutlineAmbientShadowColor(int);
method public void setOutlineProvider(android.view.ViewOutlineProvider);
+ method public void setOutlineSpotShadowColor(int);
method public void setOverScrollMode(int);
method public void setPadding(int, int, int, int);
method public void setPaddingRelative(int, int, int, int);
@@ -48219,9 +48400,9 @@
method public void addOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener);
method public void addOnWindowAttachListener(android.view.ViewTreeObserver.OnWindowAttachListener);
method public void addOnWindowFocusChangeListener(android.view.ViewTreeObserver.OnWindowFocusChangeListener);
- method public final void dispatchOnDraw();
- method public final void dispatchOnGlobalLayout();
- method public final boolean dispatchOnPreDraw();
+ method public void dispatchOnDraw();
+ method public void dispatchOnGlobalLayout();
+ method public boolean dispatchOnPreDraw();
method public boolean isAlive();
method public deprecated void removeGlobalOnLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener);
method public void removeOnDrawListener(android.view.ViewTreeObserver.OnDrawListener);
@@ -49476,6 +49657,7 @@
method public java.util.List<java.lang.String> getAvailableFieldClassificationAlgorithms();
method public java.lang.String getDefaultFieldClassificationAlgorithm();
method public android.service.autofill.UserData getUserData();
+ method public java.lang.String getUserDataId();
method public boolean hasEnabledAutofillServices();
method public boolean isAutofillSupported();
method public boolean isEnabled();
@@ -49931,7 +50113,8 @@
package android.view.textclassifier {
- public final class TextClassification {
+ public final class TextClassification implements android.os.Parcelable {
+ method public int describeContents();
method public float getConfidenceScore(java.lang.String);
method public java.lang.String getEntity(int);
method public int getEntityCount();
@@ -49945,6 +50128,8 @@
method public java.lang.CharSequence getSecondaryLabel(int);
method public java.lang.String getSignature();
method public java.lang.String getText();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassification> CREATOR;
}
public static final class TextClassification.Builder {
@@ -49985,6 +50170,7 @@
method public default android.view.textclassifier.TextLinks generateLinks(java.lang.CharSequence, android.view.textclassifier.TextLinks.Options);
method public default android.view.textclassifier.TextLinks generateLinks(java.lang.CharSequence);
method public default java.util.Collection<java.lang.String> getEntitiesForPreset(int);
+ method public default android.view.textclassifier.logging.Logger getLogger(android.view.textclassifier.logging.Logger.Config);
method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.view.textclassifier.TextSelection.Options);
method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
@@ -50014,32 +50200,42 @@
}
public final class TextLinks implements android.os.Parcelable {
- method public boolean apply(android.text.SpannableString, java.util.function.Function<android.view.textclassifier.TextLinks.TextLink, android.text.style.ClickableSpan>);
method public int describeContents();
method public java.util.Collection<android.view.textclassifier.TextLinks.TextLink> getLinks();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int APPLY_STRATEGY_IGNORE = 0; // 0x0
+ field public static final int APPLY_STRATEGY_REPLACE = 1; // 0x1
field public static final android.os.Parcelable.Creator<android.view.textclassifier.TextLinks> CREATOR;
+ field public static final int STATUS_DIFFERENT_TEXT = 3; // 0x3
+ field public static final int STATUS_LINKS_APPLIED = 0; // 0x0
+ field public static final int STATUS_NO_LINKS_APPLIED = 2; // 0x2
+ field public static final int STATUS_NO_LINKS_FOUND = 1; // 0x1
}
public static final class TextLinks.Builder {
ctor public TextLinks.Builder(java.lang.String);
- method public android.view.textclassifier.TextLinks.Builder addLink(android.view.textclassifier.TextLinks.TextLink);
+ method public android.view.textclassifier.TextLinks.Builder addLink(int, int, java.util.Map<java.lang.String, java.lang.Float>);
method public android.view.textclassifier.TextLinks build();
+ method public android.view.textclassifier.TextLinks.Builder clearTextLinks();
}
public static final class TextLinks.Options implements android.os.Parcelable {
ctor public TextLinks.Options();
method public int describeContents();
+ method public static android.view.textclassifier.TextLinks.Options fromLinkMask(int);
+ method public int getApplyStrategy();
method public android.os.LocaleList getDefaultLocales();
method public android.view.textclassifier.TextClassifier.EntityConfig getEntityConfig();
+ method public java.util.function.Function<android.view.textclassifier.TextLinks.TextLink, android.view.textclassifier.TextLinks.TextLinkSpan> getSpanFactory();
+ method public android.view.textclassifier.TextLinks.Options setApplyStrategy(int);
method public android.view.textclassifier.TextLinks.Options setDefaultLocales(android.os.LocaleList);
method public android.view.textclassifier.TextLinks.Options setEntityConfig(android.view.textclassifier.TextClassifier.EntityConfig);
+ method public android.view.textclassifier.TextLinks.Options setSpanFactory(java.util.function.Function<android.view.textclassifier.TextLinks.TextLink, android.view.textclassifier.TextLinks.TextLinkSpan>);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.textclassifier.TextLinks.Options> CREATOR;
}
public static final class TextLinks.TextLink implements android.os.Parcelable {
- ctor public TextLinks.TextLink(java.lang.String, int, int, java.util.Map<java.lang.String, java.lang.Float>);
method public int describeContents();
method public float getConfidenceScore(java.lang.String);
method public int getEnd();
@@ -50050,13 +50246,22 @@
field public static final android.os.Parcelable.Creator<android.view.textclassifier.TextLinks.TextLink> CREATOR;
}
- public final class TextSelection {
+ public static class TextLinks.TextLinkSpan extends android.text.style.ClickableSpan {
+ ctor public TextLinks.TextLinkSpan(android.view.textclassifier.TextLinks.TextLink);
+ method public final android.view.textclassifier.TextLinks.TextLink getTextLink();
+ method public void onClick(android.view.View);
+ }
+
+ public final class TextSelection implements android.os.Parcelable {
+ method public int describeContents();
method public float getConfidenceScore(java.lang.String);
method public java.lang.String getEntity(int);
method public int getEntityCount();
method public int getSelectionEndIndex();
method public int getSelectionStartIndex();
method public java.lang.String getSignature();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.textclassifier.TextSelection> CREATOR;
}
public static final class TextSelection.Builder {
@@ -50077,6 +50282,75 @@
}
+package android.view.textclassifier.logging {
+
+ public abstract class Logger {
+ ctor public Logger(android.view.textclassifier.logging.Logger.Config);
+ method public java.text.BreakIterator getTokenIterator(java.util.Locale);
+ method public boolean isSmartSelection(java.lang.String);
+ method public final void logSelectionActionEvent(int, int, int);
+ method public final void logSelectionActionEvent(int, int, int, android.view.textclassifier.TextClassification);
+ method public final void logSelectionModifiedEvent(int, int);
+ method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextClassification);
+ method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextSelection);
+ method public final void logSelectionStartedEvent(int);
+ method public abstract void writeEvent(android.view.textclassifier.logging.SelectionEvent);
+ field public static final int OUT_OF_BOUNDS = 2147483647; // 0x7fffffff
+ field public static final int OUT_OF_BOUNDS_NEGATIVE = -2147483648; // 0x80000000
+ field public static final java.lang.String WIDGET_CUSTOM_EDITTEXT = "customedit";
+ field public static final java.lang.String WIDGET_CUSTOM_TEXTVIEW = "customview";
+ field public static final java.lang.String WIDGET_CUSTOM_UNSELECTABLE_TEXTVIEW = "nosel-customview";
+ field public static final java.lang.String WIDGET_EDITTEXT = "edittext";
+ field public static final java.lang.String WIDGET_EDIT_WEBVIEW = "edit-webview";
+ field public static final java.lang.String WIDGET_TEXTVIEW = "textview";
+ field public static final java.lang.String WIDGET_UNKNOWN = "unknown";
+ field public static final java.lang.String WIDGET_UNSELECTABLE_TEXTVIEW = "nosel-textview";
+ field public static final java.lang.String WIDGET_WEBVIEW = "webview";
+ }
+
+ public static final class Logger.Config {
+ ctor public Logger.Config(android.content.Context, java.lang.String, java.lang.String);
+ method public java.lang.String getPackageName();
+ method public java.lang.String getWidgetType();
+ method public java.lang.String getWidgetVersion();
+ }
+
+ public final class SelectionEvent {
+ method public long getDurationSincePreviousEvent();
+ method public long getDurationSinceSessionStart();
+ method public int getEnd();
+ method public java.lang.String getEntityType();
+ method public int getEventIndex();
+ method public long getEventTime();
+ method public int getEventType();
+ method public java.lang.String getPackageName();
+ method public java.lang.String getSessionId();
+ method public java.lang.String getSignature();
+ method public int getSmartEnd();
+ method public int getSmartStart();
+ method public int getStart();
+ method public java.lang.String getWidgetType();
+ method public java.lang.String getWidgetVersion();
+ field public static final int ACTION_ABANDON = 107; // 0x6b
+ field public static final int ACTION_COPY = 101; // 0x65
+ field public static final int ACTION_CUT = 103; // 0x67
+ field public static final int ACTION_DRAG = 106; // 0x6a
+ field public static final int ACTION_OTHER = 108; // 0x6c
+ field public static final int ACTION_OVERTYPE = 100; // 0x64
+ field public static final int ACTION_PASTE = 102; // 0x66
+ field public static final int ACTION_RESET = 201; // 0xc9
+ field public static final int ACTION_SELECT_ALL = 200; // 0xc8
+ field public static final int ACTION_SHARE = 104; // 0x68
+ field public static final int ACTION_SMART_SHARE = 105; // 0x69
+ field public static final int EVENT_AUTO_SELECTION = 5; // 0x5
+ field public static final int EVENT_SELECTION_MODIFIED = 2; // 0x2
+ field public static final int EVENT_SELECTION_STARTED = 1; // 0x1
+ field public static final int EVENT_SMART_SELECTION_MULTI = 4; // 0x4
+ field public static final int EVENT_SMART_SELECTION_SINGLE = 3; // 0x3
+ }
+
+}
+
package android.view.textservice {
public final class SentenceSuggestionsInfo implements android.os.Parcelable {
@@ -50389,7 +50663,7 @@
ctor public URLUtil();
method public static java.lang.String composeSearchUrl(java.lang.String, java.lang.String, java.lang.String);
method public static byte[] decode(byte[]) throws java.lang.IllegalArgumentException;
- method public static final java.lang.String guessFileName(java.lang.String, java.lang.String, java.lang.String);
+ method public static java.lang.String guessFileName(java.lang.String, java.lang.String, java.lang.String);
method public static java.lang.String guessUrl(java.lang.String);
method public static boolean isAboutUrl(java.lang.String);
method public static boolean isAssetUrl(java.lang.String);
@@ -52201,6 +52475,7 @@
ctor public Magnifier(android.view.View);
method public void dismiss();
method public void show(float, float);
+ method public void update();
}
public class MediaController extends android.widget.FrameLayout {
@@ -55457,7 +55732,7 @@
}
public static final class Character.UnicodeBlock extends java.lang.Character.Subset {
- method public static final java.lang.Character.UnicodeBlock forName(java.lang.String);
+ method public static java.lang.Character.UnicodeBlock forName(java.lang.String);
method public static java.lang.Character.UnicodeBlock of(char);
method public static java.lang.Character.UnicodeBlock of(int);
field public static final java.lang.Character.UnicodeBlock AEGEAN_NUMBERS;
@@ -55684,7 +55959,7 @@
}
public static final class Character.UnicodeScript extends java.lang.Enum {
- method public static final java.lang.Character.UnicodeScript forName(java.lang.String);
+ method public static java.lang.Character.UnicodeScript forName(java.lang.String);
method public static java.lang.Character.UnicodeScript of(int);
method public static java.lang.Character.UnicodeScript valueOf(java.lang.String);
method public static final java.lang.Character.UnicodeScript[] values();
@@ -57347,6 +57622,7 @@
method public boolean enqueue();
method public T get();
method public boolean isEnqueued();
+ method public static void reachabilityFence(java.lang.Object);
}
public class ReferenceQueue<T> {
@@ -58499,8 +58775,8 @@
ctor public URL(java.net.URL, java.lang.String) throws java.net.MalformedURLException;
ctor public URL(java.net.URL, java.lang.String, java.net.URLStreamHandler) throws java.net.MalformedURLException;
method public java.lang.String getAuthority();
- method public final java.lang.Object getContent() throws java.io.IOException;
- method public final java.lang.Object getContent(java.lang.Class[]) throws java.io.IOException;
+ method public java.lang.Object getContent() throws java.io.IOException;
+ method public java.lang.Object getContent(java.lang.Class[]) throws java.io.IOException;
method public int getDefaultPort();
method public java.lang.String getFile();
method public java.lang.String getHost();
@@ -58513,7 +58789,7 @@
method public synchronized int hashCode();
method public java.net.URLConnection openConnection() throws java.io.IOException;
method public java.net.URLConnection openConnection(java.net.Proxy) throws java.io.IOException;
- method public final java.io.InputStream openStream() throws java.io.IOException;
+ method public java.io.InputStream openStream() throws java.io.IOException;
method public boolean sameFile(java.net.URL);
method public static void setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory);
method public java.lang.String toExternalForm();
@@ -63169,13 +63445,13 @@
method public int getOffset();
method public int next();
method public int previous();
- method public static final int primaryOrder(int);
+ method public static int primaryOrder(int);
method public void reset();
- method public static final short secondaryOrder(int);
+ method public static short secondaryOrder(int);
method public void setOffset(int);
method public void setText(java.lang.String);
method public void setText(java.text.CharacterIterator);
- method public static final short tertiaryOrder(int);
+ method public static short tertiaryOrder(int);
field public static final int NULLORDER = -1; // 0xffffffff
}
@@ -64456,7 +64732,7 @@
}
public final class HijrahDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
- method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.HijrahDate> atTime(java.time.LocalTime);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.HijrahDate> atTime(java.time.LocalTime);
method public static java.time.chrono.HijrahDate from(java.time.temporal.TemporalAccessor);
method public java.time.chrono.HijrahChronology getChronology();
method public java.time.chrono.HijrahEra getEra();
@@ -64543,7 +64819,7 @@
}
public final class JapaneseDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
- method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.JapaneseDate> atTime(java.time.LocalTime);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.JapaneseDate> atTime(java.time.LocalTime);
method public static java.time.chrono.JapaneseDate from(java.time.temporal.TemporalAccessor);
method public java.time.chrono.JapaneseChronology getChronology();
method public java.time.chrono.JapaneseEra getEra();
@@ -64599,7 +64875,7 @@
}
public final class MinguoDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
- method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.MinguoDate> atTime(java.time.LocalTime);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.MinguoDate> atTime(java.time.LocalTime);
method public static java.time.chrono.MinguoDate from(java.time.temporal.TemporalAccessor);
method public java.time.chrono.MinguoChronology getChronology();
method public java.time.chrono.MinguoEra getEra();
@@ -64652,7 +64928,7 @@
}
public final class ThaiBuddhistDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
- method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.ThaiBuddhistDate> atTime(java.time.LocalTime);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.ThaiBuddhistDate> atTime(java.time.LocalTime);
method public static java.time.chrono.ThaiBuddhistDate from(java.time.temporal.TemporalAccessor);
method public java.time.chrono.ThaiBuddhistChronology getChronology();
method public java.time.chrono.ThaiBuddhistEra getEra();
@@ -64704,8 +64980,8 @@
method public <T> T parse(java.lang.CharSequence, java.time.temporal.TemporalQuery<T>);
method public java.time.temporal.TemporalAccessor parseBest(java.lang.CharSequence, java.time.temporal.TemporalQuery<?>...);
method public java.time.temporal.TemporalAccessor parseUnresolved(java.lang.CharSequence, java.text.ParsePosition);
- method public static final java.time.temporal.TemporalQuery<java.time.Period> parsedExcessDays();
- method public static final java.time.temporal.TemporalQuery<java.lang.Boolean> parsedLeapSecond();
+ method public static java.time.temporal.TemporalQuery<java.time.Period> parsedExcessDays();
+ method public static java.time.temporal.TemporalQuery<java.lang.Boolean> parsedLeapSecond();
method public java.text.Format toFormat();
method public java.text.Format toFormat(java.time.temporal.TemporalQuery<?>);
method public java.time.format.DateTimeFormatter withChronology(java.time.chrono.Chronology);
@@ -66154,15 +66430,15 @@
method public java.lang.String getCountry();
method public static java.util.Locale getDefault();
method public static java.util.Locale getDefault(java.util.Locale.Category);
- method public final java.lang.String getDisplayCountry();
+ method public java.lang.String getDisplayCountry();
method public java.lang.String getDisplayCountry(java.util.Locale);
- method public final java.lang.String getDisplayLanguage();
+ method public java.lang.String getDisplayLanguage();
method public java.lang.String getDisplayLanguage(java.util.Locale);
- method public final java.lang.String getDisplayName();
+ method public java.lang.String getDisplayName();
method public java.lang.String getDisplayName(java.util.Locale);
method public java.lang.String getDisplayScript();
method public java.lang.String getDisplayScript(java.util.Locale);
- method public final java.lang.String getDisplayVariant();
+ method public java.lang.String getDisplayVariant();
method public java.lang.String getDisplayVariant(java.util.Locale);
method public java.lang.String getExtension(char);
method public java.util.Set<java.lang.Character> getExtensionKeys();
@@ -66183,7 +66459,6 @@
method public static synchronized void setDefault(java.util.Locale.Category, java.util.Locale);
method public java.util.Locale stripExtensions();
method public java.lang.String toLanguageTag();
- method public final java.lang.String toString();
field public static final java.util.Locale CANADA;
field public static final java.util.Locale CANADA_FRENCH;
field public static final java.util.Locale CHINA;
@@ -70369,7 +70644,6 @@
public class ExemptionMechanism {
ctor protected ExemptionMechanism(javax.crypto.ExemptionMechanismSpi, java.security.Provider, java.lang.String);
- method protected void finalize();
method public final byte[] genExemptionBlob() throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException;
method public final int genExemptionBlob(byte[]) throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException, javax.crypto.ShortBufferException;
method public final int genExemptionBlob(byte[], int) throws javax.crypto.ExemptionMechanismException, java.lang.IllegalStateException, javax.crypto.ShortBufferException;
diff --git a/api/removed.txt b/api/removed.txt
index 77088e5..2aab223 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -265,7 +265,6 @@
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
- method public deprecated boolean trySetQuietModeEnabled(boolean, android.os.UserHandle);
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 9127059..87269d0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -29,6 +29,7 @@
field public static final java.lang.String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
field public static final java.lang.String BIND_SETTINGS_SUGGESTIONS_SERVICE = "android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE";
+ field public static final java.lang.String BIND_TEXTCLASSIFIER_SERVICE = "android.permission.BIND_TEXTCLASSIFIER_SERVICE";
field public static final java.lang.String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
field public static final java.lang.String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE";
field public static final java.lang.String BLUETOOTH_PRIVILEGED = "android.permission.BLUETOOTH_PRIVILEGED";
@@ -310,8 +311,10 @@
ctor public InstantAppResolverService();
method public final void attachBaseContext(android.content.Context);
method public final android.os.IBinder onBind(android.content.Intent);
- method public void onGetInstantAppIntentFilter(int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback);
- method public void onGetInstantAppResolveInfo(int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback);
+ method public deprecated void onGetInstantAppIntentFilter(int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback);
+ method public void onGetInstantAppIntentFilter(android.content.Intent, int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback);
+ method public deprecated void onGetInstantAppResolveInfo(int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback);
+ method public void onGetInstantAppResolveInfo(android.content.Intent, int[], java.lang.String, android.app.InstantAppResolverService.InstantAppResolutionCallback);
}
public static final class InstantAppResolverService.InstantAppResolutionCallback {
@@ -781,6 +784,7 @@
field public static final java.lang.String NETWORK_SCORE_SERVICE = "network_score";
field public static final java.lang.String OEM_LOCK_SERVICE = "oem_lock";
field public static final java.lang.String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
+ field public static final java.lang.String SECURE_ELEMENT_SERVICE = "secure_element";
field public static final java.lang.String STATS_MANAGER = "stats";
field public static final java.lang.String SYSTEM_UPDATE_SERVICE = "system_update";
field public static final java.lang.String VR_SERVICE = "vrmanager";
@@ -818,13 +822,24 @@
field public static final java.lang.String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
field public static final java.lang.String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
field public static final java.lang.String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS";
+ field public static final java.lang.String EXTRA_CALLING_PACKAGE = "android.intent.extra.CALLING_PACKAGE";
field public static final java.lang.String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET";
+ field public static final java.lang.String EXTRA_INSTANT_APP_ACTION = "android.intent.extra.INSTANT_APP_ACTION";
+ field public static final java.lang.String EXTRA_INSTANT_APP_BUNDLES = "android.intent.extra.INSTANT_APP_BUNDLES";
+ field public static final java.lang.String EXTRA_INSTANT_APP_EXTRAS = "android.intent.extra.INSTANT_APP_EXTRAS";
+ field public static final java.lang.String EXTRA_INSTANT_APP_FAILURE = "android.intent.extra.INSTANT_APP_FAILURE";
+ field public static final java.lang.String EXTRA_INSTANT_APP_HOSTNAME = "android.intent.extra.INSTANT_APP_HOSTNAME";
+ field public static final java.lang.String EXTRA_INSTANT_APP_SUCCESS = "android.intent.extra.INSTANT_APP_SUCCESS";
+ field public static final java.lang.String EXTRA_INSTANT_APP_TOKEN = "android.intent.extra.INSTANT_APP_TOKEN";
+ field public static final java.lang.String EXTRA_LONG_VERSION_CODE = "android.intent.extra.LONG_VERSION_CODE";
field public static final java.lang.String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID";
field public static final java.lang.String EXTRA_PACKAGES = "android.intent.extra.PACKAGES";
field public static final java.lang.String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME";
field public static final java.lang.String EXTRA_REASON = "android.intent.extra.REASON";
field public static final java.lang.String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
field public static final java.lang.String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
+ field public static final java.lang.String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP";
+ field public static final java.lang.String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE";
}
public class IntentFilter implements android.os.Parcelable {
@@ -837,7 +852,9 @@
package android.content.pm {
public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+ method public boolean isInstantApp();
field public java.lang.String credentialProtectedDataDir;
+ field public int targetSandboxVersion;
}
public final class InstantAppInfo implements android.os.Parcelable {
@@ -867,6 +884,7 @@
ctor public InstantAppResolveInfo(android.content.pm.InstantAppResolveInfo.InstantAppDigest, java.lang.String, java.util.List<android.content.pm.InstantAppIntentFilter>, int);
ctor public InstantAppResolveInfo(android.content.pm.InstantAppResolveInfo.InstantAppDigest, java.lang.String, java.util.List<android.content.pm.InstantAppIntentFilter>, long, android.os.Bundle);
ctor public InstantAppResolveInfo(java.lang.String, java.lang.String, java.util.List<android.content.pm.InstantAppIntentFilter>);
+ ctor public InstantAppResolveInfo(android.os.Bundle);
method public int describeContents();
method public byte[] getDigestBytes();
method public int getDigestPrefix();
@@ -875,6 +893,7 @@
method public long getLongVersionCode();
method public java.lang.String getPackageName();
method public deprecated int getVersionCode();
+ method public boolean shouldLetInstallerDecide();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.InstantAppResolveInfo> CREATOR;
}
@@ -886,6 +905,7 @@
method public int[] getDigestPrefix();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.InstantAppResolveInfo.InstantAppDigest> CREATOR;
+ field public static final android.content.pm.InstantAppResolveInfo.InstantAppDigest UNDEFINED;
}
public final class IntentFilterVerificationInfo implements android.os.Parcelable {
@@ -2595,12 +2615,17 @@
method public void onStatusChange();
}
+ public static abstract class AudioPolicy.AudioPolicyVolumeCallback {
+ method public void onVolumeAdjustment(int);
+ }
+
public static class AudioPolicy.Builder {
ctor public AudioPolicy.Builder(android.content.Context);
method public android.media.audiopolicy.AudioPolicy.Builder addMix(android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
method public android.media.audiopolicy.AudioPolicy build();
method public void setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener);
method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener);
+ method public android.media.audiopolicy.AudioPolicy.Builder setAudioPolicyVolumeCallback(android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback);
method public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean);
method public android.media.audiopolicy.AudioPolicy.Builder setLooper(android.os.Looper) throws java.lang.IllegalArgumentException;
}
@@ -2666,10 +2691,10 @@
package android.media.tv {
public final class TvContentRatingSystemInfo implements android.os.Parcelable {
- method public static final android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo);
+ method public static android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo);
method public int describeContents();
- method public final android.net.Uri getXmlUri();
- method public final boolean isSystemDefined();
+ method public android.net.Uri getXmlUri();
+ method public boolean isSystemDefined();
method public void writeToParcel(android.os.Parcel, int);
}
@@ -3523,12 +3548,17 @@
public class HidlSupport {
method public static boolean deepEquals(java.lang.Object, java.lang.Object);
method public static int deepHashCode(java.lang.Object);
+ method public static int getPidIfSharable();
method public static boolean interfacesEqual(android.os.IHwInterface, java.lang.Object);
}
public abstract class HwBinder implements android.os.IHwBinder {
method public static final void configureRpcThreadpool(long, boolean);
+ method public static void enableInstrumentation();
+ method public static final android.os.IHwBinder getService(java.lang.String, java.lang.String) throws java.util.NoSuchElementException, android.os.RemoteException;
+ method public static final android.os.IHwBinder getService(java.lang.String, java.lang.String, boolean) throws java.util.NoSuchElementException, android.os.RemoteException;
method public static final void joinRpcThreadpool();
+ method public final void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
}
public class HwBlob {
@@ -3628,6 +3658,8 @@
public abstract interface IHwBinder {
method public abstract boolean linkToDeath(android.os.IHwBinder.DeathRecipient, long);
+ method public abstract android.os.IHwInterface queryLocalInterface(java.lang.String);
+ method public abstract void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
method public abstract boolean unlinkToDeath(android.os.IHwBinder.DeathRecipient);
}
@@ -3826,6 +3858,20 @@
public static abstract class UserManager.UserRestrictionSource implements java.lang.annotation.Annotation {
}
+ public class WorkSource implements android.os.Parcelable {
+ method public android.os.WorkSource.WorkChain createWorkChain();
+ }
+
+ public static final class WorkSource.WorkChain implements android.os.Parcelable {
+ ctor public WorkSource.WorkChain();
+ method public android.os.WorkSource.WorkChain addNode(int, java.lang.String);
+ method public int describeContents();
+ method public java.lang.String getAttributionTag();
+ method public int getAttributionUid();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.os.WorkSource.WorkChain> CREATOR;
+ }
+
}
package android.os.storage {
@@ -4430,6 +4476,24 @@
}
+package android.service.textclassifier {
+
+ public abstract class TextClassifierService extends android.app.Service {
+ ctor public TextClassifierService();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ method public abstract void onClassifyText(java.lang.CharSequence, int, int, android.view.textclassifier.TextClassification.Options, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextClassification>);
+ method public abstract void onGenerateLinks(java.lang.CharSequence, android.view.textclassifier.TextLinks.Options, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLinks>);
+ method public abstract void onSuggestSelection(java.lang.CharSequence, int, int, android.view.textclassifier.TextSelection.Options, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextSelection>);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.textclassifier.TextClassifierService";
+ }
+
+ public static abstract interface TextClassifierService.Callback<T> {
+ method public abstract void onFailure(java.lang.CharSequence);
+ method public abstract void onSuccess(T);
+ }
+
+}
+
package android.service.trust {
public class TrustAgentService extends android.app.Service {
@@ -4611,15 +4675,15 @@
}
public final deprecated class Phone {
- method public final void addListener(android.telecom.Phone.Listener);
- method public final boolean canAddCall();
- method public final deprecated android.telecom.AudioState getAudioState();
- method public final android.telecom.CallAudioState getCallAudioState();
- method public final java.util.List<android.telecom.Call> getCalls();
- method public final void removeListener(android.telecom.Phone.Listener);
+ method public void addListener(android.telecom.Phone.Listener);
+ method public boolean canAddCall();
+ method public deprecated android.telecom.AudioState getAudioState();
+ method public android.telecom.CallAudioState getCallAudioState();
+ method public java.util.List<android.telecom.Call> getCalls();
+ method public void removeListener(android.telecom.Phone.Listener);
method public void requestBluetoothAudio(java.lang.String);
- method public final void setAudioRoute(int);
- method public final void setMuted(boolean);
+ method public void setAudioRoute(int);
+ method public void setMuted(boolean);
}
public static abstract class Phone.Listener {
@@ -4739,7 +4803,9 @@
method public int describeContents();
method public int getAccessNetworkTechnology();
method public int[] getAvailableServices();
+ method public android.telephony.CellIdentity getCellIdentity();
method public int getDomain();
+ method public int getReasonForDenial();
method public int getRegState();
method public int getTransportType();
method public boolean isEmergencyEnabled();
@@ -5065,16 +5131,669 @@
package android.telephony.ims {
+ public final class ImsCallForwardInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getCondition();
+ method public java.lang.String getNumber();
+ method public int getServiceClass();
+ method public int getStatus();
+ method public int getTimeSeconds();
+ method public int getToA();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR;
+ }
+
+ public final class ImsCallProfile implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getCallExtra(java.lang.String);
+ method public java.lang.String getCallExtra(java.lang.String, java.lang.String);
+ method public boolean getCallExtraBoolean(java.lang.String);
+ method public boolean getCallExtraBoolean(java.lang.String, boolean);
+ method public int getCallExtraInt(java.lang.String);
+ method public int getCallExtraInt(java.lang.String, int);
+ method public android.os.Bundle getCallExtras();
+ method public int getCallType();
+ method public static int getCallTypeFromVideoState(int);
+ method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
+ method public int getRestrictCause();
+ method public int getServiceType();
+ method public static int getVideoStateFromCallType(int);
+ method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
+ method public boolean isVideoCall();
+ method public boolean isVideoPaused();
+ method public static int presentationToOir(int);
+ method public void setCallExtra(java.lang.String, java.lang.String);
+ method public void setCallExtraBoolean(java.lang.String, boolean);
+ method public void setCallExtraInt(java.lang.String, int);
+ method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
+ method public void updateCallType(android.telephony.ims.ImsCallProfile);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2
+ field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
+ field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0
+ field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1
+ field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3
+ field public static final int CALL_TYPE_VOICE = 2; // 0x2
+ field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1
+ field public static final int CALL_TYPE_VS = 8; // 0x8
+ field public static final int CALL_TYPE_VS_RX = 10; // 0xa
+ field public static final int CALL_TYPE_VS_TX = 9; // 0x9
+ field public static final int CALL_TYPE_VT = 4; // 0x4
+ field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7
+ field public static final int CALL_TYPE_VT_RX = 6; // 0x6
+ field public static final int CALL_TYPE_VT_TX = 5; // 0x5
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR;
+ field public static final int DIALSTRING_NORMAL = 0; // 0x0
+ field public static final int DIALSTRING_SS_CONF = 1; // 0x1
+ field public static final int DIALSTRING_USSD = 2; // 0x2
+ field public static final java.lang.String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
+ field public static final java.lang.String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
+ field public static final java.lang.String EXTRA_CHILD_NUMBER = "ChildNum";
+ field public static final java.lang.String EXTRA_CNA = "cna";
+ field public static final java.lang.String EXTRA_CNAP = "cnap";
+ field public static final java.lang.String EXTRA_CODEC = "Codec";
+ field public static final java.lang.String EXTRA_DIALSTRING = "dialstring";
+ field public static final java.lang.String EXTRA_DISPLAY_TEXT = "DisplayText";
+ field public static final java.lang.String EXTRA_IS_CALL_PULL = "CallPull";
+ field public static final java.lang.String EXTRA_OI = "oi";
+ field public static final java.lang.String EXTRA_OIR = "oir";
+ field public static final java.lang.String EXTRA_REMOTE_URI = "remote_uri";
+ field public static final java.lang.String EXTRA_USSD = "ussd";
+ field public static final int OIR_DEFAULT = 0; // 0x0
+ field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2
+ field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4
+ field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1
+ field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3
+ field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2
+ field public static final int SERVICE_TYPE_NONE = 0; // 0x0
+ field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1
+ }
+
+ public class ImsCallSessionListener {
+ method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState);
+ method public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHeld(android.telephony.ims.ImsCallProfile);
+ method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionInitiated(android.telephony.ims.ImsCallProfile);
+ method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionInviteParticipantsRequestDelivered();
+ method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionMayHandover(int, int);
+ method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
+ method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionMultipartyStateChanged(boolean);
+ method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile);
+ method public void callSessionRemoveParticipantsRequestDelivered();
+ method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionResumed(android.telephony.ims.ImsCallProfile);
+ method public void callSessionRttMessageReceived(java.lang.String);
+ method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionRttModifyResponseReceived(int);
+ method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification);
+ method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionTtyModeReceived(int);
+ method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionUpdated(android.telephony.ims.ImsCallProfile);
+ method public void callSessionUssdMessageReceived(int, java.lang.String);
+ }
+
+ public final class ImsConferenceState implements android.os.Parcelable {
+ method public int describeContents();
+ method public static int getConnectionStateForStatus(java.lang.String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR;
+ field public static final java.lang.String DISPLAY_TEXT = "display-text";
+ field public static final java.lang.String ENDPOINT = "endpoint";
+ field public static final java.lang.String SIP_STATUS_CODE = "sipstatuscode";
+ field public static final java.lang.String STATUS = "status";
+ field public static final java.lang.String STATUS_ALERTING = "alerting";
+ field public static final java.lang.String STATUS_CONNECTED = "connected";
+ field public static final java.lang.String STATUS_CONNECT_FAIL = "connect-fail";
+ field public static final java.lang.String STATUS_DIALING_IN = "dialing-in";
+ field public static final java.lang.String STATUS_DIALING_OUT = "dialing-out";
+ field public static final java.lang.String STATUS_DISCONNECTED = "disconnected";
+ field public static final java.lang.String STATUS_DISCONNECTING = "disconnecting";
+ field public static final java.lang.String STATUS_MUTED_VIA_FOCUS = "muted-via-focus";
+ field public static final java.lang.String STATUS_ON_HOLD = "on-hold";
+ field public static final java.lang.String STATUS_PENDING = "pending";
+ field public static final java.lang.String STATUS_SEND_ONLY = "sendonly";
+ field public static final java.lang.String STATUS_SEND_RECV = "sendrecv";
+ field public static final java.lang.String USER = "user";
+ field public final java.util.HashMap<java.lang.String, android.os.Bundle> mParticipants;
+ }
+
+ public final class ImsExternalCallState implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.net.Uri getAddress();
+ method public int getCallId();
+ method public int getCallState();
+ method public int getCallType();
+ method public boolean isCallHeld();
+ method public boolean isCallPullable();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_STATE_CONFIRMED = 1; // 0x1
+ field public static final int CALL_STATE_TERMINATED = 2; // 0x2
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
+ }
+
+ public final class ImsReasonInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getCode();
+ method public int getExtraCode();
+ method public java.lang.String getExtraMessage();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CODE_ACCESS_CLASS_BLOCKED = 1512; // 0x5e8
+ field public static final int CODE_ANSWERED_ELSEWHERE = 1014; // 0x3f6
+ field public static final int CODE_BLACKLISTED_CALL_ID = 506; // 0x1fa
+ field public static final int CODE_CALL_BARRED = 240; // 0xf0
+ field public static final int CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE = 1100; // 0x44c
+ field public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016; // 0x3f8
+ field public static final int CODE_CALL_PULL_OUT_OF_SYNC = 1015; // 0x3f7
+ field public static final int CODE_DATA_DISABLED = 1406; // 0x57e
+ field public static final int CODE_DATA_LIMIT_REACHED = 1405; // 0x57d
+ field public static final int CODE_DIAL_MODIFIED_TO_DIAL = 246; // 0xf6
+ field public static final int CODE_DIAL_MODIFIED_TO_DIAL_VIDEO = 247; // 0xf7
+ field public static final int CODE_DIAL_MODIFIED_TO_SS = 245; // 0xf5
+ field public static final int CODE_DIAL_MODIFIED_TO_USSD = 244; // 0xf4
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL = 248; // 0xf8
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 249; // 0xf9
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_SS = 250; // 0xfa
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_USSD = 251; // 0xfb
+ field public static final int CODE_ECBM_NOT_SUPPORTED = 901; // 0x385
+ field public static final int CODE_EMERGENCY_PERM_FAILURE = 364; // 0x16c
+ field public static final int CODE_EMERGENCY_TEMP_FAILURE = 363; // 0x16b
+ field public static final int CODE_EPDG_TUNNEL_ESTABLISH_FAILURE = 1400; // 0x578
+ field public static final int CODE_EPDG_TUNNEL_LOST_CONNECTION = 1402; // 0x57a
+ field public static final int CODE_EPDG_TUNNEL_REKEY_FAILURE = 1401; // 0x579
+ field public static final int CODE_FDN_BLOCKED = 241; // 0xf1
+ field public static final int CODE_IKEV2_AUTH_FAILURE = 1408; // 0x580
+ field public static final int CODE_IMEI_NOT_ACCEPTED = 243; // 0xf3
+ field public static final int CODE_IWLAN_DPD_FAILURE = 1300; // 0x514
+ field public static final int CODE_LOCAL_CALL_BUSY = 142; // 0x8e
+ field public static final int CODE_LOCAL_CALL_CS_RETRY_REQUIRED = 146; // 0x92
+ field public static final int CODE_LOCAL_CALL_DECLINE = 143; // 0x8f
+ field public static final int CODE_LOCAL_CALL_EXCEEDED = 141; // 0x8d
+ field public static final int CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED = 145; // 0x91
+ field public static final int CODE_LOCAL_CALL_TERMINATED = 148; // 0x94
+ field public static final int CODE_LOCAL_CALL_VCC_ON_PROGRESSING = 144; // 0x90
+ field public static final int CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED = 147; // 0x93
+ field public static final int CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE = 108; // 0x6c
+ field public static final int CODE_LOCAL_HO_NOT_FEASIBLE = 149; // 0x95
+ field public static final int CODE_LOCAL_ILLEGAL_ARGUMENT = 101; // 0x65
+ field public static final int CODE_LOCAL_ILLEGAL_STATE = 102; // 0x66
+ field public static final int CODE_LOCAL_IMS_SERVICE_DOWN = 106; // 0x6a
+ field public static final int CODE_LOCAL_INTERNAL_ERROR = 103; // 0x67
+ field public static final int CODE_LOCAL_LOW_BATTERY = 112; // 0x70
+ field public static final int CODE_LOCAL_NETWORK_IP_CHANGED = 124; // 0x7c
+ field public static final int CODE_LOCAL_NETWORK_NO_LTE_COVERAGE = 122; // 0x7a
+ field public static final int CODE_LOCAL_NETWORK_NO_SERVICE = 121; // 0x79
+ field public static final int CODE_LOCAL_NETWORK_ROAMING = 123; // 0x7b
+ field public static final int CODE_LOCAL_NOT_REGISTERED = 132; // 0x84
+ field public static final int CODE_LOCAL_NO_PENDING_CALL = 107; // 0x6b
+ field public static final int CODE_LOCAL_POWER_OFF = 111; // 0x6f
+ field public static final int CODE_LOCAL_SERVICE_UNAVAILABLE = 131; // 0x83
+ field public static final int CODE_LOW_BATTERY = 505; // 0x1f9
+ field public static final int CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED = 1403; // 0x57b
+ field public static final int CODE_MEDIA_INIT_FAILED = 401; // 0x191
+ field public static final int CODE_MEDIA_NOT_ACCEPTABLE = 403; // 0x193
+ field public static final int CODE_MEDIA_NO_DATA = 402; // 0x192
+ field public static final int CODE_MEDIA_UNSPECIFIED = 404; // 0x194
+ field public static final int CODE_MULTIENDPOINT_NOT_SUPPORTED = 902; // 0x386
+ field public static final int CODE_NETWORK_DETACH = 1513; // 0x5e9
+ field public static final int CODE_NETWORK_REJECT = 1504; // 0x5e0
+ field public static final int CODE_NETWORK_RESP_TIMEOUT = 1503; // 0x5df
+ field public static final int CODE_NO_VALID_SIM = 1501; // 0x5dd
+ field public static final int CODE_OEM_CAUSE_1 = 61441; // 0xf001
+ field public static final int CODE_OEM_CAUSE_10 = 61450; // 0xf00a
+ field public static final int CODE_OEM_CAUSE_11 = 61451; // 0xf00b
+ field public static final int CODE_OEM_CAUSE_12 = 61452; // 0xf00c
+ field public static final int CODE_OEM_CAUSE_13 = 61453; // 0xf00d
+ field public static final int CODE_OEM_CAUSE_14 = 61454; // 0xf00e
+ field public static final int CODE_OEM_CAUSE_15 = 61455; // 0xf00f
+ field public static final int CODE_OEM_CAUSE_2 = 61442; // 0xf002
+ field public static final int CODE_OEM_CAUSE_3 = 61443; // 0xf003
+ field public static final int CODE_OEM_CAUSE_4 = 61444; // 0xf004
+ field public static final int CODE_OEM_CAUSE_5 = 61445; // 0xf005
+ field public static final int CODE_OEM_CAUSE_6 = 61446; // 0xf006
+ field public static final int CODE_OEM_CAUSE_7 = 61447; // 0xf007
+ field public static final int CODE_OEM_CAUSE_8 = 61448; // 0xf008
+ field public static final int CODE_OEM_CAUSE_9 = 61449; // 0xf009
+ field public static final int CODE_RADIO_ACCESS_FAILURE = 1505; // 0x5e1
+ field public static final int CODE_RADIO_INTERNAL_ERROR = 1502; // 0x5de
+ field public static final int CODE_RADIO_LINK_FAILURE = 1506; // 0x5e2
+ field public static final int CODE_RADIO_LINK_LOST = 1507; // 0x5e3
+ field public static final int CODE_RADIO_OFF = 1500; // 0x5dc
+ field public static final int CODE_RADIO_RELEASE_ABNORMAL = 1511; // 0x5e7
+ field public static final int CODE_RADIO_RELEASE_NORMAL = 1510; // 0x5e6
+ field public static final int CODE_RADIO_SETUP_FAILURE = 1509; // 0x5e5
+ field public static final int CODE_RADIO_UPLINK_FAILURE = 1508; // 0x5e4
+ field public static final int CODE_REGISTRATION_ERROR = 1000; // 0x3e8
+ field public static final int CODE_REMOTE_CALL_DECLINE = 1404; // 0x57c
+ field public static final int CODE_SIP_ALTERNATE_EMERGENCY_CALL = 1514; // 0x5ea
+ field public static final int CODE_SIP_BAD_ADDRESS = 337; // 0x151
+ field public static final int CODE_SIP_BAD_REQUEST = 331; // 0x14b
+ field public static final int CODE_SIP_BUSY = 338; // 0x152
+ field public static final int CODE_SIP_CLIENT_ERROR = 342; // 0x156
+ field public static final int CODE_SIP_FORBIDDEN = 332; // 0x14c
+ field public static final int CODE_SIP_GLOBAL_ERROR = 362; // 0x16a
+ field public static final int CODE_SIP_NOT_ACCEPTABLE = 340; // 0x154
+ field public static final int CODE_SIP_NOT_FOUND = 333; // 0x14d
+ field public static final int CODE_SIP_NOT_REACHABLE = 341; // 0x155
+ field public static final int CODE_SIP_NOT_SUPPORTED = 334; // 0x14e
+ field public static final int CODE_SIP_REDIRECTED = 321; // 0x141
+ field public static final int CODE_SIP_REQUEST_CANCELLED = 339; // 0x153
+ field public static final int CODE_SIP_REQUEST_TIMEOUT = 335; // 0x14f
+ field public static final int CODE_SIP_SERVER_ERROR = 354; // 0x162
+ field public static final int CODE_SIP_SERVER_INTERNAL_ERROR = 351; // 0x15f
+ field public static final int CODE_SIP_SERVER_TIMEOUT = 353; // 0x161
+ field public static final int CODE_SIP_SERVICE_UNAVAILABLE = 352; // 0x160
+ field public static final int CODE_SIP_TEMPRARILY_UNAVAILABLE = 336; // 0x150
+ field public static final int CODE_SIP_USER_REJECTED = 361; // 0x169
+ field public static final int CODE_SUPP_SVC_CANCELLED = 1202; // 0x4b2
+ field public static final int CODE_SUPP_SVC_FAILED = 1201; // 0x4b1
+ field public static final int CODE_SUPP_SVC_REINVITE_COLLISION = 1203; // 0x4b3
+ field public static final int CODE_TIMEOUT_1XX_WAITING = 201; // 0xc9
+ field public static final int CODE_TIMEOUT_NO_ANSWER = 202; // 0xca
+ field public static final int CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE = 203; // 0xcb
+ field public static final int CODE_UNSPECIFIED = 0; // 0x0
+ field public static final int CODE_USER_DECLINE = 504; // 0x1f8
+ field public static final int CODE_USER_IGNORE = 503; // 0x1f7
+ field public static final int CODE_USER_NOANSWER = 502; // 0x1f6
+ field public static final int CODE_USER_TERMINATED = 501; // 0x1f5
+ field public static final int CODE_USER_TERMINATED_BY_REMOTE = 510; // 0x1fe
+ field public static final int CODE_UT_CB_PASSWORD_MISMATCH = 821; // 0x335
+ field public static final int CODE_UT_NETWORK_ERROR = 804; // 0x324
+ field public static final int CODE_UT_NOT_SUPPORTED = 801; // 0x321
+ field public static final int CODE_UT_OPERATION_NOT_ALLOWED = 803; // 0x323
+ field public static final int CODE_UT_SERVICE_UNAVAILABLE = 802; // 0x322
+ field public static final int CODE_UT_SS_MODIFIED_TO_DIAL = 822; // 0x336
+ field public static final int CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO = 825; // 0x339
+ field public static final int CODE_UT_SS_MODIFIED_TO_SS = 824; // 0x338
+ field public static final int CODE_UT_SS_MODIFIED_TO_USSD = 823; // 0x337
+ field public static final int CODE_WIFI_LOST = 1407; // 0x57f
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsReasonInfo> CREATOR;
+ field public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3; // 0x3
+ field public static final int EXTRA_CODE_CALL_RETRY_NORMAL = 1; // 0x1
+ field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2
+ field public static final java.lang.String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service";
+ }
+
public class ImsService extends android.app.Service {
ctor public ImsService();
+ method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
+ method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
+ method public void disableIms(int);
+ method public void enableIms(int);
+ method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+ method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+ method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
+ method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
+ method public void readyForFeatureCreation();
+ }
+
+ public final class ImsSsData implements android.os.Parcelable {
+ ctor public ImsSsData();
+ method public int describeContents();
+ method public boolean isTypeBarring();
+ method public boolean isTypeCf();
+ method public boolean isTypeClip();
+ method public boolean isTypeClir();
+ method public boolean isTypeColp();
+ method public boolean isTypeColr();
+ method public boolean isTypeCw();
+ method public boolean isTypeIcb();
+ method public boolean isTypeInterrogation();
+ method public boolean isTypeUnConditional();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR;
+ field public static final int SS_ACTIVATION = 0; // 0x0
+ field public static final int SS_ALL_BARRING = 18; // 0x12
+ field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3
+ field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5
+ field public static final int SS_ALL_TELESEVICES = 1; // 0x1
+ field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0
+ field public static final int SS_BAIC = 16; // 0x10
+ field public static final int SS_BAIC_ROAMING = 17; // 0x11
+ field public static final int SS_BAOC = 13; // 0xd
+ field public static final int SS_BAOIC = 14; // 0xe
+ field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf
+ field public static final int SS_CFU = 0; // 0x0
+ field public static final int SS_CFUT = 6; // 0x6
+ field public static final int SS_CF_ALL = 4; // 0x4
+ field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int SS_CF_BUSY = 1; // 0x1
+ field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3
+ field public static final int SS_CF_NO_REPLY = 2; // 0x2
+ field public static final int SS_CLIP = 7; // 0x7
+ field public static final int SS_CLIR = 8; // 0x8
+ field public static final int SS_CNAP = 11; // 0xb
+ field public static final int SS_COLP = 9; // 0x9
+ field public static final int SS_COLR = 10; // 0xa
+ field public static final int SS_DEACTIVATION = 1; // 0x1
+ field public static final int SS_ERASURE = 4; // 0x4
+ field public static final int SS_INCOMING_BARRING = 20; // 0x14
+ field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16
+ field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15
+ field public static final int SS_INTERROGATION = 2; // 0x2
+ field public static final int SS_OUTGOING_BARRING = 19; // 0x13
+ field public static final int SS_REGISTRATION = 3; // 0x3
+ field public static final int SS_SMS_SERVICES = 4; // 0x4
+ field public static final int SS_TELEPHONY = 2; // 0x2
+ field public static final int SS_WAIT = 12; // 0xc
+ }
+
+ public final class ImsSsInfo implements android.os.Parcelable {
+ ctor public ImsSsInfo();
+ method public int describeContents();
+ method public java.lang.String getIcbNum();
+ method public int getStatus();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
+ field public static final int DISABLED = 0; // 0x0
+ field public static final int ENABLED = 1; // 0x1
+ field public static final int NOT_REGISTERED = -1; // 0xffffffff
+ }
+
+ public final class ImsStreamMediaProfile implements android.os.Parcelable {
+ method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile);
+ method public int describeContents();
+ method public int getAudioDirection();
+ method public int getAudioQuality();
+ method public int getRttMode();
+ method public int getVideoDirection();
+ method public int getVideoQuality();
+ method public boolean isRttCall();
+ method public void setRttMode(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int AUDIO_QUALITY_AMR = 1; // 0x1
+ field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2
+ field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4
+ field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5
+ field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7
+ field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6
+ field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14
+ field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11
+ field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13
+ field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12
+ field public static final int AUDIO_QUALITY_G711A = 13; // 0xd
+ field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf
+ field public static final int AUDIO_QUALITY_G711U = 11; // 0xb
+ field public static final int AUDIO_QUALITY_G722 = 14; // 0xe
+ field public static final int AUDIO_QUALITY_G723 = 12; // 0xc
+ field public static final int AUDIO_QUALITY_G729 = 16; // 0x10
+ field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8
+ field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9
+ field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa
+ field public static final int AUDIO_QUALITY_NONE = 0; // 0x0
+ field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR;
+ field public static final int DIRECTION_INACTIVE = 0; // 0x0
+ field public static final int DIRECTION_INVALID = -1; // 0xffffffff
+ field public static final int DIRECTION_RECEIVE = 1; // 0x1
+ field public static final int DIRECTION_SEND = 2; // 0x2
+ field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3
+ field public static final int RTT_MODE_DISABLED = 0; // 0x0
+ field public static final int RTT_MODE_FULL = 1; // 0x1
+ field public static final int VIDEO_QUALITY_NONE = 0; // 0x0
+ field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1
+ field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2
+ field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4
+ field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8
+ field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10
+ }
+
+ public final class ImsSuppServiceNotification implements android.os.Parcelable {
+ ctor public ImsSuppServiceNotification(int, int, int, int, java.lang.String, java.lang.String[]);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR;
+ field public final int code;
+ field public final java.lang.String[] history;
+ field public final int index;
+ field public final int notificationType;
+ field public final java.lang.String number;
+ field public final int type;
+ }
+
+ public class ImsUtListener {
+ method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData);
+ method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]);
+ method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]);
+ method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]);
+ method public void onUtConfigurationQueried(int, android.os.Bundle);
+ method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo);
+ method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo);
+ method public void onUtConfigurationUpdated(int);
+ }
+
+ public abstract class ImsVideoCallProvider {
+ ctor public ImsVideoCallProvider();
+ method public void changeCallDataUsage(long);
+ method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
+ method public void changePeerDimensions(int, int);
+ method public void changeVideoQuality(int);
+ method public void handleCallSessionEvent(int);
+ method public abstract void onRequestCallDataUsage();
+ method public abstract void onRequestCameraCapabilities();
+ method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
+ method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
+ method public abstract void onSetCamera(java.lang.String);
+ method public void onSetCamera(java.lang.String, int);
+ method public abstract void onSetDeviceOrientation(int);
+ method public abstract void onSetDisplaySurface(android.view.Surface);
+ method public abstract void onSetPauseImage(android.net.Uri);
+ method public abstract void onSetPreviewSurface(android.view.Surface);
+ method public abstract void onSetZoom(float);
+ method public void receiveSessionModifyRequest(android.telecom.VideoProfile);
+ method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
}
}
-package android.telephony.ims.internal.stub {
+package android.telephony.ims.feature {
- public class SmsImplBase {
- ctor public SmsImplBase();
+ public final class CapabilityChangeRequest implements android.os.Parcelable {
+ method public void addCapabilitiesToDisableForTech(int, int);
+ method public void addCapabilitiesToEnableForTech(int, int);
+ method public int describeContents();
+ method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable();
+ method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR;
+ }
+
+ public static class CapabilityChangeRequest.CapabilityPair {
+ ctor public CapabilityChangeRequest.CapabilityPair(int, int);
+ method public int getCapability();
+ method public int getRadioTech();
+ }
+
+ public abstract class ImsFeature {
+ ctor public ImsFeature();
+ method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public abstract void onFeatureReady();
+ method public abstract void onFeatureRemoved();
+ method public final void setFeatureState(int);
+ field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff
+ field public static final int CAPABILITY_SUCCESS = 0; // 0x0
+ field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0
+ field public static final int FEATURE_MMTEL = 1; // 0x1
+ field public static final int FEATURE_RCS = 2; // 0x2
+ field public static final int STATE_INITIALIZING = 1; // 0x1
+ field public static final int STATE_READY = 2; // 0x2
+ field public static final int STATE_UNAVAILABLE = 0; // 0x0
+ }
+
+ protected static class ImsFeature.CapabilityCallbackProxy {
+ method public void onChangeCapabilityConfigurationError(int, int, int);
+ }
+
+ public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
+ ctor public MmTelFeature();
+ method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
+ method public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(android.telephony.ims.ImsCallProfile);
+ method public android.telephony.ims.stub.ImsEcbmImplBase getEcbm();
+ method public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint();
+ method public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation();
+ method public android.telephony.ims.stub.ImsUtImplBase getUt();
+ method public final void notifyCapabilitiesStatusChanged(android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
+ method public final void notifyIncomingCall(android.telephony.ims.stub.ImsCallSessionImplBase, android.os.Bundle);
+ method public final void notifyVoiceMessageCountUpdate(int);
+ method public void onFeatureReady();
+ method public void onFeatureRemoved();
+ method public boolean queryCapabilityConfiguration(int, int);
+ method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
+ method public void setUiTtyMode(int, android.os.Message);
+ method public int shouldProcessCall(java.lang.String[]);
+ field public static final int PROCESS_CALL_CSFB = 1; // 0x1
+ field public static final int PROCESS_CALL_EMERGENCY_CSFB = 2; // 0x2
+ field public static final int PROCESS_CALL_IMS = 0; // 0x0
+ }
+
+ public static class MmTelFeature.MmTelCapabilities {
+ ctor public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
+ ctor public MmTelFeature.MmTelCapabilities(int);
+ method public final void addCapabilities(int);
+ method public final boolean isCapable(int);
+ method public final void removeCapabilities(int);
+ field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8
+ field public static final int CAPABILITY_TYPE_UT = 4; // 0x4
+ field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2
+ field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1
+ }
+
+ public static abstract class MmTelFeature.MmTelCapabilities.MmTelCapability implements java.lang.annotation.Annotation {
+ }
+
+ public static abstract class MmTelFeature.ProcessCallResult implements java.lang.annotation.Annotation {
+ }
+
+ public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
+ ctor public RcsFeature();
+ method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public void onFeatureReady();
+ method public void onFeatureRemoved();
+ }
+
+}
+
+package android.telephony.ims.stub {
+
+ public class ImsCallSessionImplBase implements java.lang.AutoCloseable {
+ ctor public ImsCallSessionImplBase();
+ method public void accept(int, android.telephony.ims.ImsStreamMediaProfile);
+ method public void close();
+ method public void extendToConference(java.lang.String[]);
+ method public java.lang.String getCallId();
+ method public android.telephony.ims.ImsCallProfile getCallProfile();
+ method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider();
+ method public android.telephony.ims.ImsCallProfile getLocalCallProfile();
+ method public java.lang.String getProperty(java.lang.String);
+ method public android.telephony.ims.ImsCallProfile getRemoteCallProfile();
+ method public int getState();
+ method public void hold(android.telephony.ims.ImsStreamMediaProfile);
+ method public void inviteParticipants(java.lang.String[]);
+ method public boolean isInCall();
+ method public boolean isMultiparty();
+ method public void merge();
+ method public void reject(int);
+ method public void removeParticipants(java.lang.String[]);
+ method public void resume(android.telephony.ims.ImsStreamMediaProfile);
+ method public void sendDtmf(char, android.os.Message);
+ method public void sendRttMessage(java.lang.String);
+ method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile);
+ method public void sendRttModifyResponse(boolean);
+ method public void sendUssd(java.lang.String);
+ method public void setListener(android.telephony.ims.ImsCallSessionListener);
+ method public void setMute(boolean);
+ method public void start(java.lang.String, android.telephony.ims.ImsCallProfile);
+ method public void startConference(java.lang.String[], android.telephony.ims.ImsCallProfile);
+ method public void startDtmf(char);
+ method public void stopDtmf();
+ method public void terminate(int);
+ method public void update(int, android.telephony.ims.ImsStreamMediaProfile);
+ field public static final int USSD_MODE_NOTIFY = 0; // 0x0
+ field public static final int USSD_MODE_REQUEST = 1; // 0x1
+ }
+
+ public static class ImsCallSessionImplBase.State {
+ method public static java.lang.String toString(int);
+ field public static final int ESTABLISHED = 4; // 0x4
+ field public static final int ESTABLISHING = 3; // 0x3
+ field public static final int IDLE = 0; // 0x0
+ field public static final int INITIATED = 1; // 0x1
+ field public static final int INVALID = -1; // 0xffffffff
+ field public static final int NEGOTIATING = 2; // 0x2
+ field public static final int REESTABLISHING = 6; // 0x6
+ field public static final int RENEGOTIATING = 5; // 0x5
+ field public static final int TERMINATED = 8; // 0x8
+ field public static final int TERMINATING = 7; // 0x7
+ }
+
+ public class ImsConfigImplBase {
+ ctor public ImsConfigImplBase();
+ method public int getConfigInt(int);
+ method public java.lang.String getConfigString(int);
+ method public final void notifyProvisionedValueChanged(int, int);
+ method public final void notifyProvisionedValueChanged(int, java.lang.String);
+ method public int setConfig(int, int);
+ method public int setConfig(int, java.lang.String);
+ field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
+ field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0
+ field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public class ImsEcbmImplBase {
+ ctor public ImsEcbmImplBase();
+ method public final void enteredEcbm();
+ method public void exitEmergencyCallbackMode();
+ method public final void exitedEcbm();
+ }
+
+ public final class ImsFeatureConfiguration implements android.os.Parcelable {
+ ctor public ImsFeatureConfiguration();
+ method public int describeContents();
+ method public int[] getServiceFeatures();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
+ }
+
+ public static class ImsFeatureConfiguration.Builder {
+ ctor public ImsFeatureConfiguration.Builder();
+ method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int);
+ method public android.telephony.ims.stub.ImsFeatureConfiguration build();
+ }
+
+ public class ImsMultiEndpointImplBase {
+ ctor public ImsMultiEndpointImplBase();
+ method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
+ method public void requestImsExternalCallStateInfo();
+ }
+
+ public class ImsRegistrationImplBase {
+ ctor public ImsRegistrationImplBase();
+ method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
+ method public final void onRegistered(int);
+ method public final void onRegistering(int);
+ method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]);
+ method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
+ field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
+ field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
+ field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
+ }
+
+ public class ImsSmsImplBase {
+ ctor public ImsSmsImplBase();
method public void acknowledgeSms(int, int, int);
method public void acknowledgeSmsReport(int, int, int);
method public java.lang.String getSmsFormat();
@@ -5093,6 +5812,29 @@
field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1
}
+ public class ImsUtImplBase {
+ ctor public ImsUtImplBase();
+ method public void close();
+ method public int queryCallBarring(int);
+ method public int queryCallBarringForServiceClass(int, int);
+ method public int queryCallForward(int, java.lang.String);
+ method public int queryCallWaiting();
+ method public int queryClip();
+ method public int queryClir();
+ method public int queryColp();
+ method public int queryColr();
+ method public void setListener(android.telephony.ims.ImsUtListener);
+ method public int transact(android.os.Bundle);
+ method public int updateCallBarring(int, int, java.lang.String[]);
+ method public int updateCallBarringForServiceClass(int, int, java.lang.String[], int);
+ method public int updateCallForward(int, int, java.lang.String, int, int);
+ method public int updateCallWaiting(boolean, int);
+ method public int updateClip(boolean);
+ method public int updateClir(int);
+ method public int updateColp(boolean);
+ method public int updateColr(int);
+ }
+
}
package android.telephony.mbms {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index b63703d..48f43e0 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -1,13 +1,5 @@
package android.app {
- public abstract deprecated class EphemeralResolverService extends android.app.InstantAppResolverService {
- ctor public EphemeralResolverService();
- method public android.os.Looper getLooper();
- method public abstract deprecated java.util.List<android.content.pm.EphemeralResolveInfo> onEphemeralResolveInfoList(int[], int);
- method public android.content.pm.EphemeralResolveInfo onGetEphemeralIntentFilter(java.lang.String);
- method public java.util.List<android.content.pm.EphemeralResolveInfo> onGetEphemeralResolveInfo(int[]);
- }
-
public class Notification implements android.os.Parcelable {
method public static java.lang.Class<? extends android.app.Notification.Style> getNotificationStyleClass(java.lang.String);
}
@@ -31,10 +23,7 @@
public class Intent implements java.lang.Cloneable android.os.Parcelable {
field public static final deprecated java.lang.String ACTION_DEVICE_INITIALIZATION_WIZARD = "android.intent.action.DEVICE_INITIALIZATION_WIZARD";
- field public static final deprecated java.lang.String ACTION_EPHEMERAL_RESOLVER_SETTINGS = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
- field public static final deprecated java.lang.String ACTION_INSTALL_EPHEMERAL_PACKAGE = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
- field public static final deprecated java.lang.String ACTION_RESOLVE_EPHEMERAL_PACKAGE = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
field public static final deprecated java.lang.String ACTION_SERVICE_STATE = "android.intent.action.SERVICE_STATE";
field public static final deprecated java.lang.String EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR = "cdmaDefaultRoamingIndicator";
field public static final deprecated java.lang.String EXTRA_CDMA_ROAMING_INDICATOR = "cdmaRoamingIndicator";
@@ -62,45 +51,6 @@
}
-package android.content.pm {
-
- public final deprecated class EphemeralIntentFilter implements android.os.Parcelable {
- ctor public EphemeralIntentFilter(java.lang.String, java.util.List<android.content.IntentFilter>);
- method public int describeContents();
- method public java.util.List<android.content.IntentFilter> getFilters();
- method public java.lang.String getSplitName();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralIntentFilter> CREATOR;
- }
-
- public final deprecated class EphemeralResolveInfo implements android.os.Parcelable {
- ctor public deprecated EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List<android.content.IntentFilter>);
- ctor public deprecated EphemeralResolveInfo(android.content.pm.EphemeralResolveInfo.EphemeralDigest, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>);
- ctor public EphemeralResolveInfo(android.content.pm.EphemeralResolveInfo.EphemeralDigest, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>, int);
- ctor public EphemeralResolveInfo(java.lang.String, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>);
- method public int describeContents();
- method public byte[] getDigestBytes();
- method public int getDigestPrefix();
- method public deprecated java.util.List<android.content.IntentFilter> getFilters();
- method public java.util.List<android.content.pm.EphemeralIntentFilter> getIntentFilters();
- method public java.lang.String getPackageName();
- method public int getVersionCode();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralResolveInfo> CREATOR;
- field public static final java.lang.String SHA_ALGORITHM = "SHA-256";
- }
-
- public static final class EphemeralResolveInfo.EphemeralDigest implements android.os.Parcelable {
- ctor public EphemeralResolveInfo.EphemeralDigest(java.lang.String);
- method public int describeContents();
- method public byte[][] getDigestBytes();
- method public int[] getDigestPrefix();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralResolveInfo.EphemeralDigest> CREATOR;
- }
-
-}
-
package android.media.tv {
public final class TvInputManager {
diff --git a/api/test-current.txt b/api/test-current.txt
index 4e8f904..bf00343 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -565,6 +565,14 @@
method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception;
}
+ public final class DateTransformation extends android.service.autofill.InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
+ method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception;
+ }
+
+ public final class DateValueSanitizer extends android.service.autofill.InternalSanitizer implements android.os.Parcelable android.service.autofill.Sanitizer {
+ method public android.view.autofill.AutofillValue sanitize(android.view.autofill.AutofillValue);
+ }
+
public final class FillResponse implements android.os.Parcelable {
method public int getFlags();
}
@@ -599,7 +607,8 @@
}
public abstract interface ValueFinder {
- method public abstract java.lang.String findByAutofillId(android.view.autofill.AutofillId);
+ method public default java.lang.String findByAutofillId(android.view.autofill.AutofillId);
+ method public abstract android.view.autofill.AutofillValue findRawValueByAutofillId(android.view.autofill.AutofillId);
}
}
@@ -986,8 +995,8 @@
}
public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
- method public final void setActionButton(int);
- method public final void setButtonState(int);
+ method public void setActionButton(int);
+ method public void setButtonState(int);
}
public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index d1af71d..54785ca 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -66,9 +66,12 @@
namespace android {
static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
+static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
+static const char PRODUCT_ENCRYPTED_BOOTANIMATION_FILE[] = "/product/media/bootanimation-encrypted.zip";
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
+static const char PRODUCT_SHUTDOWNANIMATION_FILE[] = "/product/media/shutdownanimation.zip";
static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip";
static const char SYSTEM_DATA_DIR_PATH[] = "/data/system";
@@ -308,14 +311,20 @@
bool encryptedAnimation = atoi(decrypt) != 0 ||
!strcmp("trigger_restart_min_framework", decrypt);
- if (!mShuttingDown && encryptedAnimation &&
- (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
- mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE;
- return NO_ERROR;
+ if (!mShuttingDown && encryptedAnimation) {
+ static const char* encryptedBootFiles[] =
+ {PRODUCT_ENCRYPTED_BOOTANIMATION_FILE, SYSTEM_ENCRYPTED_BOOTANIMATION_FILE};
+ for (const char* f : encryptedBootFiles) {
+ if (access(f, R_OK) == 0) {
+ mZipFileName = f;
+ return NO_ERROR;
+ }
+ }
}
- static const char* bootFiles[] = {OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};
+ static const char* bootFiles[] =
+ {PRODUCT_BOOTANIMATION_FILE, OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};
static const char* shutdownFiles[] =
- {OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE};
+ {PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE};
for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) {
if (access(f, R_OK) == 0) {
diff --git a/cmds/dpm/src/com/android/commands/dpm/Dpm.java b/cmds/dpm/src/com/android/commands/dpm/Dpm.java
index 3ac70d6..47581e1 100644
--- a/cmds/dpm/src/com/android/commands/dpm/Dpm.java
+++ b/cmds/dpm/src/com/android/commands/dpm/Dpm.java
@@ -45,6 +45,7 @@
private static final String COMMAND_SET_DEVICE_OWNER = "set-device-owner";
private static final String COMMAND_SET_PROFILE_OWNER = "set-profile-owner";
private static final String COMMAND_REMOVE_ACTIVE_ADMIN = "remove-active-admin";
+ private static final String COMMAND_CLEAR_FREEZE_PERIOD_RECORD = "clear-freeze-period-record";
private IDevicePolicyManager mDevicePolicyManager;
private int mUserId = UserHandle.USER_SYSTEM;
@@ -75,7 +76,11 @@
"\n" +
"dpm remove-active-admin: Disables an active admin, the admin must have declared" +
" android:testOnly in the application in its manifest. This will also remove" +
- " device and profile owners\n");
+ " device and profile owners\n" +
+ "\n" +
+ "dpm " + COMMAND_CLEAR_FREEZE_PERIOD_RECORD + ": clears framework-maintained " +
+ "record of past freeze periods that the device went through. For use during " +
+ "feature development to prevent triggering restriction on setting freeze periods");
}
@Override
@@ -101,6 +106,9 @@
case COMMAND_REMOVE_ACTIVE_ADMIN:
runRemoveActiveAdmin();
break;
+ case COMMAND_CLEAR_FREEZE_PERIOD_RECORD:
+ runClearFreezePeriodRecord();
+ break;
default:
throw new IllegalArgumentException ("unknown command '" + command + "'");
}
@@ -190,6 +198,11 @@
+ mComponent.toShortString() + " for user " + mUserId);
}
+ private void runClearFreezePeriodRecord() throws RemoteException {
+ mDevicePolicyManager.clearSystemUpdatePolicyFreezePeriodRecord();
+ System.out.println("Success");
+ }
+
private ComponentName parseComponentName(String component) {
ComponentName cn = ComponentName.unflattenFromString(component);
if (cn == null) {
diff --git a/cmds/incident/main.cpp b/cmds/incident/main.cpp
index 519852d..cdec6a0 100644
--- a/cmds/incident/main.cpp
+++ b/cmds/incident/main.cpp
@@ -148,9 +148,19 @@
static int
get_dest(const char* arg)
{
- if (strcmp(arg, "LOCAL") == 0) return 0;
- if (strcmp(arg, "EXPLICIT") == 0) return 1;
- if (strcmp(arg, "AUTOMATIC") == 0) return 2;
+ if (strcmp(arg, "L") == 0
+ || strcmp(arg, "LOCAL") == 0) {
+ return DEST_LOCAL;
+ }
+ if (strcmp(arg, "E") == 0
+ || strcmp(arg, "EXPLICIT") == 0) {
+ return DEST_EXPLICIT;
+ }
+ if (strcmp(arg, "A") == 0
+ || strcmp(arg, "AUTO") == 0
+ || strcmp(arg, "AUTOMATIC") == 0) {
+ return DEST_AUTOMATIC;
+ }
return -1; // return the default value
}
diff --git a/cmds/incidentd/src/Privacy.cpp b/cmds/incidentd/src/Privacy.cpp
index 5db2239..3f0e331 100644
--- a/cmds/incidentd/src/Privacy.cpp
+++ b/cmds/incidentd/src/Privacy.cpp
@@ -65,10 +65,19 @@
bool
PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; }
-PrivacySpec new_spec_from_args(int dest)
+PrivacySpec PrivacySpec::new_spec(int dest)
{
- if (dest < 0) return PrivacySpec();
- return PrivacySpec(dest);
+ switch (dest) {
+ case android::os::DEST_AUTOMATIC:
+ case android::os::DEST_EXPLICIT:
+ case android::os::DEST_LOCAL:
+ return PrivacySpec(dest);
+ default:
+ return PrivacySpec();
+ }
}
-PrivacySpec get_default_dropbox_spec() { return PrivacySpec(android::os::DEST_AUTOMATIC); }
\ No newline at end of file
+PrivacySpec PrivacySpec::get_default_dropbox_spec()
+{
+ return PrivacySpec(android::os::DEST_AUTOMATIC);
+}
diff --git a/cmds/incidentd/src/Privacy.h b/cmds/incidentd/src/Privacy.h
index 9e15ff4..4f3db67 100644
--- a/cmds/incidentd/src/Privacy.h
+++ b/cmds/incidentd/src/Privacy.h
@@ -65,8 +65,6 @@
const uint8_t dest;
PrivacySpec() : dest(DEST_DEFAULT_VALUE) {}
- PrivacySpec(uint8_t dest) : dest(dest) {}
-
bool operator<(const PrivacySpec& other) const;
// check permission of a policy, if returns true, don't strip the data.
@@ -74,9 +72,12 @@
// if returns true, no data need to be stripped.
bool RequireAll() const;
-};
-PrivacySpec new_spec_from_args(int dest);
-PrivacySpec get_default_dropbox_spec();
+ // Constructs spec using static methods below.
+ static PrivacySpec new_spec(int dest);
+ static PrivacySpec get_default_dropbox_spec();
+private:
+ PrivacySpec(uint8_t dest) : dest(dest) {}
+};
#endif // PRIVACY_H
diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp
index bd559d6..b9f479b 100644
--- a/cmds/incidentd/src/Reporter.cpp
+++ b/cmds/incidentd/src/Reporter.cpp
@@ -64,7 +64,8 @@
ReportRequestSet::ReportRequestSet()
:mRequests(),
mSections(),
- mMainFd(-1)
+ mMainFd(-1),
+ mMainDest(-1)
{
}
@@ -86,6 +87,12 @@
mMainFd = fd;
}
+void
+ReportRequestSet::setMainDest(int dest)
+{
+ mMainDest = dest;
+}
+
bool
ReportRequestSet::containsSection(int id) {
return mSections.containsSection(id);
@@ -125,12 +132,14 @@
status_t err = NO_ERROR;
bool needMainFd = false;
int mainFd = -1;
+ int mainDest = -1;
HeaderSection headers;
// See if we need the main file
for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) {
if ((*it)->fd < 0 && mainFd < 0) {
needMainFd = true;
+ mainDest = (*it)->args.dest();
break;
}
}
@@ -154,6 +163,7 @@
// Add to the set
batch.setMainFd(mainFd);
+ batch.setMainDest(mainDest);
}
// Tell everyone that we're starting.
diff --git a/cmds/incidentd/src/Reporter.h b/cmds/incidentd/src/Reporter.h
index 2615c62..f30ecf0 100644
--- a/cmds/incidentd/src/Reporter.h
+++ b/cmds/incidentd/src/Reporter.h
@@ -53,6 +53,7 @@
void add(const sp<ReportRequest>& request);
void setMainFd(int fd);
+ void setMainDest(int dest);
typedef vector<sp<ReportRequest>>::iterator iterator;
@@ -61,10 +62,12 @@
int mainFd() { return mMainFd; }
bool containsSection(int id);
+ int mainDest() { return mMainDest; }
private:
vector<sp<ReportRequest>> mRequests;
IncidentReportArgs mSections;
int mMainFd;
+ int mMainDest;
};
// ================================================================================
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 0827785..faeab87 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -152,36 +152,40 @@
// The streaming ones, group requests by spec in order to save unnecessary strip operations
map<PrivacySpec, vector<sp<ReportRequest>>> requestsBySpec;
- for (ReportRequestSet::iterator it = requests->begin(); it != requests->end(); it++) {
+ for (auto it = requests->begin(); it != requests->end(); it++) {
sp<ReportRequest> request = *it;
if (!request->ok() || !request->args.containsSection(id)) {
continue; // skip invalid request
}
- PrivacySpec spec = new_spec_from_args(request->args.dest());
+ PrivacySpec spec = PrivacySpec::new_spec(request->args.dest());
requestsBySpec[spec].push_back(request);
}
- for (map<PrivacySpec, vector<sp<ReportRequest>>>::iterator mit = requestsBySpec.begin(); mit != requestsBySpec.end(); mit++) {
+ for (auto mit = requestsBySpec.begin(); mit != requestsBySpec.end(); mit++) {
PrivacySpec spec = mit->first;
err = privacyBuffer.strip(spec);
if (err != NO_ERROR) return err; // it means the privacyBuffer data is corrupted.
if (privacyBuffer.size() == 0) continue;
- for (vector<sp<ReportRequest>>::iterator it = mit->second.begin(); it != mit->second.end(); it++) {
+ for (auto it = mit->second.begin(); it != mit->second.end(); it++) {
sp<ReportRequest> request = *it;
err = write_section_header(request->fd, id, privacyBuffer.size());
if (err != NO_ERROR) { request->err = err; continue; }
err = privacyBuffer.flush(request->fd);
if (err != NO_ERROR) { request->err = err; continue; }
writeable++;
- ALOGD("Section %d flushed %zu bytes to fd %d with spec %d", id, privacyBuffer.size(), request->fd, spec.dest);
+ ALOGD("Section %d flushed %zu bytes to fd %d with spec %d", id,
+ privacyBuffer.size(), request->fd, spec.dest);
}
privacyBuffer.clear();
}
// The dropbox file
if (requests->mainFd() >= 0) {
- err = privacyBuffer.strip(get_default_dropbox_spec());
+ PrivacySpec spec = requests->mainDest() < 0 ?
+ PrivacySpec::get_default_dropbox_spec() :
+ PrivacySpec::new_spec(requests->mainDest());
+ err = privacyBuffer.strip(spec);
if (err != NO_ERROR) return err; // the buffer data is corrupted.
if (privacyBuffer.size() == 0) goto DONE;
@@ -190,7 +194,8 @@
err = privacyBuffer.flush(requests->mainFd());
if (err != NO_ERROR) { requests->setMainFd(-1); goto DONE; }
writeable++;
- ALOGD("Section %d flushed %zu bytes to dropbox %d", id, privacyBuffer.size(), requests->mainFd());
+ ALOGD("Section %d flushed %zu bytes to dropbox %d with spec %d", id,
+ privacyBuffer.size(), requests->mainFd(), spec.dest);
}
DONE:
diff --git a/cmds/incidentd/tests/PrivacyBuffer_test.cpp b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
index 32b9e42..c7bfe55 100644
--- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp
+++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
@@ -73,7 +73,7 @@
}
void assertStrip(uint8_t dest, string expected, Privacy* policy) {
- PrivacySpec spec(dest);
+ PrivacySpec spec = PrivacySpec::new_spec(dest);
EncodedBuffer::iterator bufData = buffer.data();
PrivacyBuffer privacyBuf(policy, bufData);
ASSERT_EQ(privacyBuf.strip(spec), NO_ERROR);
@@ -224,7 +224,8 @@
Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
EncodedBuffer::iterator bufData = buffer.data();
PrivacyBuffer privacyBuf(create_message_privacy(300, list), bufData);
- PrivacySpec spec1(DEST_EXPLICIT), spec2(DEST_LOCAL);
+ PrivacySpec spec1 = PrivacySpec::new_spec(DEST_EXPLICIT);
+ PrivacySpec spec2 = PrivacySpec::new_spec(DEST_LOCAL);
ASSERT_EQ(privacyBuf.strip(spec1), NO_ERROR);
assertBuffer(privacyBuf, STRING_FIELD_0);
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 565b092..eabbb96 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -137,7 +137,7 @@
LOCAL_MODULE_CLASS := EXECUTABLES
-#LOCAL_INIT_RC := statsd.rc
+LOCAL_INIT_RC := statsd.rc
include $(BUILD_EXECUTABLE)
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index 288ebe9..857a6dd 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -69,18 +69,17 @@
using std::string;
-
string HashableDimensionKey::toString() const {
string flattened;
DimensionsValueToString(getDimensionsValue(), &flattened);
return flattened;
}
-bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2) {
+bool EqualsTo(const DimensionsValue& s1, const DimensionsValue& s2) {
if (s1.field() != s2.field()) {
return false;
}
- if (s1.value_case() != s1.value_case()) {
+ if (s1.value_case() != s2.value_case()) {
return false;
}
switch (s1.value_case()) {
@@ -102,8 +101,8 @@
}
bool allMatched = true;
for (int i = 0; allMatched && i < s1.value_tuple().dimensions_value_size(); ++i) {
- allMatched &= compareDimensionsValue(s1.value_tuple().dimensions_value(i),
- s2.value_tuple().dimensions_value(i));
+ allMatched &= EqualsTo(s1.value_tuple().dimensions_value(i),
+ s2.value_tuple().dimensions_value(i));
}
return allMatched;
}
@@ -113,12 +112,54 @@
}
}
+bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2) {
+ if (s1.field() != s2.field()) {
+ return s1.field() < s2.field();
+ }
+ if (s1.value_case() != s2.value_case()) {
+ return s1.value_case() < s2.value_case();
+ }
+ switch (s1.value_case()) {
+ case DimensionsValue::ValueCase::kValueStr:
+ return s1.value_str() < s2.value_str();
+ case DimensionsValue::ValueCase::kValueInt:
+ return s1.value_int() < s2.value_int();
+ case DimensionsValue::ValueCase::kValueLong:
+ return s1.value_long() < s2.value_long();
+ case DimensionsValue::ValueCase::kValueBool:
+ return (int)s1.value_bool() < (int)s2.value_bool();
+ case DimensionsValue::ValueCase::kValueFloat:
+ return s1.value_float() < s2.value_float();
+ case DimensionsValue::ValueCase::kValueTuple:
+ {
+ if (s1.value_tuple().dimensions_value_size() !=
+ s2.value_tuple().dimensions_value_size()) {
+ return s1.value_tuple().dimensions_value_size() <
+ s2.value_tuple().dimensions_value_size();
+ }
+ for (int i = 0; i < s1.value_tuple().dimensions_value_size(); ++i) {
+ if (EqualsTo(s1.value_tuple().dimensions_value(i),
+ s2.value_tuple().dimensions_value(i))) {
+ continue;
+ } else {
+ return LessThan(s1.value_tuple().dimensions_value(i),
+ s2.value_tuple().dimensions_value(i));
+ }
+ }
+ return false;
+ }
+ case DimensionsValue::ValueCase::VALUE_NOT_SET:
+ default:
+ return false;
+ }
+}
+
bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const {
- return compareDimensionsValue(getDimensionsValue(), that.getDimensionsValue());
+ return EqualsTo(getDimensionsValue(), that.getDimensionsValue());
};
bool HashableDimensionKey::operator<(const HashableDimensionKey& that) const {
- return toString().compare(that.toString()) < 0;
+ return LessThan(getDimensionsValue(), that.getDimensionsValue());
};
} // namespace statsd
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index edc9f2c..a4066aa 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -91,23 +91,22 @@
}
void StatsLogProcessor::mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const {
- std::vector<Field> uidFields;
+ std::set<Field, FieldCmp> uidFields;
if (android::util::kAtomsWithAttributionChain.find(event->GetTagId()) !=
android::util::kAtomsWithAttributionChain.end()) {
- findFields(
- event->getFieldValueMap(),
- buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY),
- &uidFields);
+ FieldMatcher matcher;
+ buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY, &matcher);
+ findFields(event->getFieldValueMap(), matcher, &uidFields);
} else if (android::util::kAtomsWithUidField.find(event->GetTagId()) !=
android::util::kAtomsWithUidField.end()) {
- findFields(
- event->getFieldValueMap(),
- buildSimpleAtomFieldMatcher(event->GetTagId(), 1 /* uid is always the 1st field. */),
- &uidFields);
+ FieldMatcher matcher;
+ buildSimpleAtomFieldMatcher(
+ event->GetTagId(), 1 /* uid is always the 1st field. */, &matcher);
+ findFields(event->getFieldValueMap(), matcher, &uidFields);
}
- for (size_t i = 0; i < uidFields.size(); ++i) {
- DimensionsValue* value = event->findFieldValueOrNull(uidFields[i]);
+ for (const auto& uidField : uidFields) {
+ DimensionsValue* value = event->findFieldValueOrNull(uidField);
if (value != nullptr && value->value_case() == DimensionsValue::ValueCase::kValueInt) {
const int uid = mUidMap->getHostUidOrSelf(value->value_int());
value->set_value_int(uid);
@@ -196,6 +195,14 @@
return it->second->byteSize();
}
+void StatsLogProcessor::dumpStates(FILE* out, bool verbose) {
+ std::lock_guard<std::mutex> lock(mMetricsMutex);
+ fprintf(out, "MetricsManager count: %lu\n", (unsigned long)mMetricsManagers.size());
+ for (auto metricsManager : mMetricsManagers) {
+ metricsManager.second->dumpStates(out, verbose);
+ }
+}
+
void StatsLogProcessor::onDumpReport(const ConfigKey& key, const uint64_t& dumpTimeStampNs,
ConfigMetricsReportList* report) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index fb85aa8..c19ff63 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -61,6 +61,8 @@
return mUidMap;
}
+ void dumpStates(FILE* out, bool verbose);
+
private:
mutable mutex mMetricsMutex;
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 31994e1..f545bb0 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -175,8 +175,13 @@
return NO_MEMORY; // the fd is already open
}
+ bool verbose = false;
+ if (args.size() > 0 && !args[0].compare(String16("-v"))) {
+ verbose = true;
+ }
+
// TODO: Proto format for incident reports
- dump_impl(out);
+ dump_impl(out, verbose);
fclose(out);
return NO_ERROR;
@@ -185,9 +190,9 @@
/**
* Write debugging data about statsd in text format.
*/
-void StatsService::dump_impl(FILE* out) {
- mConfigManager->Dump(out);
+void StatsService::dump_impl(FILE* out, bool verbose) {
StatsdStats::getInstance().dumpStats(out);
+ mProcessor->dumpStates(out, verbose);
}
/**
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index ba6bd24..be20893 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -140,7 +140,7 @@
/**
* Text output of dumpsys.
*/
- void dump_impl(FILE* out);
+ void dump_impl(FILE* out, bool verbose);
/**
* Print usage information for the commands
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index c990296..4e570a6 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -22,6 +22,10 @@
option java_outer_classname = "AtomsProto";
import "frameworks/base/core/proto/android/app/enums.proto";
+import "frameworks/base/core/proto/android/os/enums.proto";
+import "frameworks/base/core/proto/android/server/enums.proto";
+import "frameworks/base/core/proto/android/telephony/enums.proto";
+import "frameworks/base/core/proto/android/view/enums.proto";
/**
* The master atom class. This message defines all of the available
@@ -84,33 +88,38 @@
AppStartChanged app_start_changed = 48;
AppStartCancelChanged app_start_cancel_changed = 49;
AppStartFullyDrawnChanged app_start_fully_drawn_changed = 50;
- LmkEventOccurred lmk_event_occurred = 51;
+ LmkKillOccurred lmk_kill_occurred = 51;
PictureInPictureStateChanged picture_in_picture_state_changed = 52;
WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53;
+ LmkStateChanged lmk_state_changed = 54;
+ AppStartMemoryStateCaptured app_start_memory_state_captured = 55;
+ ShutdownSequenceReported shutdown_sequence_reported = 56;
+ BootSequenceReported boot_sequence_reported = 57;
// TODO: Reorder the numbering so that the most frequent occur events occur in the first 15.
}
// Pulled events will start at field 10000.
+ // Next: 10019
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000;
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
MobileBytesTransfer mobile_bytes_transfer = 10002;
MobileBytesTransferByFgBg mobile_bytes_transfer_by_fg_bg = 10003;
+ BluetoothBytesTransfer bluetooth_bytes_transfer = 10006;
KernelWakelock kernel_wakelock = 10004;
SubsystemSleepState subsystem_sleep_state = 10005;
- // 10006 and 10007 are free to use.
CpuTimePerFreq cpu_time_per_freq = 10008;
CpuTimePerUid cpu_time_per_uid = 10009;
CpuTimePerUidFreq cpu_time_per_uid_freq = 10010;
WifiActivityEnergyInfo wifi_activity_energy_info = 10011;
ModemActivityInfo modem_activity_info = 10012;
- ProcessMemoryStat process_memory_stat = 10013;
- CpuSuspendTime cpu_suspend_time = 10014;
- CpuIdleTime cpu_idle_time = 10015;
+ BluetoothActivityInfo bluetooth_activity_info = 10007;
+ ProcessMemoryState process_memory_state = 10013;
+ SystemElapsedRealtime system_elapsed_realtime = 10014;
+ SystemUptime system_uptime = 10015;
CpuActiveTime cpu_active_time = 10016;
CpuClusterTime cpu_cluster_time = 10017;
DiskSpace disk_space = 10018;
- SystemUptime system_uptime = 10019;
}
}
@@ -162,18 +171,8 @@
* frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message ScreenStateChanged {
- // TODO: Use the real screen state.
- enum State {
- STATE_UNKNOWN = 0;
- STATE_OFF = 1;
- STATE_ON = 2;
- STATE_DOZE = 3;
- STATE_DOZE_SUSPEND = 4;
- STATE_VR = 5;
- STATE_ON_SUSPEND = 6;
- }
- // New screen state.
- optional State display_state = 1;
+ // New screen state, from frameworks/base/core/proto/android/view/enums.proto.
+ optional android.view.DisplayStateEnum state = 1;
}
/**
@@ -196,7 +195,6 @@
* frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message ProcessLifeCycleStateChanged {
- // TODO: Use the real (mapped) process states.
optional int32 uid = 1; // TODO: should be a string tagged w/ uid annotation
// TODO: What is this?
@@ -412,13 +410,9 @@
message WakelockStateChanged {
repeated AttributionNode attribution_node = 1;
- // Type of wakelock.
- enum Type {
- PARTIAL = 0;
- FULL = 1;
- WINDOW = 2;
- }
- optional Type type = 2;
+ // The type (level) of the wakelock; e.g. a partial wakelock or a full wakelock.
+ // From frameworks/base/core/proto/android/os/enums.proto.
+ optional android.os.WakeLockLevelEnum level = 2;
// The wakelock tag (Called tag in the Java API, sometimes name elsewhere).
optional string tag = 3;
@@ -475,13 +469,7 @@
* frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
*/
message DeviceIdleModeStateChanged {
- // TODO: Use the enum matching BatteryStats.DEVICE_IDLE_MODE_.
- enum State {
- DEVICE_IDLE_MODE_OFF = 0;
- DEVICE_IDLE_MODE_LIGHT = 1;
- DEVICE_IDLE_MODE_DEEP = 2;
- }
- optional State state = 1;
+ optional android.server.DeviceIdleModeEnum state = 1;
}
@@ -492,13 +480,7 @@
* frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
*/
message DeviceIdlingModeStateChanged {
- // TODO: Use the enum matching BatteryStats.DEVICE_IDLE_MODE_.
- enum State {
- DEVICE_IDLE_MODE_OFF = 0;
- DEVICE_IDLE_MODE_LIGHT = 1;
- DEVICE_IDLE_MODE_DEEP = 2;
- }
- optional State state = 1;
+ optional android.server.DeviceIdleModeEnum state = 1;
}
/**
@@ -530,15 +512,8 @@
* frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
*/
message ChargingStateChanged {
- // TODO: Link directly to BatteryManager.java's constants (via a proto).
- enum State {
- BATTERY_STATUS_UNKNOWN = 1;
- BATTERY_STATUS_CHARGING = 2;
- BATTERY_STATUS_DISCHARGING = 3;
- BATTERY_STATUS_NOT_CHARGING = 4;
- BATTERY_STATUS_FULL = 5;
- }
- optional State charging_state = 1;
+ // State of the battery, from frameworks/base/core/proto/android/os/enums.proto.
+ optional android.os.BatteryStatusEnum state = 1;
}
/**
@@ -548,18 +523,8 @@
* frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
*/
message PluggedStateChanged {
- // TODO: Link directly to BatteryManager.java's constants (via a proto).
- enum State {
- // Note that NONE is not in BatteryManager.java's constants.
- BATTERY_PLUGGED_NONE = 0;
- // Power source is an AC charger.
- BATTERY_PLUGGED_AC = 1;
- // Power source is a USB port.
- BATTERY_PLUGGED_USB = 2;
- // Power source is wireless.
- BATTERY_PLUGGED_WIRELESS = 4;
- }
- optional State plugged_state = 1;
+ // Whether the device is plugged in, from frameworks/base/core/proto/android/os/enums.proto.
+ optional android.os.BatteryPluggedStateEnum state = 1;
}
/**
@@ -613,13 +578,8 @@
// TODO: Add attribution instead of uid?
optional int32 uid = 1;
- // TODO: Reference telephony/java/android/telephony/DataConnectionRealTimeInfo.java states.
- enum PowerState {
- DC_POWER_STATE_LOW = 1;
- DC_POWER_STATE_MEDIUM = 2;
- DC_POWER_STATE_HIGH = 3;
- }
- optional PowerState power_state = 2;
+ // Power state, from frameworks/base/core/proto/android/telephony/enums.proto.
+ optional android.telephony.DataConnectionPowerStateEnum state = 2;
}
/**
@@ -633,13 +593,8 @@
// TODO: Add attribution instead of uid?
optional int32 uid = 1;
- // TODO: Reference telephony/java/android/telephony/DataConnectionRealTimeInfo.java states.
- enum PowerState {
- DC_POWER_STATE_LOW = 1;
- DC_POWER_STATE_MEDIUM = 2;
- DC_POWER_STATE_HIGH = 3;
- }
- optional PowerState power_state = 2;
+ // Power state, from frameworks/base/core/proto/android/telephony/enums.proto.
+ optional android.telephony.DataConnectionPowerStateEnum state = 2;
}
/**
@@ -679,15 +634,8 @@
* frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
*/
message WifiSignalStrengthChanged {
- // TODO: Reference the actual telephony/java/android/telephony/SignalStrength.java states.
- enum SignalStrength {
- SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
- SIGNAL_STRENGTH_POOR = 1;
- SIGNAL_STRENGTH_MODERATE = 2;
- SIGNAL_STRENGTH_GOOD = 3;
- SIGNAL_STRENGTH_GREAT = 4;
- }
- optional SignalStrength signal_strength = 1;
+ // Signal strength, from frameworks/base/core/proto/android/telephony/enums.proto.
+ optional android.telephony.SignalStrengthEnum signal_strength = 1;
}
/**
@@ -723,21 +671,64 @@
}
/**
+ * Logs shutdown reason and duration on next boot.
+ *
+ * Logged from:
+ * frameworks/base/core/java/com/android/server/BootReceiver.java
+ */
+message ShutdownSequenceReported {
+ // True if shutdown is for a reboot. Default: false if we do not know.
+ optional bool reboot = 1;
+
+ // Reason for shutdown. Eg: userrequested. Default: "<EMPTY>".
+ optional string reason = 2;
+
+ // Beginning of shutdown time in ms using wall clock time since unix epoch.
+ // Default: 0 if no start time received.
+ optional int64 start_time_ms = 3;
+
+ // Duration of shutdown in ms. Default: 0 if no duration received.
+ optional int64 duration_ms = 4;
+}
+
+
+/**
+ * Logs boot reason and duration.
+ *
+ * Logged from:
+ * system/core/bootstat/bootstat.cpp
+ */
+message BootSequenceReported {
+ // Reason for bootloader boot. Eg. reboot. See bootstat.cpp for larger list
+ // Default: "<EMPTY>" if not available.
+ optional string bootloader_reason = 1;
+
+ // Reason for system boot. Eg. bootloader, reboot,userrequested
+ // Default: "<EMPTY>" if not available.
+ optional string system_reason = 2;
+
+ // End of boot time in ms from unix epoch using system wall clock.
+ optional int64 end_time_ms = 3;
+
+ // Total boot duration in ms.
+ optional int64 total_duration_ms = 4;
+
+ // Bootloader duration in ms.
+ optional int64 bootloader_duration_ms = 5;
+
+ // Time since last boot in ms. Default: 0 if not available.
+ optional int64 time_since_last_boot = 6;
+}
+
+/**
* Logs phone signal strength changes.
*
* Logged from:
* frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
*/
message PhoneSignalStrengthChanged {
- // TODO: Reference the actual telephony/java/android/telephony/SignalStrength.java states.
- enum SignalStrength {
- SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
- SIGNAL_STRENGTH_POOR = 1;
- SIGNAL_STRENGTH_MODERATE = 2;
- SIGNAL_STRENGTH_GOOD = 3;
- SIGNAL_STRENGTH_GREAT = 4;
- }
- optional SignalStrength signal_strength = 1;
+ // Signal strength, from frameworks/base/core/proto/android/telephony/enums.proto.
+ optional android.telephony.SignalStrengthEnum signal_strength = 1;
}
/**
@@ -890,15 +881,7 @@
// Device uptime when activity started.
optional int64 activity_start_msec = 7;
- // TODO: Update android/app/ActivityManagerInternal.java constants to depend on our proto enum.
- enum TransitionReason {
- APP_START_TRANSITION_REASON_UNKNOWN = 0;
- SPLASH_SCREEN = 1;
- WINDOWS_DRAWN = 2;
- TIMEOUT = 3;
- SNAPSHOT = 4;
- }
- optional TransitionReason reason = 8;
+ optional android.app.AppTransitionReasonEnum reason = 8;
optional int32 transition_delay_msec = 9;
// -1 if not set.
@@ -1060,6 +1043,20 @@
}
/**
+ * Pulls bytes transferred via bluetooth. It is pulled from Bluetooth controller.
+ *
+ * Pulled from:
+ * StatsCompanionService
+ */
+message BluetoothBytesTransfer {
+ optional int32 uid = 1;
+
+ optional int64 rx_bytes = 2;
+
+ optional int64 tx_bytes = 3;
+}
+
+/**
* Pulls the kernel wakelock durations. This atom is adapted from
* android/internal/os/KernelWakelockStats.java
*
@@ -1229,32 +1226,60 @@
optional uint64 energy_used = 10;
}
-/*
- * Logs the memory stats for a process
+/**
+ * Pulls Bluetooth Activity Energy Info
+ * Note: BluetoothBytesTransfer is pulled at the same time from the controller.
*/
-message ProcessMemoryStat {
+message BluetoothActivityInfo {
+ // timestamp(wall clock) of record creation
+ optional uint64 timestamp_ms = 1;
+ // bluetooth stack state
+ optional int32 bluetooth_stack_state = 2;
+ // tx time in ms
+ optional uint64 controller_tx_time_ms = 3;
+ // rx time in ms
+ optional uint64 controller_rx_time_ms = 4;
+ // idle time in ms
+ optional uint64 controller_idle_time_ms = 5;
+ // product of current(mA), voltage(V) and time(ms)
+ optional uint64 energy_used = 6;
+}
+
+/*
+ * Logs the memory stats for an app on startup.
+ * Logged from:
+ * frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+ */
+message AppStartMemoryStateCaptured {
// The uid if available. -1 means not available.
optional int32 uid = 1;
// The process name.
optional string process_name = 2;
+ // The activity name.
+ optional string activity_name = 3;
+
// # of page-faults
- optional int64 pgfault = 3;
+ optional int64 pgfault = 4;
// # of major page-faults
- optional int64 pgmajfault = 4;
+ optional int64 pgmajfault = 5;
- // RSS+CACHE(+SWAP)
- optional int64 usage_in_bytes = 5;
+ // RSS
+ optional int64 rss_in_bytes = 6;
+
+ // CACHE
+ optional int64 cache_in_bytes = 7;
+
+ // SWAP
+ optional int64 swap_in_bytes = 8;
}
/*
- * Logs the event when LMKD kills a process to reduce memory pressure
- * Logged from:
- * system/core/lmkd/lmkd.c
+ * Logs the memory stats for a process.
*/
-message LmkEventOccurred {
+message ProcessMemoryState {
// The uid if available. -1 means not available.
optional int32 uid = 1;
@@ -1270,22 +1295,78 @@
// # of major page-faults
optional int64 pgmajfault = 5;
- // RSS+CACHE(+SWAP)
- optional int64 usage_in_bytes = 6;
+ // RSS
+ optional int64 rss_in_bytes = 6;
+
+ // CACHE
+ optional int64 cache_in_bytes = 7;
+
+ // SWAP
+ optional int64 swap_in_bytes = 8;
}
/*
- * Cpu syspend time for cpu power calculation.
+ * Logs the change in Low Memory Killer Daemon (LMKD) state which is used as start/stop boundaries
+ * for LMK event.
+ * Logged from:
+ * system/core/lmkd/lmkd.c
*/
-message CpuSuspendTime {
- optional uint64 time = 1;
+message LmkStateChanged {
+ enum State {
+ UNKNOWN = 0;
+ START = 1;
+ STOP = 2;
+ }
+ optional State state = 1;
}
/*
- * Cpu idle time for cpu power calculation.
+ * Logs the event when Low Memory Killer Daemon (LMKD) kills a process to reduce memory pressure.
+ * Logged from:
+ * system/core/lmkd/lmkd.c
*/
-message CpuIdleTime {
- optional uint64 time = 1;
+message LmkKillOccurred {
+ // The uid if available. -1 means not available.
+ optional int32 uid = 1;
+
+ // The process name.
+ optional string process_name = 2;
+
+ // oom adj score.
+ optional int32 oom_score = 3;
+
+ // # of page-faults
+ optional int64 pgfault = 4;
+
+ // # of major page-faults
+ optional int64 pgmajfault = 5;
+
+ // RSS
+ optional int64 rss_in_bytes = 6;
+
+ // CACHE
+ optional int64 cache_in_bytes = 7;
+
+ // SWAP
+ optional int64 swap_in_bytes = 8;
+}
+
+/*
+ * Elapsed real time from SystemClock.
+ */
+message SystemElapsedRealtime {
+ optional uint64 time_ms = 1;
+}
+
+/*
+ * Up time from SystemClock.
+ */
+message SystemUptime {
+ // Milliseconds since the system was booted.
+ // This clock stops when the system enters deep sleep (CPU off, display dark, device waiting
+ // for external input).
+ // It is not affected by clock scaling, idle, or other power saving mechanisms.
+ optional uint64 uptime_ms = 1;
}
/*
@@ -1329,14 +1410,3 @@
// available bytes in download cache or temp directories
optional uint64 temp_available_bytes = 3;
}
-
-/*
- * Pulls system up time.
- */
-message SystemUptime {
- // Milliseconds since the system was booted.
- // This clock stops when the system enters deep sleep (CPU off, display dark, device waiting
- // for external input).
- // It is not affected by clock scaling, idle, or other power saving mechanisms.
- optional uint64 uptime_ms = 1;
-}
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index 7a1bb0c..5cfc349 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -289,7 +289,8 @@
}
// outputKey is the output values. e.g, uid:1234
- const std::vector<DimensionsValue> outputValues = getDimensionKeys(event, mOutputDimensions);
+ std::vector<DimensionsValue> outputValues;
+ getDimensionKeys(event, mOutputDimensions, &outputValues);
if (outputValues.size() == 0) {
// The original implementation would generate an empty string dimension hash when condition
// is not sliced.
diff --git a/cmds/statsd/src/condition/condition_util.cpp b/cmds/statsd/src/condition/condition_util.cpp
index ddfb8d1..3b2d480 100644
--- a/cmds/statsd/src/condition/condition_util.cpp
+++ b/cmds/statsd/src/condition/condition_util.cpp
@@ -116,28 +116,30 @@
}
}
-void getFieldsFromFieldMatcher(const FieldMatcher& matcher, const Field& parentField,
- std::vector<Field> *allFields) {
- Field newParent = parentField;
- Field* leaf = getSingleLeaf(&newParent);
- leaf->set_field(matcher.field());
+void getFieldsFromFieldMatcher(const FieldMatcher& matcher, Field* rootField, Field* leafField,
+ std::vector<Field> *allFields) {
if (matcher.child_size() == 0) {
- allFields->push_back(newParent);
+ allFields->push_back(*rootField);
return;
}
for (int i = 0; i < matcher.child_size(); ++i) {
- leaf->add_child();
- getFieldsFromFieldMatcher(matcher.child(i), newParent, allFields);
+ Field* newLeafField = leafField->add_child();
+ newLeafField->set_field(matcher.child(i).field());
+ getFieldsFromFieldMatcher(matcher.child(i), rootField, newLeafField, allFields);
}
}
void getFieldsFromFieldMatcher(const FieldMatcher& matcher, std::vector<Field> *allFields) {
- Field parentField;
- getFieldsFromFieldMatcher(matcher, parentField, allFields);
+ if (!matcher.has_field()) {
+ return;
+ }
+ Field rootField;
+ rootField.set_field(matcher.field());
+ getFieldsFromFieldMatcher(matcher, &rootField, &rootField, allFields);
}
void flattenValueLeaves(const DimensionsValue& value,
- std::vector<DimensionsValue> *allLaves) {
+ std::vector<const DimensionsValue*> *allLaves) {
switch (value.value_case()) {
case DimensionsValue::ValueCase::kValueStr:
case DimensionsValue::ValueCase::kValueInt:
@@ -145,7 +147,7 @@
case DimensionsValue::ValueCase::kValueBool:
case DimensionsValue::ValueCase::kValueFloat:
case DimensionsValue::ValueCase::VALUE_NOT_SET:
- allLaves->push_back(value);
+ allLaves->push_back(&value);
break;
case DimensionsValue::ValueCase::kValueTuple:
for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) {
@@ -155,45 +157,44 @@
}
}
-std::vector<HashableDimensionKey> getDimensionKeysForCondition(
- const LogEvent& event, const MetricConditionLink& link) {
+void getDimensionKeysForCondition(
+ const LogEvent& event, const MetricConditionLink& link,
+ std::vector<HashableDimensionKey> *hashableDimensionKeys) {
std::vector<Field> whatFields;
getFieldsFromFieldMatcher(link.fields_in_what(), &whatFields);
std::vector<Field> conditionFields;
getFieldsFromFieldMatcher(link.fields_in_condition(), &conditionFields);
- std::vector<HashableDimensionKey> hashableDimensionKeys;
-
// TODO(yanglu): here we could simplify the logic to get the leaf value node in what and
// directly construct the full condition value tree.
- std::vector<DimensionsValue> whatValues = getDimensionKeys(event, link.fields_in_what());
+ std::vector<DimensionsValue> whatValues;
+ getDimensionKeys(event, link.fields_in_what(), &whatValues);
for (size_t i = 0; i < whatValues.size(); ++i) {
- std::vector<DimensionsValue> whatLeaves;
+ std::vector<const DimensionsValue*> whatLeaves;
flattenValueLeaves(whatValues[i], &whatLeaves);
if (whatLeaves.size() != whatFields.size() ||
whatLeaves.size() != conditionFields.size()) {
ALOGE("Dimensions between what and condition not equal.");
- return hashableDimensionKeys;
+ return;
}
FieldValueMap conditionValueMap;
for (size_t j = 0; j < whatLeaves.size(); ++j) {
- if (!setFieldInLeafValueProto(conditionFields[j], &whatLeaves[j])) {
+ DimensionsValue* conditionValue = &conditionValueMap[conditionFields[j]];
+ *conditionValue = *whatLeaves[i];
+ if (!setFieldInLeafValueProto(conditionFields[j], conditionValue)) {
ALOGE("Not able to reset the field for condition leaf value.");
- return hashableDimensionKeys;
+ return;
}
- conditionValueMap.insert(std::make_pair(conditionFields[j], whatLeaves[j]));
}
- std::vector<DimensionsValue> conditionValues;
- findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValues);
- if (conditionValues.size() != 1) {
+ std::vector<DimensionsValue> conditionValueTrees;
+ findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValueTrees);
+ if (conditionValueTrees.size() != 1) {
ALOGE("Not able to find unambiguous field value in condition atom.");
continue;
}
- hashableDimensionKeys.push_back(HashableDimensionKey(conditionValues[0]));
+ hashableDimensionKeys->push_back(HashableDimensionKey(conditionValueTrees[0]));
}
-
- return hashableDimensionKeys;
}
} // namespace statsd
diff --git a/cmds/statsd/src/condition/condition_util.h b/cmds/statsd/src/condition/condition_util.h
index 598027b..a7288be 100644
--- a/cmds/statsd/src/condition/condition_util.h
+++ b/cmds/statsd/src/condition/condition_util.h
@@ -40,8 +40,9 @@
const LogicalOperation& operation,
const std::vector<ConditionState>& conditionCache);
-std::vector<HashableDimensionKey> getDimensionKeysForCondition(
- const LogEvent& event, const MetricConditionLink& link);
+void getDimensionKeysForCondition(
+ const LogEvent& event, const MetricConditionLink& link,
+ std::vector<HashableDimensionKey> *dimensionKeys);
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/dimension.cpp b/cmds/statsd/src/dimension.cpp
index bb7a044..04445ca 100644
--- a/cmds/statsd/src/dimension.cpp
+++ b/cmds/statsd/src/dimension.cpp
@@ -38,7 +38,7 @@
return *leafValue;
}
-void appendLeafNodeToParent(const Field& field,
+void appendLeafNodeToTree(const Field& field,
const DimensionsValue& value,
DimensionsValue* parentValue) {
if (field.child_size() <= 0) {
@@ -58,24 +58,24 @@
parentValue->mutable_value_tuple()->add_dimensions_value();
idx = parentValue->mutable_value_tuple()->dimensions_value_size() - 1;
}
- appendLeafNodeToParent(
+ appendLeafNodeToTree(
field.child(0), value,
parentValue->mutable_value_tuple()->mutable_dimensions_value(idx));
}
-void addNodeToRootDimensionsValues(const Field& field,
- const DimensionsValue& node,
- std::vector<DimensionsValue>* rootValues) {
- if (rootValues == nullptr) {
+void appendLeafNodeToTrees(const Field& field,
+ const DimensionsValue& node,
+ std::vector<DimensionsValue>* rootTrees) {
+ if (rootTrees == nullptr) {
return;
}
- if (rootValues->empty()) {
- DimensionsValue rootValue;
- appendLeafNodeToParent(field, node, &rootValue);
- rootValues->push_back(rootValue);
+ if (rootTrees->empty()) {
+ DimensionsValue tree;
+ appendLeafNodeToTree(field, node, &tree);
+ rootTrees->push_back(tree);
} else {
- for (size_t i = 0; i < rootValues->size(); ++i) {
- appendLeafNodeToParent(field, node, &rootValues->at(i));
+ for (size_t i = 0; i < rootTrees->size(); ++i) {
+ appendLeafNodeToTree(field, node, &rootTrees->at(i));
}
}
}
@@ -85,22 +85,25 @@
void findDimensionsValues(
const FieldValueMap& fieldValueMap,
const FieldMatcher& matcher,
- const Field& field,
+ Field* rootField,
+ Field* leafField,
std::vector<DimensionsValue>* rootDimensionsValues);
void findNonRepeatedDimensionsValues(
const FieldValueMap& fieldValueMap,
const FieldMatcher& matcher,
- const Field& field,
+ Field* rootField,
+ Field* leafField,
std::vector<DimensionsValue>* rootValues) {
if (matcher.child_size() > 0) {
+ Field* newLeafField = leafField->add_child();
for (const auto& childMatcher : matcher.child()) {
- Field childField = field;
- appendLeaf(&childField, childMatcher.field());
- findDimensionsValues(fieldValueMap, childMatcher, childField, rootValues);
+ newLeafField->set_field(childMatcher.field());
+ findDimensionsValues(fieldValueMap, childMatcher, rootField, newLeafField, rootValues);
}
+ leafField->clear_child();
} else {
- auto ret = fieldValueMap.equal_range(field);
+ auto ret = fieldValueMap.equal_range(*rootField);
int found = 0;
for (auto it = ret.first; it != ret.second; ++it) {
found++;
@@ -113,40 +116,43 @@
ALOGE("Found multiple values for optional field.");
return;
}
- addNodeToRootDimensionsValues(field, ret.first->second, rootValues);
+ appendLeafNodeToTrees(*rootField, ret.first->second, rootValues);
}
}
void findRepeatedDimensionsValues(const FieldValueMap& fieldValueMap,
const FieldMatcher& matcher,
- const Field& field,
+ Field* rootField,
+ Field* leafField,
std::vector<DimensionsValue>* rootValues) {
if (matcher.position() == Position::FIRST) {
- Field first_field = field;
- setPositionForLeaf(&first_field, 0);
- findNonRepeatedDimensionsValues(fieldValueMap, matcher, first_field, rootValues);
+ leafField->set_position_index(0);
+ findNonRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField, rootValues);
+ leafField->clear_position_index();
} else {
- auto itLower = fieldValueMap.lower_bound(field);
+ auto itLower = fieldValueMap.lower_bound(*rootField);
if (itLower == fieldValueMap.end()) {
return;
}
- Field next_field = field;
- getNextField(&next_field);
- auto itUpper = fieldValueMap.lower_bound(next_field);
+ const int leafFieldNum = leafField->field();
+ leafField->set_field(leafFieldNum + 1);
+ auto itUpper = fieldValueMap.lower_bound(*rootField);
+ // Resets the field number.
+ leafField->set_field(leafFieldNum);
switch (matcher.position()) {
case Position::LAST:
{
itUpper--;
if (itUpper != fieldValueMap.end()) {
- Field last_field = field;
- int last_index = getPositionByReferenceField(field, itUpper->first);
+ int last_index = getPositionByReferenceField(*rootField, itUpper->first);
if (last_index < 0) {
return;
}
- setPositionForLeaf(&last_field, last_index);
+ leafField->set_position_index(last_index);
findNonRepeatedDimensionsValues(
- fieldValueMap, matcher, last_field, rootValues);
+ fieldValueMap, matcher, rootField, leafField, rootValues);
+ leafField->clear_position_index();
}
}
break;
@@ -154,20 +160,20 @@
{
std::set<int> indexes;
for (auto it = itLower; it != itUpper; ++it) {
- int index = getPositionByReferenceField(field, it->first);
+ int index = getPositionByReferenceField(*rootField, it->first);
if (index >= 0) {
indexes.insert(index);
}
}
if (!indexes.empty()) {
- Field any_field = field;
std::vector<DimensionsValue> allValues;
for (const int index : indexes) {
- setPositionForLeaf(&any_field, index);
+ leafField->set_position_index(index);
std::vector<DimensionsValue> newValues = *rootValues;
findNonRepeatedDimensionsValues(
- fieldValueMap, matcher, any_field, &newValues);
+ fieldValueMap, matcher, rootField, leafField, &newValues);
allValues.insert(allValues.end(), newValues.begin(), newValues.end());
+ leafField->clear_position_index();
}
rootValues->clear();
rootValues->insert(rootValues->end(), allValues.begin(), allValues.end());
@@ -183,12 +189,15 @@
void findDimensionsValues(
const FieldValueMap& fieldValueMap,
const FieldMatcher& matcher,
- const Field& field,
+ Field* rootField,
+ Field* leafField,
std::vector<DimensionsValue>* rootDimensionsValues) {
if (!matcher.has_position()) {
- findNonRepeatedDimensionsValues(fieldValueMap, matcher, field, rootDimensionsValues);
+ findNonRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField,
+ rootDimensionsValues);
} else {
- findRepeatedDimensionsValues(fieldValueMap, matcher, field, rootDimensionsValues);
+ findRepeatedDimensionsValues(fieldValueMap, matcher, rootField, leafField,
+ rootDimensionsValues);
}
}
@@ -198,56 +207,49 @@
const FieldValueMap& fieldValueMap,
const FieldMatcher& matcher,
std::vector<DimensionsValue>* rootDimensionsValues) {
- findDimensionsValues(fieldValueMap, matcher,
- buildSimpleAtomField(matcher.field()), rootDimensionsValues);
+ Field rootField;
+ buildSimpleAtomField(matcher.field(), &rootField);
+ findDimensionsValues(fieldValueMap, matcher, &rootField, &rootField, rootDimensionsValues);
}
-FieldMatcher buildSimpleAtomFieldMatcher(const int tagId) {
- FieldMatcher matcher;
- matcher.set_field(tagId);
- return matcher;
+void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher) {
+ matcher->set_field(tagId);
}
-FieldMatcher buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum) {
- FieldMatcher matcher;
- matcher.set_field(tagId);
- matcher.add_child()->set_field(atomFieldNum);
- return matcher;
+void buildSimpleAtomFieldMatcher(const int tagId, const int fieldNum, FieldMatcher* matcher) {
+ matcher->set_field(tagId);
+ matcher->add_child()->set_field(fieldNum);
}
constexpr int ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO = 1;
constexpr int UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 1;
constexpr int TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO = 2;
-FieldMatcher buildAttributionUidFieldMatcher(const int tagId, const Position position) {
- FieldMatcher matcher;
- matcher.set_field(tagId);
- auto child = matcher.add_child();
+void buildAttributionUidFieldMatcher(const int tagId, const Position position,
+ FieldMatcher* matcher) {
+ matcher->set_field(tagId);
+ auto child = matcher->add_child();
child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
child->set_position(position);
child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
- return matcher;
}
-FieldMatcher buildAttributionTagFieldMatcher(const int tagId, const Position position) {
- FieldMatcher matcher;
- matcher.set_field(tagId);
- FieldMatcher* child = matcher.add_child();
+void buildAttributionTagFieldMatcher(const int tagId, const Position position,
+ FieldMatcher* matcher) {
+ matcher->set_field(tagId);
+ FieldMatcher* child = matcher->add_child();
child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
child->set_position(position);
child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
- return matcher;
}
-FieldMatcher buildAttributionFieldMatcher(const int tagId, const Position position) {
- FieldMatcher matcher;
- matcher.set_field(tagId);
- FieldMatcher* child = matcher.add_child();
+void buildAttributionFieldMatcher(const int tagId, const Position position, FieldMatcher* matcher) {
+ matcher->set_field(tagId);
+ FieldMatcher* child = matcher->add_child();
child->set_field(ATTRIBUTION_FIELD_NUM_IN_ATOM_PROTO);
child->set_position(position);
child->add_child()->set_field(UID_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
child->add_child()->set_field(TAG_FIELD_NUM_IN_ATTRIBUTION_NODE_PROTO);
- return matcher;
}
void DimensionsValueToString(const DimensionsValue& value, std::string *flattened) {
@@ -284,28 +286,6 @@
}
}
-void getDimensionsValueLeafNodes(
- const DimensionsValue& value, std::vector<DimensionsValue> *leafNodes) {
- switch (value.value_case()) {
- case DimensionsValue::ValueCase::kValueStr:
- case DimensionsValue::ValueCase::kValueInt:
- case DimensionsValue::ValueCase::kValueLong:
- case DimensionsValue::ValueCase::kValueBool:
- case DimensionsValue::ValueCase::kValueFloat:
- leafNodes->push_back(value);
- break;
- case DimensionsValue::ValueCase::kValueTuple:
- for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) {
- getDimensionsValueLeafNodes(value.value_tuple().dimensions_value(i), leafNodes);
- }
- break;
- case DimensionsValue::ValueCase::VALUE_NOT_SET:
- break;
- default:
- break;
- }
-}
-
std::string DimensionsValueToString(const DimensionsValue& value) {
std::string flatten;
DimensionsValueToString(value, &flatten);
diff --git a/cmds/statsd/src/dimension.h b/cmds/statsd/src/dimension.h
index d0f96a2..e900c5e 100644
--- a/cmds/statsd/src/dimension.h
+++ b/cmds/statsd/src/dimension.h
@@ -33,8 +33,7 @@
DimensionsValue getSingleLeafValue(const DimensionsValue& value);
// Appends the leaf node to the parent tree.
-void appendLeafNodeToParent(const Field& field, const DimensionsValue& value,
- DimensionsValue* parentValue);
+void appendLeafNodeToTree(const Field& field, const DimensionsValue& value, DimensionsValue* tree);
// Constructs the DimensionsValue protos from the FieldMatcher. Each DimensionsValue proto
// represents a tree. When the input proto has repeated fields and the input "dimensions" wants
@@ -45,13 +44,16 @@
std::vector<DimensionsValue>* rootDimensionsValues);
// Utils to build FieldMatcher proto for simple one-depth atoms.
-FieldMatcher buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum);
-FieldMatcher buildSimpleAtomFieldMatcher(const int tagId);
+void buildSimpleAtomFieldMatcher(const int tagId, const int atomFieldNum, FieldMatcher* matcher);
+void buildSimpleAtomFieldMatcher(const int tagId, FieldMatcher* matcher);
// Utils to build FieldMatcher proto for attribution nodes.
-FieldMatcher buildAttributionUidFieldMatcher(const int tagId, const Position position);
-FieldMatcher buildAttributionTagFieldMatcher(const int tagId, const Position position);
-FieldMatcher buildAttributionFieldMatcher(const int tagId, const Position position);
+void buildAttributionUidFieldMatcher(const int tagId, const Position position,
+ FieldMatcher* matcher);
+void buildAttributionTagFieldMatcher(const int tagId, const Position position,
+ FieldMatcher* matcher);
+void buildAttributionFieldMatcher(const int tagId, const Position position,
+ FieldMatcher* matcher);
// Utils to print pretty string for DimensionsValue proto.
std::string DimensionsValueToString(const DimensionsValue& value);
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
index e06ae48..148c9ae 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
@@ -64,12 +64,20 @@
mPullers.insert({android::util::CPU_TIME_PER_FREQ, make_shared<StatsCompanionServicePuller>(android::util::CPU_TIME_PER_FREQ)});
mPullers.insert({android::util::CPU_TIME_PER_UID, make_shared<CpuTimePerUidPuller>()});
mPullers.insert({android::util::CPU_TIME_PER_UID_FREQ, make_shared<CpuTimePerUidFreqPuller>()});
- mPullers.insert({android::util::CPU_SUSPEND_TIME, make_shared<StatsCompanionServicePuller>(android::util::CPU_SUSPEND_TIME)});
- mPullers.insert({android::util::CPU_IDLE_TIME, make_shared<StatsCompanionServicePuller>(android::util::CPU_IDLE_TIME)});
- mPullers.insert({android::util::DISK_SPACE,
- make_shared<StatsCompanionServicePuller>(android::util::DISK_SPACE)});
+ mPullers.insert(
+ {android::util::SYSTEM_ELAPSED_REALTIME,
+ make_shared<StatsCompanionServicePuller>(android::util::SYSTEM_ELAPSED_REALTIME)});
mPullers.insert({android::util::SYSTEM_UPTIME,
make_shared<StatsCompanionServicePuller>(android::util::SYSTEM_UPTIME)});
+ mPullers.insert({android::util::DISK_SPACE,
+ make_shared<StatsCompanionServicePuller>(android::util::DISK_SPACE)});
+ mPullers.insert(
+ {android::util::BLUETOOTH_ACTIVITY_INFO,
+ make_shared<StatsCompanionServicePuller>(android::util::BLUETOOTH_ACTIVITY_INFO)});
+
+ mPullers.insert(
+ {android::util::BLUETOOTH_BYTES_TRANSFER,
+ make_shared<StatsCompanionServicePuller>(android::util::BLUETOOTH_BYTES_TRANSFER)});
mPullers.insert(
{android::util::WIFI_ACTIVITY_ENERGY_INFO,
make_shared<StatsCompanionServicePuller>(android::util::WIFI_ACTIVITY_ENERGY_INFO)});
diff --git a/cmds/statsd/src/field_util.cpp b/cmds/statsd/src/field_util.cpp
index 4ff4f74..acf64fe 100644
--- a/cmds/statsd/src/field_util.cpp
+++ b/cmds/statsd/src/field_util.cpp
@@ -102,24 +102,13 @@
}
}
-Field buildAtomField(const int tagId, const Field &atomField) {
- Field field;
- *field.add_child() = atomField;
- field.set_field(tagId);
- return field;
+void buildSimpleAtomField(const int tagId, const int atomFieldNum, Field *field) {
+ field->set_field(tagId);
+ field->add_child()->set_field(atomFieldNum);
}
-Field buildSimpleAtomField(const int tagId, const int atomFieldNum) {
- Field field;
- field.set_field(tagId);
- field.add_child()->set_field(atomFieldNum);
- return field;
-}
-
-Field buildSimpleAtomField(const int tagId) {
- Field field;
- field.set_field(tagId);
- return field;
+void buildSimpleAtomField(const int tagId, Field *field) {
+ field->set_field(tagId);
}
void appendLeaf(Field *parent, int node_field_num) {
@@ -145,18 +134,6 @@
}
}
-
-void getNextField(Field* field) {
- if (field->child_size() <= 0) {
- field->set_field(field->field() + 1);
- return;
- }
- if (field->child_size() != 1) {
- return;
- }
- getNextField(field->mutable_child(0));
-}
-
void increasePosition(Field *field) {
if (!field->has_position_index()) {
field->set_position_index(0);
@@ -176,34 +153,30 @@
return getPositionByReferenceField(ref.child(0), field_with_index.child(0));
}
-void setPositionForLeaf(Field *field, int index) {
- if (field->child_size() <= 0) {
- field->set_position_index(index);
- } else {
- setPositionForLeaf(field->mutable_child(0), index);
- }
-}
-
namespace {
+
void findFields(
const FieldValueMap& fieldValueMap,
const FieldMatcher& matcher,
- const Field& field,
- std::vector<Field>* rootFields);
+ Field* rootField,
+ Field* leafField,
+ std::set<Field, FieldCmp>* rootFields);
void findNonRepeatedFields(
const FieldValueMap& fieldValueMap,
const FieldMatcher& matcher,
- const Field& field,
- std::vector<Field>* rootFields) {
+ Field* rootField,
+ Field* leafField,
+ std::set<Field, FieldCmp>* rootFields) {
if (matcher.child_size() > 0) {
+ Field* newLeafField = leafField->add_child();
for (const auto& childMatcher : matcher.child()) {
- Field childField = field;
- appendLeaf(&childField, childMatcher.field());
- findFields(fieldValueMap, childMatcher, childField, rootFields);
+ newLeafField->set_field(childMatcher.field());
+ findFields(fieldValueMap, childMatcher, rootField, newLeafField, rootFields);
}
+ leafField->clear_child();
} else {
- auto ret = fieldValueMap.equal_range(field);
+ auto ret = fieldValueMap.equal_range(*rootField);
int found = 0;
for (auto it = ret.first; it != ret.second; ++it) {
found++;
@@ -216,38 +189,42 @@
ALOGE("Found multiple values for optional field.");
return;
}
- rootFields->push_back(ret.first->first);
+ rootFields->insert(ret.first->first);
}
}
void findRepeatedFields(const FieldValueMap& fieldValueMap, const FieldMatcher& matcher,
- const Field& field, std::vector<Field>* rootFields) {
+ Field* rootField, Field* leafField,
+ std::set<Field, FieldCmp>* rootFields) {
if (matcher.position() == Position::FIRST) {
- Field first_field = field;
- setPositionForLeaf(&first_field, 0);
- findNonRepeatedFields(fieldValueMap, matcher, first_field, rootFields);
+ leafField->set_position_index(0);
+ findNonRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields);
+ leafField->clear_position_index();
} else {
- auto itLower = fieldValueMap.lower_bound(field);
+ auto itLower = fieldValueMap.lower_bound(*rootField);
if (itLower == fieldValueMap.end()) {
return;
}
- Field next_field = field;
- getNextField(&next_field);
- auto itUpper = fieldValueMap.lower_bound(next_field);
+
+ const int leafFieldNum = leafField->field();
+ leafField->set_field(leafFieldNum + 1);
+ auto itUpper = fieldValueMap.lower_bound(*rootField);
+ // Resets the field number.
+ leafField->set_field(leafFieldNum);
switch (matcher.position()) {
case Position::LAST:
{
itUpper--;
if (itUpper != fieldValueMap.end()) {
- Field last_field = field;
- int last_index = getPositionByReferenceField(field, itUpper->first);
+ int last_index = getPositionByReferenceField(*rootField, itUpper->first);
if (last_index < 0) {
return;
}
- setPositionForLeaf(&last_field, last_index);
+ leafField->set_position_index(last_index);
findNonRepeatedFields(
- fieldValueMap, matcher, last_field, rootFields);
+ fieldValueMap, matcher, rootField, leafField, rootFields);
+ leafField->clear_position_index();
}
}
break;
@@ -255,17 +232,17 @@
{
std::set<int> indexes;
for (auto it = itLower; it != itUpper; ++it) {
- int index = getPositionByReferenceField(field, it->first);
+ int index = getPositionByReferenceField(*rootField, it->first);
if (index >= 0) {
indexes.insert(index);
}
}
if (!indexes.empty()) {
- Field any_field = field;
for (const int index : indexes) {
- setPositionForLeaf(&any_field, index);
+ leafField->set_position_index(index);
findNonRepeatedFields(
- fieldValueMap, matcher, any_field, rootFields);
+ fieldValueMap, matcher, rootField, leafField, rootFields);
+ leafField->clear_position_index();
}
}
}
@@ -279,12 +256,13 @@
void findFields(
const FieldValueMap& fieldValueMap,
const FieldMatcher& matcher,
- const Field& field,
- std::vector<Field>* rootFields) {
+ Field* rootField,
+ Field* leafField,
+ std::set<Field, FieldCmp>* rootFields) {
if (!matcher.has_position()) {
- findNonRepeatedFields(fieldValueMap, matcher, field, rootFields);
+ findNonRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields);
} else {
- findRepeatedFields(fieldValueMap, matcher, field, rootFields);
+ findRepeatedFields(fieldValueMap, matcher, rootField, leafField, rootFields);
}
}
@@ -293,17 +271,24 @@
void findFields(
const FieldValueMap& fieldValueMap,
const FieldMatcher& matcher,
- std::vector<Field>* rootFields) {
- return findFields(fieldValueMap, matcher, buildSimpleAtomField(matcher.field()), rootFields);
+ std::set<Field, FieldCmp>* rootFields) {
+ if (!matcher.has_field() || fieldValueMap.empty()) {
+ return;
+ }
+ Field rootField;
+ buildSimpleAtomField(matcher.field(), &rootField);
+ return findFields(fieldValueMap, matcher, &rootField, &rootField, rootFields);
}
void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap) {
- std::vector<Field> rootFields;
+ if (!matcher.has_field()) {
+ return;
+ }
+ std::set<Field, FieldCmp> rootFields;
findFields(*fieldValueMap, matcher, &rootFields);
- std::set<Field, FieldCmp> rootFieldSet(rootFields.begin(), rootFields.end());
auto it = fieldValueMap->begin();
while (it != fieldValueMap->end()) {
- if (rootFieldSet.find(it->first) == rootFieldSet.end()) {
+ if (rootFields.find(it->first) == rootFields.end()) {
it = fieldValueMap->erase(it);
} else {
it++;
diff --git a/cmds/statsd/src/field_util.h b/cmds/statsd/src/field_util.h
index a4dfddd..b04465d 100644
--- a/cmds/statsd/src/field_util.h
+++ b/cmds/statsd/src/field_util.h
@@ -20,7 +20,8 @@
#include "frameworks/base/cmds/statsd/src/statsd_internal.pb.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
-#include <unordered_map>
+#include <map>
+#include <set>
namespace android {
namespace os {
@@ -54,15 +55,9 @@
void appendLeaf(Field *parent, int node_field_num);
void appendLeaf(Field *parent, int node_field_num, int position);
-// Given the field sorting logic, this function is to increase the "field" at the leaf node.
-void getNextField(Field* field);
-
// Increase the position index for the node. If the "position_index" is not set, set it as 0.
void increasePosition(Field *field);
-// Finds the leaf node and set the index there.
-void setPositionForLeaf(Field *field, int index);
-
// Returns true if the matcher has specified at least one leaf node.
bool hasLeafNode(const FieldMatcher& matcher);
@@ -72,15 +67,13 @@
int getPositionByReferenceField(const Field& reference, const Field& field_with_index);
// Utils to build the Field proto for simple atom fields.
-Field buildAtomField(const int tagId, const Field &atomField);
-Field buildSimpleAtomField(const int tagId, const int atomFieldNum);
-Field buildSimpleAtomField(const int tagId);
+void buildSimpleAtomField(const int tagId, const int atomFieldNum, Field* field);
+void buildSimpleAtomField(const int tagId, Field* field);
// Find out all the fields specified by the matcher.
void findFields(
- const FieldValueMap& fieldValueMap,
- const FieldMatcher& matcher,
- std::vector<Field>* rootFields);
+ const FieldValueMap& fieldValueMap, const FieldMatcher& matcher,
+ std::set<Field, FieldCmp>* rootFields);
// Filter out the fields not in the field matcher.
void filterFields(const FieldMatcher& matcher, FieldValueMap* fieldValueMap);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 63bde7d..77f5456 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -45,6 +45,8 @@
const int FIELD_ID_ATOM_STATS = 7;
const int FIELD_ID_UIDMAP_STATS = 8;
const int FIELD_ID_ANOMALY_ALARM_STATS = 9;
+const int FIELD_ID_PULLED_ATOM_STATS = 10;
+const int FIELD_ID_LOGGER_ERROR_STATS = 11;
const int FIELD_ID_MATCHER_STATS_NAME = 1;
const int FIELD_ID_MATCHER_STATS_COUNT = 2;
@@ -60,6 +62,9 @@
const int FIELD_ID_ANOMALY_ALARMS_REGISTERED = 1;
+const int FIELD_ID_LOGGER_STATS_TIME = 1;
+const int FIELD_ID_LOGGER_STATS_ERROR_CODE = 2;
+
std::map<int, long> StatsdStats::kPullerCooldownMap = {
{android::util::KERNEL_WAKELOCK, 1},
{android::util::WIFI_BYTES_TRANSFER, 1},
@@ -282,6 +287,15 @@
mPushedAtomStats[atomId]++;
}
+void StatsdStats::noteLoggerError(int error) {
+ lock_guard<std::mutex> lock(mLock);
+ // grows strictly one at a time. so it won't > kMaxLoggerErrors
+ if (mLoggerErrors.size() == kMaxLoggerErrors) {
+ mLoggerErrors.pop_front();
+ }
+ mLoggerErrors.push_back(std::make_pair(time(nullptr), error));
+}
+
void StatsdStats::reset() {
lock_guard<std::mutex> lock(mLock);
resetInternalLocked();
@@ -297,6 +311,7 @@
mAlertStats.clear();
mAnomalyAlarmRegisteredStats = 0;
mMatcherStats.clear();
+ mLoggerErrors.clear();
for (auto& config : mConfigStats) {
config.second.clear_broadcast_sent_time_sec();
config.second.clear_data_drop_time_sec();
@@ -465,6 +480,14 @@
"lost=%d\n",
mUidMapStats.bytes_used(), mUidMapStats.snapshots(), mUidMapStats.changes(),
mUidMapStats.dropped_snapshots(), mUidMapStats.dropped_changes());
+
+ for (const auto& error : mLoggerErrors) {
+ time_t error_time = error.first;
+ struct tm* error_tm = localtime(&error_time);
+ char buffer[80];
+ strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M%p\n", error_tm);
+ fprintf(out, "Logger error %d at %s\n", error.second, buffer);
+ }
}
void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
@@ -526,6 +549,14 @@
mUidMapStats.SerializeToArray(&buffer[0], numBytes);
proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UIDMAP_STATS, &buffer[0], buffer.size());
+ for (const auto& error : mLoggerErrors) {
+ long long token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_LOGGER_ERROR_STATS |
+ FIELD_COUNT_REPEATED);
+ proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOGGER_STATS_TIME, error.first);
+ proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOGGER_STATS_ERROR_CODE, error.second);
+ proto.end(token);
+ }
+
output->clear();
size_t bufferSize = proto.size();
output->resize(bufferSize);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 7cb48ea..1f4bfa6 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -49,6 +49,8 @@
// The max number of old config stats we keep.
const static int kMaxIceBoxSize = 20;
+ const static int kMaxLoggerErrors = 10;
+
const static int kMaxTimestampCount = 20;
const static int kMaxLogSourceCount = 50;
@@ -185,6 +187,11 @@
void notePullFromCache(int pullAtomId);
/**
+ * Records statsd met an error while reading from logd.
+ */
+ void noteLoggerError(int error);
+
+ /**
* Reset the historical stats. Including all stats in icebox, and the tracked stats about
* metrics, matchers, and atoms. The active configs will be kept and StatsdStats will continue
* to collect stats after reset() has been called.
@@ -246,6 +253,9 @@
// Maps PullAtomId to its stats. The size is capped by the puller atom counts.
std::map<int, PulledAtomStats> mPulledAtomStats;
+ // Logd errors. Size capped by kMaxLoggerErrors.
+ std::list<const std::pair<int, int>> mLoggerErrors;
+
// Stores the number of times statsd modified the anomaly alarm registered with
// StatsCompanionService.
int mAnomalyAlarmRegisteredStats = 0;
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 1ca793c..9e72f5b 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -198,7 +198,8 @@
int seenListStart = 0;
- Field field;
+ Field fieldTree;
+ Field* atomField = fieldTree.add_child();
do {
elem = android_log_read_next(context);
switch ((int)elem.type) {
@@ -206,51 +207,37 @@
// elem at [0] is EVENT_TYPE_LIST, [1] is the tag id.
if (i == 1) {
mTagId = elem.data.int32;
+ fieldTree.set_field(mTagId);
} else {
- increaseField(&field, seenListStart > 0/* is_child */);
- DimensionsValue dimensionsValue;
- dimensionsValue.set_value_int(elem.data.int32);
- setFieldInLeafValueProto(field, &dimensionsValue);
- mFieldValueMap.insert(
- std::make_pair(buildAtomField(mTagId, field), dimensionsValue));
+ increaseField(atomField, seenListStart > 0/* is_child */);
+ mFieldValueMap[fieldTree].set_value_int(elem.data.int32);
}
break;
case EVENT_TYPE_FLOAT:
{
- increaseField(&field, seenListStart > 0/* is_child */);
- DimensionsValue dimensionsValue;
- dimensionsValue.set_value_float(elem.data.float32);
- setFieldInLeafValueProto(field, &dimensionsValue);
- mFieldValueMap.insert(
- std::make_pair(buildAtomField(mTagId, field), dimensionsValue));
+ increaseField(atomField, seenListStart > 0/* is_child */);
+ mFieldValueMap[fieldTree].set_value_float(elem.data.float32);
}
break;
case EVENT_TYPE_STRING:
{
- increaseField(&field, seenListStart > 0/* is_child */);
- DimensionsValue dimensionsValue;
- dimensionsValue.set_value_str(string(elem.data.string, elem.len).c_str());
- setFieldInLeafValueProto(field, &dimensionsValue);
- mFieldValueMap.insert(
- std::make_pair(buildAtomField(mTagId, field), dimensionsValue));
+ increaseField(atomField, seenListStart > 0/* is_child */);
+ mFieldValueMap[fieldTree].set_value_str(
+ string(elem.data.string, elem.len).c_str());
}
break;
case EVENT_TYPE_LONG:
{
- increaseField(&field, seenListStart > 0 /* is_child */);
- DimensionsValue dimensionsValue;
- dimensionsValue.set_value_long(elem.data.int64);
- setFieldInLeafValueProto(field, &dimensionsValue);
- mFieldValueMap.insert(
- std::make_pair(buildAtomField(mTagId, field), dimensionsValue));
+ increaseField(atomField, seenListStart > 0 /* is_child */);
+ mFieldValueMap[fieldTree].set_value_long(elem.data.int64);
}
break;
case EVENT_TYPE_LIST:
if (i >= 1) {
if (seenListStart > 0) {
- increasePosition(&field);
+ increasePosition(atomField);
} else {
- increaseField(&field, false /* is_child */);
+ increaseField(atomField, false /* is_child */);
}
seenListStart++;
if (seenListStart >= 3) {
@@ -262,10 +249,10 @@
case EVENT_TYPE_LIST_STOP:
seenListStart--;
if (seenListStart == 0) {
- field.clear_position_index();
+ atomField->clear_position_index();
} else {
- if (field.child_size() > 0) {
- field.mutable_child(0)->clear_field();
+ if (atomField->child_size() > 0) {
+ atomField->mutable_child(0)->clear_field();
}
}
break;
@@ -393,14 +380,9 @@
bool LogEvent::GetSimpleAtomDimensionsValueProto(size_t atomField,
DimensionsValue* dimensionsValue) const {
- return GetAtomDimensionsValueProto(
- buildSimpleAtomFieldMatcher(mTagId, atomField), dimensionsValue);
-}
-
-DimensionsValue LogEvent::GetSimpleAtomDimensionsValueProto(size_t atomField) const {
- DimensionsValue dimensionsValue;
- GetSimpleAtomDimensionsValueProto(atomField, &dimensionsValue);
- return dimensionsValue;
+ FieldMatcher matcher;
+ buildSimpleAtomFieldMatcher(mTagId, atomField, &matcher);
+ return GetAtomDimensionsValueProto(matcher, dimensionsValue);
}
DimensionsValue* LogEvent::findFieldValueOrNull(const Field& field) {
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 5a4efd4..eb2c008 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -92,7 +92,6 @@
* Get a DimensionsValue proto objects from Field.
*/
bool GetSimpleAtomDimensionsValueProto(size_t field, DimensionsValue* dimensionsValue) const;
- DimensionsValue GetSimpleAtomDimensionsValueProto(size_t atomField) const;
/**
* Write test data to the LogEvent. This can only be used when the LogEvent is constructed
diff --git a/cmds/statsd/src/logd/LogReader.cpp b/cmds/statsd/src/logd/LogReader.cpp
index 5d43ef3..0fe896b 100644
--- a/cmds/statsd/src/logd/LogReader.cpp
+++ b/cmds/statsd/src/logd/LogReader.cpp
@@ -16,10 +16,11 @@
#include "logd/LogReader.h"
-#include <utils/Errors.h>
+#include "guardrail/StatsdStats.h"
#include <time.h>
#include <unistd.h>
+#include <utils/Errors.h>
using namespace android;
using namespace std;
@@ -92,16 +93,15 @@
// Read forever
if (eventLogger) {
-
+ log_msg msg;
while (true) {
- log_msg msg;
-
// Read a message
err = android_logger_list_read(loggers, &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
if (err <= 0) {
+ StatsdStats::getInstance().noteLoggerError(err);
fprintf(stderr, "logcat read failure: %s\n", strerror(err));
break;
}
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index 48f62e7..b6f440f 100644
--- a/cmds/statsd/src/matchers/matcher_util.cpp
+++ b/cmds/statsd/src/matchers/matcher_util.cpp
@@ -93,25 +93,28 @@
return matched;
}
-bool matchesNonRepeatedField(
- const UidMap& uidMap,
- const FieldValueMap& fieldMap,
- const FieldValueMatcher&matcher,
- const Field& field) {
+namespace {
+
+bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& fieldMap,
+ const FieldValueMatcher&matcher, Field* rootField, Field* leafField);
+
+bool matchesNonRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap,
+ const FieldValueMatcher&matcher, Field* rootField, Field* leafField) {
if (matcher.value_matcher_case() ==
FieldValueMatcher::ValueMatcherCase::VALUE_MATCHER_NOT_SET) {
return !fieldMap.empty() && fieldMap.begin()->first.field() == matcher.field();
} else if (matcher.value_matcher_case() == FieldValueMatcher::ValueMatcherCase::kMatchesTuple) {
bool allMatched = true;
+ Field* newLeafField = leafField->add_child();
for (int i = 0; allMatched && i < matcher.matches_tuple().field_value_matcher_size(); ++i) {
const auto& childMatcher = matcher.matches_tuple().field_value_matcher(i);
- Field childField = field;
- appendLeaf(&childField, childMatcher.field());
- allMatched &= matchFieldSimple(uidMap, fieldMap, childMatcher, childField);
+ newLeafField->set_field(childMatcher.field());
+ allMatched &= matchFieldSimple(uidMap, fieldMap, childMatcher, rootField, newLeafField);
}
+ leafField->clear_child();
return allMatched;
} else {
- auto ret = fieldMap.equal_range(field);
+ auto ret = fieldMap.equal_range(*rootField);
int found = 0;
for (auto it = ret.first; it != ret.second; ++it) {
found++;
@@ -132,7 +135,7 @@
break;
case FieldValueMatcher::ValueMatcherCase::kEqString:
{
- if (IsAttributionUidField(field)) {
+ if (IsAttributionUidField(*rootField)) {
const int uid = ret.first->second.value_int();
std::set<string> packageNames =
uidMap.getAppNamesFromUid(uid, true /* normalize*/);
@@ -171,19 +174,25 @@
}
bool matchesRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap,
- const FieldValueMatcher&matcher, const Field& field) {
+ const FieldValueMatcher&matcher,
+ Field* rootField, Field* leafField) {
if (matcher.position() == Position::FIRST) {
- Field first_field = field;
- setPositionForLeaf(&first_field, 0);
- return matchesNonRepeatedField(uidMap, fieldMap, matcher, first_field);
+ leafField->set_position_index(0);
+ bool res = matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField);
+ leafField->clear_position_index();
+ return res;
} else {
- auto itLower = fieldMap.lower_bound(field);
+ auto itLower = fieldMap.lower_bound(*rootField);
if (itLower == fieldMap.end()) {
return false;
}
- Field next_field = field;
- getNextField(&next_field);
- auto itUpper = fieldMap.lower_bound(next_field);
+
+ const int leafFieldNum = leafField->field();
+ leafField->set_field(leafFieldNum + 1);
+ auto itUpper = fieldMap.lower_bound(*rootField);
+ // Resets the field number.
+ leafField->set_field(leafFieldNum);
+
switch (matcher.position()) {
case Position::LAST:
{
@@ -191,30 +200,30 @@
if (itUpper == fieldMap.end()) {
return false;
} else {
- Field last_field = field;
- int last_index = getPositionByReferenceField(field, itUpper->first);
+ int last_index = getPositionByReferenceField(*rootField, itUpper->first);
if (last_index < 0) {
return false;
}
- setPositionForLeaf(&last_field, last_index);
- return matchesNonRepeatedField(uidMap, fieldMap, matcher, last_field);
+ leafField->set_position_index(last_index);
+ bool res = matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField);
+ leafField->clear_position_index();
+ return res;
}
}
break;
case Position::ANY:
{
- std::set<int> indexes;
- for (auto it = itLower; it != itUpper; ++it) {
- int index = getPositionByReferenceField(field, it->first);
- if (index >= 0) {
- indexes.insert(index);
- }
- }
bool matched = false;
- for (const int index : indexes) {
- Field any_field = field;
- setPositionForLeaf(&any_field, index);
- matched |= matchesNonRepeatedField(uidMap, fieldMap, matcher, any_field);
+ for (auto it = itLower; it != itUpper; ++it) {
+ int index = getPositionByReferenceField(*rootField, it->first);
+ if (index >= 0) {
+ leafField->set_position_index(index);
+ matched |= matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField);
+ leafField->clear_position_index();
+ if (matched) {
+ break;
+ }
+ }
}
return matched;
}
@@ -226,14 +235,16 @@
}
bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& fieldMap,
- const FieldValueMatcher&matcher, const Field& field) {
+ const FieldValueMatcher&matcher, Field* rootField, Field* leafField) {
if (!matcher.has_position()) {
- return matchesNonRepeatedField(uidMap, fieldMap, matcher, field);
+ return matchesNonRepeatedField(uidMap, fieldMap, matcher, rootField, leafField);
} else {
- return matchesRepeatedField(uidMap, fieldMap, matcher, field);
+ return matchesRepeatedField(uidMap, fieldMap, matcher, rootField, leafField);
}
}
+} // namespace
+
bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher,
const LogEvent& event) {
if (simpleMatcher.field_value_matcher_size() <= 0) {
@@ -247,13 +258,15 @@
*root_field_matcher.mutable_matches_tuple()->add_field_value_matcher() =
simpleMatcher.field_value_matcher(i);
}
- return matchFieldSimple(uidMap, event.getFieldValueMap(), root_field_matcher, root_field);
+ return matchFieldSimple(
+ uidMap, event.getFieldValueMap(), root_field_matcher, &root_field, &root_field);
}
-vector<DimensionsValue> getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher) {
- vector<DimensionsValue> values;
- findDimensionsValues(event.getFieldValueMap(), matcher, &values);
- return values;
+void getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher,
+ std::vector<DimensionsValue> *dimensionKeys) {
+ if (matcher.has_field()) {
+ findDimensionsValues(event.getFieldValueMap(), matcher, dimensionKeys);
+ }
}
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h
index 704cb4c..a45a9fb 100644
--- a/cmds/statsd/src/matchers/matcher_util.h
+++ b/cmds/statsd/src/matchers/matcher_util.h
@@ -42,13 +42,11 @@
bool combinationMatch(const std::vector<int>& children, const LogicalOperation& operation,
const std::vector<MatchingState>& matcherResults);
-bool matchFieldSimple(const UidMap& uidMap, const FieldValueMap& dimensionsMap,
- const FieldValueMatcher& matcher, const Field& field);
-
bool matchesSimple(const UidMap& uidMap,
const SimpleAtomMatcher& simpleMatcher, const LogEvent& wrapper);
-std::vector<DimensionsValue> getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher);
+void getDimensionKeys(const LogEvent& event, const FieldMatcher& matcher,
+ std::vector<DimensionsValue> *dimensionKeys);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 16fc7ee..061b7a3 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -68,6 +68,8 @@
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
+ void dumpStatesLocked(FILE* out, bool verbose) const override{};
+
// Util function to flush the old packet.
void flushIfNeededLocked(const uint64_t& newEventTime);
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index e26fe56..000874c 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -233,6 +233,21 @@
mCurrentBucketNum += numBucketsForward;
}
+void DurationMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
+ if (mCurrentSlicedDuration.size() == 0) {
+ return;
+ }
+
+ fprintf(out, "DurationMetric %lld dimension size %lu\n", (long long)mMetricId,
+ (unsigned long)mCurrentSlicedDuration.size());
+ if (verbose) {
+ for (const auto& slice : mCurrentSlicedDuration) {
+ fprintf(out, "\t%s\n", slice.first.c_str());
+ slice.second->dumpStates(out, verbose);
+ }
+ }
+}
+
bool DurationMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey) {
// the key is not new, we are good.
if (mCurrentSlicedDuration.find(newKey) != mCurrentSlicedDuration.end()) {
@@ -275,7 +290,8 @@
auto it = mCurrentSlicedDuration.find(eventKey);
- std::vector<DimensionsValue> values = getDimensionKeys(event, mInternalDimensions);
+ std::vector<DimensionsValue> values;
+ getDimensionKeys(event, mInternalDimensions, &values);
if (values.empty()) {
if (matcherIndex == mStartIndex) {
it->second->noteStart(DEFAULT_DIMENSION_KEY, condition,
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index e06b9a1..d8cab92 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -68,6 +68,8 @@
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
+ void dumpStatesLocked(FILE* out, bool verbose) const override;
+
// Util function to flush the old packet.
void flushIfNeededLocked(const uint64_t& eventTime);
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index a57b07d..9da0dd0 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -62,6 +62,8 @@
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
+ void dumpStatesLocked(FILE* out, bool verbose) const override{};
+
// Maps to a EventMetricDataWrapper. Storing atom events in ProtoOutputStream
// is more space efficient than storing LogEvent.
std::unique_ptr<android::util::ProtoOutputStream> mProto;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 24dc5b0..1072c5a 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -58,6 +58,7 @@
const int FIELD_ID_START_BUCKET_NANOS = 1;
const int FIELD_ID_END_BUCKET_NANOS = 2;
const int FIELD_ID_ATOM = 3;
+const int FIELD_ID_TIMESTAMP = 4;
GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
const int conditionIndex,
@@ -67,7 +68,7 @@
: MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
mStatsPullerManager(statsPullerManager),
mPullTagId(pullTagId) {
- mCurrentSlicedBucket = std::make_shared<DimToGaugeFieldsMap>();
+ mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>();
mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>();
int64_t bucketSizeMills = 0;
if (metric.has_bucket()) {
@@ -77,6 +78,7 @@
}
mBucketSizeNs = bucketSizeMills * 1000000;
+ mSamplingType = metric.sampling_type();
mFieldFilter = metric.gauge_fields_filter();
// TODO: use UidMap if uid->pkg_name is required
@@ -89,7 +91,7 @@
}
// Kicks off the puller immediately.
- if (mPullTagId != -1) {
+ if (mPullTagId != -1 && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
mStatsPullerManager->RegisterReceiver(mPullTagId, this, bucketSizeMills);
}
@@ -154,12 +156,23 @@
(long long)bucket.mBucketStartNs);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_BUCKET_NANOS,
(long long)bucket.mBucketEndNs);
- long long atomToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM);
- writeFieldValueTreeToStream(*bucket.mGaugeFields, protoOutput);
- protoOutput->end(atomToken);
+
+ if (!bucket.mGaugeAtoms.empty()) {
+ long long atomsToken =
+ protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ATOM);
+ for (const auto& atom : bucket.mGaugeAtoms) {
+ writeFieldValueTreeToStream(*atom.mFields, protoOutput);
+ }
+ protoOutput->end(atomsToken);
+
+ for (const auto& atom : bucket.mGaugeAtoms) {
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_TIMESTAMP,
+ (long long)atom.mTimestamps);
+ }
+ }
protoOutput->end(bucketInfoToken);
- VLOG("\t bucket [%lld - %lld] includes %d gauge fields.", (long long)bucket.mBucketStartNs,
- (long long)bucket.mBucketEndNs, (int)bucket.mGaugeFields->size());
+ VLOG("\t bucket [%lld - %lld] includes %d atoms.", (long long)bucket.mBucketStartNs,
+ (long long)bucket.mBucketEndNs, (int)bucket.mGaugeAtoms.size());
}
protoOutput->end(wrapperToken);
}
@@ -181,14 +194,26 @@
if (mPullTagId == -1) {
return;
}
- // No need to pull again. Either scheduled pull or condition on true happened
- if (!mCondition) {
+
+ bool triggerPuller = false;
+ switch(mSamplingType) {
+ // When the metric wants to do random sampling and there is already one gauge atom for the
+ // current bucket, do not do it again.
+ case GaugeMetric::RANDOM_ONE_SAMPLE: {
+ triggerPuller = mCondition && mCurrentSlicedBucket->empty();
+ break;
+ }
+ case GaugeMetric::ALL_CONDITION_CHANGES: {
+ triggerPuller = true;
+ break;
+ }
+ default:
+ break;
+ }
+ if (!triggerPuller) {
return;
}
- // Already have gauge metric for the current bucket, do not do it again.
- if (mCurrentSlicedBucket->size() > 0) {
- return;
- }
+
vector<std::shared_ptr<LogEvent>> allData;
if (!mStatsPullerManager->Pull(mPullTagId, &allData)) {
ALOGE("Stats puller failed for tag: %d", mPullTagId);
@@ -257,20 +282,24 @@
}
flushIfNeededLocked(eventTimeNs);
- // For gauge metric, we just simply use the first gauge in the given bucket.
- if (mCurrentSlicedBucket->find(eventKey) != mCurrentSlicedBucket->end()) {
+ // When gauge metric wants to randomly sample the output atom, we just simply use the first
+ // gauge in the given bucket.
+ if (mCurrentSlicedBucket->find(eventKey) != mCurrentSlicedBucket->end() &&
+ mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
return;
}
- std::shared_ptr<FieldValueMap> gaugeFields = getGaugeFields(event);
if (hitGuardRailLocked(eventKey)) {
return;
}
- (*mCurrentSlicedBucket)[eventKey] = gaugeFields;
+ GaugeAtom gaugeAtom;
+ gaugeAtom.mFields = getGaugeFields(event);
+ gaugeAtom.mTimestamps = eventTimeNs;
+ (*mCurrentSlicedBucket)[eventKey].push_back(gaugeAtom);
// Anomaly detection on gauge metric only works when there is one numeric
// field specified.
if (mAnomalyTrackers.size() > 0) {
- if (gaugeFields->size() == 1) {
- const DimensionsValue& dimensionsValue = gaugeFields->begin()->second;
+ if (gaugeAtom.mFields->size() == 1) {
+ const DimensionsValue& dimensionsValue = gaugeAtom.mFields->begin()->second;
long gaugeVal = 0;
if (dimensionsValue.has_value_int()) {
gaugeVal = (long)dimensionsValue.value_int();
@@ -289,7 +318,10 @@
mCurrentSlicedBucketForAnomaly->clear();
status_t err = NO_ERROR;
for (const auto& slice : *mCurrentSlicedBucket) {
- const DimensionsValue& dimensionsValue = slice.second->begin()->second;
+ if (slice.second.empty() || slice.second.front().mFields->empty()) {
+ continue;
+ }
+ const DimensionsValue& dimensionsValue = slice.second.front().mFields->begin()->second;
long gaugeVal = 0;
if (dimensionsValue.has_value_int()) {
gaugeVal = (long)dimensionsValue.value_int();
@@ -318,7 +350,7 @@
info.mBucketNum = mCurrentBucketNum;
for (const auto& slice : *mCurrentSlicedBucket) {
- info.mGaugeFields = slice.second;
+ info.mGaugeAtoms = slice.second;
auto& bucketList = mPastBuckets[slice.first];
bucketList.push_back(info);
VLOG("gauge metric %lld, dump key value: %s",
@@ -334,7 +366,7 @@
}
mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>();
- mCurrentSlicedBucket = std::make_shared<DimToGaugeFieldsMap>();
+ mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>();
// Adjusts the bucket start time
int64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index f267e98..6c01347 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -32,15 +32,20 @@
namespace os {
namespace statsd {
+struct GaugeAtom {
+ std::shared_ptr<FieldValueMap> mFields;
+ int64_t mTimestamps;
+};
+
struct GaugeBucket {
int64_t mBucketStartNs;
int64_t mBucketEndNs;
- std::shared_ptr<FieldValueMap> mGaugeFields;
+ std::vector<GaugeAtom> mGaugeAtoms;
uint64_t mBucketNum;
};
-typedef std::unordered_map<HashableDimensionKey, std::shared_ptr<FieldValueMap>>
- DimToGaugeFieldsMap;
+typedef std::unordered_map<HashableDimensionKey, std::vector<GaugeAtom>>
+ DimToGaugeAtomsMap;
// This gauge metric producer first register the puller to automatically pull the gauge at the
// beginning of each bucket. If the condition is met, insert it to the bucket info. Otherwise
@@ -48,7 +53,7 @@
// producer always reports the guage at the earliest time of the bucket when the condition is met.
class GaugeMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
public:
- GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& countMetric,
+ GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
const int pullTagId, const int64_t startTimeNs);
@@ -83,6 +88,8 @@
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
+ void dumpStatesLocked(FILE* out, bool verbose) const override{};
+
// Util function to flush the old packet.
void flushIfNeededLocked(const uint64_t& eventTime);
@@ -95,7 +102,7 @@
std::unordered_map<HashableDimensionKey, std::vector<GaugeBucket>> mPastBuckets;
// The current bucket.
- std::shared_ptr<DimToGaugeFieldsMap> mCurrentSlicedBucket;
+ std::shared_ptr<DimToGaugeAtomsMap> mCurrentSlicedBucket;
// The current bucket for anomaly detection.
std::shared_ptr<DimToValMap> mCurrentSlicedBucketForAnomaly;
@@ -106,6 +113,8 @@
// Whitelist of fields to report. Empty means all are reported.
FieldFilter mFieldFilter;
+ GaugeMetric::SamplingType mSamplingType;
+
// apply a whitelist on the original input
std::shared_ptr<FieldValueMap> getGaugeFields(const LogEvent& event);
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index d620a7e..e74924a 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -32,8 +32,7 @@
ConditionKey conditionKey;
if (mConditionSliced) {
for (const auto& link : mConditionLinks) {
- conditionKey.insert(std::make_pair(link.condition(),
- getDimensionKeysForCondition(event, link)));
+ getDimensionKeysForCondition(event, link, &conditionKey[link.condition()]);
}
if (mWizard->query(mConditionTrackerIndex, conditionKey) != ConditionState::kTrue) {
condition = false;
@@ -44,8 +43,9 @@
condition = mCondition;
}
- if (mDimensions.child_size() > 0) {
- vector<DimensionsValue> dimensionValues = getDimensionKeys(event, mDimensions);
+ if (mDimensions.has_field() && mDimensions.child_size() > 0) {
+ vector<DimensionsValue> dimensionValues;
+ getDimensionKeys(event, mDimensions, &dimensionValues);
for (const DimensionsValue& dimensionValue : dimensionValues) {
onMatchedLogEventInternalLocked(
matcherIndex, HashableDimensionKey(dimensionValue), conditionKey, condition, event);
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 3779c44..6f33073 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -96,6 +96,11 @@
return onDumpReportLocked(dumpTimeNs, report);
}
+ void dumpStates(FILE* out, bool verbose) const {
+ std::lock_guard<std::mutex> lock(mMutex);
+ dumpStatesLocked(out, verbose);
+ }
+
// Returns the memory in bytes currently used to store this metric's data. Does not change
// state.
size_t byteSize() const {
@@ -128,6 +133,7 @@
android::util::ProtoOutputStream* protoOutput) = 0;
virtual void onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) = 0;
virtual size_t byteSizeLocked() const = 0;
+ virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
const int64_t mMetricId;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index f929517..d0737de 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -154,6 +154,20 @@
}
}
+void MetricsManager::dumpStates(FILE* out, bool verbose) {
+ fprintf(out, "ConfigKey %s, allowed source:", mConfigKey.ToString().c_str());
+ {
+ std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex);
+ for (const auto& source : mAllowedLogSources) {
+ fprintf(out, "%d ", source);
+ }
+ }
+ fprintf(out, "\n");
+ for (const auto& producer : mAllMetricProducers) {
+ producer->dumpStates(out, verbose);
+ }
+}
+
void MetricsManager::onDumpReport(ProtoOutputStream* protoOutput) {
VLOG("=========================Metric Reports Start==========================");
uint64_t dumpTimeStampNs = time(nullptr) * NS_PER_SEC;
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index a0239fc..9cdbafc 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -61,6 +61,8 @@
return !mAllowedPkg.empty();
}
+ void dumpStates(FILE* out, bool verbose);
+
// Config source owner can call onDumpReport() to get all the metrics collected.
virtual void onDumpReport(android::util::ProtoOutputStream* protoOutput);
virtual void onDumpReport(const uint64_t& dumpTimeStampNs, ConfigMetricsReport* report);
@@ -68,7 +70,6 @@
// Computes the total byte size of all metrics managed by a single config source.
// Does not change the state.
virtual size_t byteSize();
-
private:
const ConfigKey mConfigKey;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 3e7032d..9f750cf 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -67,6 +67,8 @@
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
+ void dumpStatesLocked(FILE* out, bool verbose) const override{};
+
// Util function to flush the old packet.
void flushIfNeededLocked(const uint64_t& eventTime);
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 371460e..c2d2cea 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -97,6 +97,8 @@
// Predict the anomaly timestamp given the current status.
virtual int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
const uint64_t currentTimestamp) const = 0;
+ // Dump internal states for debugging
+ virtual void dumpStates(FILE* out, bool verbose) const = 0;
protected:
// Starts the anomaly alarm.
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index 0c99391..412a0c9 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -291,6 +291,11 @@
return currentTimestamp;
}
+void MaxDurationTracker::dumpStates(FILE* out, bool verbose) const {
+ fprintf(out, "\t\t sub-durations %lu\n", (unsigned long)mInfos.size());
+ fprintf(out, "\t\t current duration %lld\n", (long long)mDuration);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index 5d3c158..661d131 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -48,9 +48,10 @@
int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
const uint64_t currentTimestamp) const override;
+ void dumpStates(FILE* out, bool verbose) const override;
private:
- std::map<HashableDimensionKey, DurationInfo> mInfos;
+ std::unordered_map<HashableDimensionKey, DurationInfo> mInfos;
void noteConditionChanged(const HashableDimensionKey& key, bool conditionMet,
const uint64_t timestamp);
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index 6bf4228..75d7c08 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -314,6 +314,12 @@
return eventTimestampNs + thresholdNs;
}
+void OringDurationTracker::dumpStates(FILE* out, bool verbose) const {
+ fprintf(out, "\t\t started count %lu\n", (unsigned long)mStarted.size());
+ fprintf(out, "\t\t paused count %lu\n", (unsigned long)mPaused.size());
+ fprintf(out, "\t\t current duration %lld\n", (long long)mDuration);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index 638b7ad..43469ca 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -48,6 +48,7 @@
int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
const uint64_t currentTimestamp) const override;
+ void dumpStates(FILE* out, bool verbose) const override;
private:
// We don't need to keep track of individual durations. The information that's needed is:
@@ -55,10 +56,10 @@
// 2) which keys are paused (started but condition was false)
// 3) whenever a key stops, we remove it from the started set. And if the set becomes empty,
// it means everything has stopped, we then record the end time.
- std::map<HashableDimensionKey, int> mStarted;
- std::map<HashableDimensionKey, int> mPaused;
+ std::unordered_map<HashableDimensionKey, int> mStarted;
+ std::unordered_map<HashableDimensionKey, int> mPaused;
int64_t mLastStartTime;
- std::map<HashableDimensionKey, ConditionKey> mConditionKeyMap;
+ std::unordered_map<HashableDimensionKey, ConditionKey> mConditionKeyMap;
// return true if we should not allow newKey to be tracked because we are above the threshold
bool hitGuardRail(const HashableDimensionKey& newKey);
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index f73c4a5..af21ca4 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -100,7 +100,9 @@
optional int64 end_bucket_nanos = 2;
- optional Atom atom = 3;
+ repeated Atom atom = 3;
+
+ repeated int64 timestamp_nanos = 4;
}
message GaugeMetricData {
@@ -262,4 +264,10 @@
optional int64 min_pull_interval_sec = 4;
}
repeated PulledAtomStats pulled_atom_stats = 10;
+
+ message LoggerErrorStats {
+ optional int32 logger_disconnection_sec = 1;
+ optional int32 error_code = 2;
+ }
+ repeated LoggerErrorStats logger_error_stats = 11;
}
\ No newline at end of file
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 07bbcb2..2ea79a6 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -222,6 +222,12 @@
optional TimeUnit bucket = 6;
repeated MetricConditionLink links = 7;
+
+ enum SamplingType {
+ RANDOM_ONE_SAMPLE = 1;
+ ALL_CONDITION_CHANGES = 2;
+ }
+ optional SamplingType sampling_type = 9 [default = RANDOM_ONE_SAMPLE] ;
}
message ValueMetric {
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
index e56a6c5..a80fdc5 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
@@ -153,23 +153,26 @@
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid1);
EXPECT_EQ(data.bucket_info_size(), 3);
+ EXPECT_EQ(data.bucket_info(0).atom_size(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
- EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().type(), AppStartChanged::HOT);
- EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_name(), "activity_name2");
- EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_start_msec(), 102L);
+ EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::HOT);
+ EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name2");
+ EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_msec(), 102L);
+ EXPECT_EQ(data.bucket_info(1).atom_size(), 1);
EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
- EXPECT_EQ(data.bucket_info(1).atom().app_start_changed().type(), AppStartChanged::WARM);
- EXPECT_EQ(data.bucket_info(1).atom().app_start_changed().activity_name(), "activity_name4");
- EXPECT_EQ(data.bucket_info(1).atom().app_start_changed().activity_start_msec(), 104L);
+ EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().type(), AppStartChanged::WARM);
+ EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_name(), "activity_name4");
+ EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_start_msec(), 104L);
+ EXPECT_EQ(data.bucket_info(2).atom_size(), 1);
EXPECT_EQ(data.bucket_info(2).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(2).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
- EXPECT_EQ(data.bucket_info(2).atom().app_start_changed().type(), AppStartChanged::COLD);
- EXPECT_EQ(data.bucket_info(2).atom().app_start_changed().activity_name(), "activity_name5");
- EXPECT_EQ(data.bucket_info(2).atom().app_start_changed().activity_start_msec(), 105L);
+ EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().type(), AppStartChanged::COLD);
+ EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_name(), "activity_name5");
+ EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_start_msec(), 105L);
data = gaugeMetrics.data(1);
@@ -178,11 +181,12 @@
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid2);
EXPECT_EQ(data.bucket_info_size(), 1);
+ EXPECT_EQ(data.bucket_info(0).atom_size(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
- EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().type(), AppStartChanged::COLD);
- EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_name(), "activity_name7");
- EXPECT_EQ(data.bucket_info(0).atom().app_start_changed().activity_start_msec(), 201L);
+ EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::COLD);
+ EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name7");
+ EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_msec(), 201L);
}
#else
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index eda16a2..4504a95 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -123,11 +123,13 @@
auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
auto screenTurnedOnEvent =
- CreateScreenStateChangedEvent(ScreenStateChanged::STATE_ON, bucketStartTimeNs + 2);
+ CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 2);
auto screenTurnedOffEvent =
- CreateScreenStateChangedEvent(ScreenStateChanged::STATE_OFF, bucketStartTimeNs + 200);
+ CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 200);
auto screenTurnedOnEvent2 =
- CreateScreenStateChangedEvent(ScreenStateChanged::STATE_ON,
+ CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
bucketStartTimeNs + 2 * bucketSizeNs - 100);
auto syncOnEvent1 =
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index e656b98..1186a16 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -73,11 +73,13 @@
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
auto screenTurnedOnEvent =
- CreateScreenStateChangedEvent(ScreenStateChanged::STATE_ON, bucketStartTimeNs + 1);
+ CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 1);
auto screenTurnedOffEvent =
- CreateScreenStateChangedEvent(ScreenStateChanged::STATE_OFF, bucketStartTimeNs + 200);
+ CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 200);
auto screenTurnedOnEvent2 =
- CreateScreenStateChangedEvent(ScreenStateChanged::STATE_ON,
+ CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
bucketStartTimeNs + bucketSizeNs + 500);
std::vector<AttributionNode> attributions1 =
@@ -156,7 +158,8 @@
events.clear();
events.push_back(CreateScreenStateChangedEvent(
- ScreenStateChanged::STATE_OFF, bucketStartTimeNs + 2 * bucketSizeNs + 90));
+ android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 2 * bucketSizeNs + 90));
events.push_back(CreateAcquireWakelockEvent(
attributions1, "wl3", bucketStartTimeNs + 2 * bucketSizeNs + 100));
events.push_back(CreateReleaseWakelockEvent(
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 897328d..4ad2097 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -149,8 +149,8 @@
metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
MetricConditionLink* link = metric.add_links();
link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
- *link->mutable_fields_in_what() = buildSimpleAtomFieldMatcher(tagId, 1);
- *link->mutable_fields_in_condition() = buildSimpleAtomFieldMatcher(conditionTagId, 2);
+ buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
+ buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
LogEvent event1(tagId, bucketStartTimeNs + 1);
event1.write("111"); // uid
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index 34cde60..da00cae 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -98,8 +98,8 @@
metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
MetricConditionLink* link = metric.add_links();
link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
- *link->mutable_fields_in_what() = buildSimpleAtomFieldMatcher(tagId, 1);
- *link->mutable_fields_in_condition() = buildSimpleAtomFieldMatcher(conditionTagId, 2);
+ buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
+ buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
LogEvent event1(tagId, bucketStartTimeNs + 1);
EXPECT_TRUE(event1.write("111"));
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 82772d8..4533ac6 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -78,7 +78,7 @@
gaugeProducer.onDataPulled(allData);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second->begin();
+ auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
EXPECT_EQ(10, it->second.value_int());
it++;
EXPECT_EQ(11, it->second.value_int());
@@ -94,14 +94,14 @@
allData.push_back(event2);
gaugeProducer.onDataPulled(allData);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- it = gaugeProducer.mCurrentSlicedBucket->begin()->second->begin();
+ it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
EXPECT_EQ(24, it->second.value_int());
it++;
EXPECT_EQ(25, it->second.value_int());
// One dimension.
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.size());
- it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeFields->begin();
+ it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
EXPECT_EQ(10L, it->second.value_int());
it++;
EXPECT_EQ(11L, it->second.value_int());
@@ -112,7 +112,7 @@
// One dimension.
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
- it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeFields->begin();
+ it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
EXPECT_EQ(24L, it->second.value_int());
it++;
EXPECT_EQ(25L, it->second.value_int());
@@ -151,7 +151,8 @@
gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(100,
- gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
+ gaugeProducer.mCurrentSlicedBucket->begin()->
+ second.front().mFields->begin()->second.value_int());
EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
@@ -165,17 +166,18 @@
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(110,
- gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
+ gaugeProducer.mCurrentSlicedBucket->begin()->
+ second.front().mFields->begin()->second.value_int());
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()->second.back()
- .mGaugeFields->begin()->second.value_int());
+ .mGaugeAtoms.front().mFields->begin()->second.value_int());
gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()->second.back()
- .mGaugeFields->begin()->second.value_int());
+ .mGaugeAtoms.front().mFields->begin()->second.value_int());
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
}
@@ -214,7 +216,8 @@
gaugeProducer.onDataPulled({event1});
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(13L,
- gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
+ gaugeProducer.mCurrentSlicedBucket->begin()->
+ second.front().mFields->begin()->second.value_int());
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY), 0U);
std::shared_ptr<LogEvent> event2 =
@@ -226,7 +229,8 @@
gaugeProducer.onDataPulled({event2});
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(15L,
- gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
+ gaugeProducer.mCurrentSlicedBucket->begin()->
+ second.front().mFields->begin()->second.value_int());
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
@@ -239,7 +243,8 @@
gaugeProducer.onDataPulled({event3});
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(26L,
- gaugeProducer.mCurrentSlicedBucket->begin()->second->begin()->second.value_int());
+ gaugeProducer.mCurrentSlicedBucket->begin()->
+ second.front().mFields->begin()->second.value_int());
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_DIMENSION_KEY),
event2->GetTimestampNs() / NS_PER_SEC + refPeriodSec);
@@ -250,7 +255,7 @@
event4->init();
gaugeProducer.onDataPulled({event4});
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
- EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second->empty());
+ EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
}
} // namespace statsd
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 718b2e1..9f4582d 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -48,7 +48,7 @@
}
AtomMatcher CreateScreenStateChangedAtomMatcher(
- const string& name, ScreenStateChanged::State state) {
+ 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();
@@ -60,11 +60,13 @@
}
AtomMatcher CreateScreenTurnedOnAtomMatcher() {
- return CreateScreenStateChangedAtomMatcher("ScreenTurnedOn", ScreenStateChanged::STATE_ON);
+ return CreateScreenStateChangedAtomMatcher("ScreenTurnedOn",
+ android::view::DisplayStateEnum::DISPLAY_STATE_ON);
}
AtomMatcher CreateScreenTurnedOffAtomMatcher() {
- return CreateScreenStateChangedAtomMatcher("ScreenTurnedOff", ScreenStateChanged::STATE_OFF);
+ return CreateScreenStateChangedAtomMatcher("ScreenTurnedOff",
+ ::android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
}
AtomMatcher CreateSyncStateChangedAtomMatcher(
@@ -209,7 +211,7 @@
}
std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
- const ScreenStateChanged::State state, uint64_t timestampNs) {
+ const android::view::DisplayStateEnum state, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::SCREEN_STATE_CHANGED, timestampNs);
EXPECT_TRUE(event->write(state));
event->init();
@@ -221,7 +223,7 @@
const WakelockStateChanged::State state, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs);
event->write(attributions);
- event->write(WakelockStateChanged::PARTIAL);
+ event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
event->write(wakelockName);
event->write(state);
event->init();
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 1fc33de..ff8fef0c 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -84,7 +84,7 @@
// Create log event for screen state changed.
std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
- const ScreenStateChanged::State state, uint64_t timestampNs);
+ const android::view::DisplayStateEnum state, uint64_t timestampNs);
// Create log event for app moving to background.
std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs);
diff --git a/cmds/statsd/tools/dogfood/Android.mk b/cmds/statsd/tools/dogfood/Android.mk
index 32a85b1..a65095f 100644
--- a/cmds/statsd/tools/dogfood/Android.mk
+++ b/cmds/statsd/tools/dogfood/Android.mk
@@ -27,6 +27,7 @@
LOCAL_PROTOC_OPTIMIZE_TYPE := lite
LOCAL_PRIVILEGED_MODULE := true
LOCAL_DEX_PREOPT := false
+LOCAL_CERTIFICATE := platform
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)
diff --git a/cmds/statsd/tools/dogfood/AndroidManifest.xml b/cmds/statsd/tools/dogfood/AndroidManifest.xml
index 7bfde40..cd76c9d 100644
--- a/cmds/statsd/tools/dogfood/AndroidManifest.xml
+++ b/cmds/statsd/tools/dogfood/AndroidManifest.xml
@@ -18,6 +18,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.statsd.dogfood"
+ android:sharedUserId="android.uid.system"
android:versionCode="1"
android:versionName="1.0" >
diff --git a/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config b/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config
index c1c3914..d050061 100644
--- a/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config
+++ b/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config
Binary files differ
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java
index d4b2aa4..5dcce9a 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java
@@ -90,7 +90,7 @@
case 2:
case 10:
StatsLog.write(StatsLog.CHARGING_STATE_CHANGED,
- StatsLog.CHARGING_STATE_CHANGED__CHARGING_STATE__BATTERY_STATUS_CHARGING
+ StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_CHARGING
/* charging_state */);
break;
case 3:
@@ -103,7 +103,7 @@
case 4:
case 12:
StatsLog.write(StatsLog.CHARGING_STATE_CHANGED,
- StatsLog.CHARGING_STATE_CHANGED__CHARGING_STATE__BATTERY_STATUS_NOT_CHARGING
+ StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_NOT_CHARGING
/* charging_state */);
break;
case 5:
@@ -115,7 +115,7 @@
break;
case 6:
StatsLog.write(StatsLog.SCREEN_STATE_CHANGED,
- StatsLog.SCREEN_STATE_CHANGED__DISPLAY_STATE__STATE_ON /* display_state */);
+ StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_ON /* display_state */);
break;
case 7:
for (int i = 0; i < mBurst; i++) {
@@ -125,7 +125,7 @@
break;
case 14:
StatsLog.write(StatsLog.SCREEN_STATE_CHANGED,
- StatsLog.SCREEN_STATE_CHANGED__DISPLAY_STATE__STATE_OFF /* display_state */);
+ StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_OFF /* display_state */);
break;
case 15:
for (int i = 0; i < mBurst; i++) {
@@ -147,14 +147,14 @@
public void finish() {
// Screen goes back to off. This will ensure that conditions get back to false.
StatsLog.write(StatsLog.SCREEN_STATE_CHANGED,
- StatsLog.SCREEN_STATE_CHANGED__DISPLAY_STATE__STATE_OFF /* display_state */);
+ StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_OFF /* display_state */);
for (int i = 0; i < mBurst; i++) {
StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */,
StatsLog.AUDIO_STATE_CHANGED__STATE__OFF /* state */);
}
// Stop charging, to ensure the corresponding durations are closed.
StatsLog.write(StatsLog.CHARGING_STATE_CHANGED,
- StatsLog.CHARGING_STATE_CHANGED__CHARGING_STATE__BATTERY_STATUS_NOT_CHARGING
+ StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_NOT_CHARGING
/* charging_state */);
// Stop scanning GPS, to ensure the corresponding conditions get back to false.
for (int i = 0; i < mBurst; i++) {
diff --git a/cmds/svc/src/com/android/commands/svc/UsbCommand.java b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
index 34f6d7d..3893be4 100644
--- a/cmds/svc/src/com/android/commands/svc/UsbCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
@@ -21,7 +21,6 @@
import android.hardware.usb.UsbManager;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
public class UsbCommand extends Svc.Command {
public UsbCommand() {
@@ -37,41 +36,41 @@
public String longHelp() {
return shortHelp() + "\n"
+ "\n"
- + "usage: svc usb setFunction [function] [usbDataUnlocked=false]\n"
- + " Set the current usb function and optionally the data lock state.\n\n"
+ + "usage: svc usb setFunctions [function]\n"
+ + " Set the current usb function. If function is blank, sets to charging.\n"
+ " svc usb setScreenUnlockedFunctions [function]\n"
- + " Sets the functions which, if the device was charging,"
- + " become current on screen unlock.\n"
- + " svc usb getFunction\n"
- + " Gets the list of currently enabled functions\n";
+ + " Sets the functions which, if the device was charging, become current on"
+ + "screen unlock. If function is blank, turn off this feature.\n"
+ + " svc usb getFunctions\n"
+ + " Gets the list of currently enabled functions\n\n"
+ + "possible values of [function] are any of 'mtp', 'ptp', 'rndis', 'midi'\n";
}
@Override
public void run(String[] args) {
- boolean validCommand = false;
if (args.length >= 2) {
- if ("setFunction".equals(args[1])) {
- IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
- Context.USB_SERVICE));
- boolean unlockData = false;
- if (args.length >= 4) {
- unlockData = Boolean.valueOf(args[3]);
- }
+ IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
+ Context.USB_SERVICE));
+ if ("setFunctions".equals(args[1])) {
try {
- usbMgr.setCurrentFunction((args.length >=3 ? args[2] : null), unlockData);
+ usbMgr.setCurrentFunctions(UsbManager.usbFunctionsFromString(
+ args.length >= 3 ? args[2] : ""));
} catch (RemoteException e) {
System.err.println("Error communicating with UsbManager: " + e);
}
return;
- } else if ("getFunction".equals(args[1])) {
- System.err.println(SystemProperties.get("sys.usb.config"));
+ } else if ("getFunctions".equals(args[1])) {
+ try {
+ System.err.println(
+ UsbManager.usbFunctionsToString(usbMgr.getCurrentFunctions()));
+ } catch (RemoteException e) {
+ System.err.println("Error communicating with UsbManager: " + e);
+ }
return;
} else if ("setScreenUnlockedFunctions".equals(args[1])) {
- IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
- Context.USB_SERVICE));
try {
- usbMgr.setScreenUnlockedFunctions((args.length >= 3 ? args[2] :
- UsbManager.USB_FUNCTION_NONE));
+ usbMgr.setScreenUnlockedFunctions(UsbManager.usbFunctionsFromString(
+ args.length >= 3 ? args[2] : ""));
} catch (RemoteException e) {
System.err.println("Error communicating with UsbManager: " + e);
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index b58c523..fdb0ac9 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -17,7 +17,6 @@
package android.app;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
-
import static java.lang.Character.MIN_VALUE;
import android.annotation.CallSuper;
@@ -4713,7 +4712,6 @@
* their launch had come from the original activity.
* @param intent The Intent to start.
* @param options ActivityOptions or null.
- * @param permissionToken Token received from the system that permits this call to be made.
* @param ignoreTargetSecurity If true, the activity manager will not check whether the
* caller it is doing the start is, is actually allowed to start the target activity.
* If you set this to true, you must set an explicit component in the Intent and do any
@@ -4722,7 +4720,7 @@
* @hide
*/
public void startActivityAsCaller(Intent intent, @Nullable Bundle options,
- IBinder permissionToken, boolean ignoreTargetSecurity, int userId) {
+ boolean ignoreTargetSecurity, int userId) {
if (mParent != null) {
throw new RuntimeException("Can't be called from a child");
}
@@ -4730,7 +4728,7 @@
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivityAsCaller(
this, mMainThread.getApplicationThread(), mToken, this,
- intent, -1, options, permissionToken, ignoreTargetSecurity, userId);
+ intent, -1, options, ignoreTargetSecurity, userId);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, -1, ar.getResultCode(),
@@ -6340,7 +6338,7 @@
mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix);
- final AutofillManager afm = mAutofillManager;
+ final AutofillManager afm = getAutofillManager();
if (afm != null) {
afm.dump(prefix, writer);
} else {
@@ -7118,7 +7116,7 @@
boolean isAppDebuggable =
(mApplication.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
- // This property is set for all builds except final release
+ // This property is set for all non-user builds except final release
boolean isDlwarningEnabled = SystemProperties.getInt("ro.bionic.ld.warning", 0) == 1;
if (isAppDebuggable || isDlwarningEnabled) {
@@ -7141,11 +7139,14 @@
}
}
- // We might disable this for final builds.
- boolean isApiWarningEnabled = true;
+ // This property is set for all non-user builds except final release
+ boolean isApiWarningEnabled = SystemProperties.getInt("ro.art.hiddenapi.warning", 0) == 1;
if (isAppDebuggable || isApiWarningEnabled) {
- if (VMRuntime.getRuntime().hasUsedHiddenApi()) {
+ if (!mMainThread.mHiddenApiWarningShown && VMRuntime.getRuntime().hasUsedHiddenApi()) {
+ // Only show the warning once per process.
+ mMainThread.mHiddenApiWarningShown = true;
+
String appName = getApplicationInfo().loadLabel(getPackageManager())
.toString();
String warning = "Detected problems with API compatiblity\n"
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4d5ac6f..e2ce8b1 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -449,31 +449,6 @@
*/
public static final int INTENT_SENDER_FOREGROUND_SERVICE = 5;
- /**
- * Extra included on intents that are delegating the call to
- * ActivityManager#startActivityAsCaller to another app. This token is necessary for that call
- * to succeed. Type is IBinder.
- * @hide
- */
- public static final String EXTRA_PERMISSION_TOKEN = "android.app.extra.PERMISSION_TOKEN";
-
- /**
- * Extra included on intents that contain an EXTRA_INTENT, with options that the contained
- * intent may want to be started with. Type is Bundle.
- * TODO: remove once the ChooserActivity moves to systemui
- * @hide
- */
- public static final String EXTRA_OPTIONS = "android.app.extra.OPTIONS";
-
- /**
- * Extra included on intents that contain an EXTRA_INTENT, use this boolean value for the
- * parameter of the same name when starting the contained intent.
- * TODO: remove once the ChooserActivity moves to systemui
- * @hide
- */
- public static final String EXTRA_IGNORE_TARGET_SECURITY =
- "android.app.extra.EXTRA_IGNORE_TARGET_SECURITY";
-
/** @hide User operation call: success! */
public static final int USER_OP_SUCCESS = 0;
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index da9f728..5ee7ede 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -43,25 +43,29 @@
* Type for {@link #notifyAppTransitionStarting}: The transition was started because we drew
* the splash screen.
*/
- public static final int APP_TRANSITION_SPLASH_SCREEN = 1;
+ public static final int APP_TRANSITION_SPLASH_SCREEN =
+ AppProtoEnums.APP_TRANSITION_SPLASH_SCREEN; // 1
/**
* Type for {@link #notifyAppTransitionStarting}: The transition was started because we all
* app windows were drawn
*/
- public static final int APP_TRANSITION_WINDOWS_DRAWN = 2;
+ public static final int APP_TRANSITION_WINDOWS_DRAWN =
+ AppProtoEnums.APP_TRANSITION_WINDOWS_DRAWN; // 2
/**
* Type for {@link #notifyAppTransitionStarting}: The transition was started because of a
* timeout.
*/
- public static final int APP_TRANSITION_TIMEOUT = 3;
+ public static final int APP_TRANSITION_TIMEOUT =
+ AppProtoEnums.APP_TRANSITION_TIMEOUT; // 3
/**
* Type for {@link #notifyAppTransitionStarting}: The transition was started because of a
* we drew a task snapshot.
*/
- public static final int APP_TRANSITION_SNAPSHOT = 4;
+ public static final int APP_TRANSITION_SNAPSHOT =
+ AppProtoEnums.APP_TRANSITION_SNAPSHOT; // 4
/**
* The bundle key to extract the assist data.
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 4bcd677..fee5827 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -207,6 +207,12 @@
"android.activity.taskOverlayCanResume";
/**
+ * See {@link #setAvoidMoveToFront()}.
+ * @hide
+ */
+ private static final String KEY_AVOID_MOVE_TO_FRONT = "android.activity.avoidMoveToFront";
+
+ /**
* Where the split-screen-primary stack should be positioned.
* @hide
*/
@@ -307,6 +313,7 @@
private boolean mDisallowEnterPictureInPictureWhileLaunching;
private boolean mTaskOverlay;
private boolean mTaskOverlayCanResume;
+ private boolean mAvoidMoveToFront;
private AppTransitionAnimationSpec mAnimSpecs[];
private int mRotationAnimationHint = -1;
private Bundle mAppVerificationBundle;
@@ -923,6 +930,7 @@
mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false);
+ mAvoidMoveToFront = opts.getBoolean(KEY_AVOID_MOVE_TO_FRONT, false);
mSplitScreenCreateMode = opts.getInt(KEY_SPLIT_SCREEN_CREATE_MODE,
SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT);
mDisallowEnterPictureInPictureWhileLaunching = opts.getBoolean(
@@ -1239,6 +1247,25 @@
return mTaskOverlayCanResume;
}
+ /**
+ * Sets whether the activity launched should not cause the activity stack it is contained in to
+ * be moved to the front as a part of launching.
+ *
+ * @hide
+ */
+ public void setAvoidMoveToFront() {
+ mAvoidMoveToFront = true;
+ }
+
+ /**
+ * @return whether the activity launch should prevent moving the associated activity stack to
+ * the front.
+ * @hide
+ */
+ public boolean getAvoidMoveToFront() {
+ return mAvoidMoveToFront;
+ }
+
/** @hide */
public int getSplitScreenCreateMode() {
return mSplitScreenCreateMode;
@@ -1416,6 +1443,7 @@
b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
b.putBoolean(KEY_TASK_OVERLAY_CAN_RESUME, mTaskOverlayCanResume);
+ b.putBoolean(KEY_AVOID_MOVE_TO_FRONT, mAvoidMoveToFront);
b.putInt(KEY_SPLIT_SCREEN_CREATE_MODE, mSplitScreenCreateMode);
b.putBoolean(KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING,
mDisallowEnterPictureInPictureWhileLaunching);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 934b0f3..29e091b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -291,6 +291,7 @@
boolean mJitEnabled = false;
boolean mSomeActivitiesChanged = false;
boolean mUpdatingSystemConfig = false;
+ /* package */ boolean mHiddenApiWarningShown = false;
// These can be accessed by multiple threads; mResourcesManager is the lock.
// XXX For now we keep around information about all packages we have
@@ -389,7 +390,7 @@
ActivityInfo activityInfo;
CompatibilityInfo compatInfo;
- public LoadedApk loadedApk;
+ public LoadedApk packageInfo;
List<ResultInfo> pendingResults;
List<ReferrerIntent> pendingIntents;
@@ -432,7 +433,7 @@
this.isForward = isForward;
this.profilerInfo = profilerInfo;
this.overrideConfig = overrideConfig;
- this.loadedApk = client.getLoadedApkNoCheck(activityInfo.applicationInfo,
+ this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo,
compatInfo);
init();
}
@@ -614,7 +615,7 @@
}
static final class AppBindData {
- LoadedApk loadedApk;
+ LoadedApk info;
String processName;
ApplicationInfo appInfo;
List<ProviderInfo> providers;
@@ -1913,13 +1914,13 @@
return mH;
}
- public final LoadedApk getLoadedApkForPackageName(String packageName,
- CompatibilityInfo compatInfo, int flags) {
- return getLoadedApkForPackageName(packageName, compatInfo, flags, UserHandle.myUserId());
+ public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
+ int flags) {
+ return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId());
}
- public final LoadedApk getLoadedApkForPackageName(String packageName,
- CompatibilityInfo compatInfo, int flags, int userId) {
+ public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
+ int flags, int userId) {
final boolean differentUser = (UserHandle.myUserId() != userId);
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
@@ -1932,13 +1933,13 @@
ref = mResourcePackages.get(packageName);
}
- LoadedApk loadedApk = ref != null ? ref.get() : null;
- //Slog.i(TAG, "getLoadedApkForPackageName " + packageName + ": " + loadedApk);
- //if (loadedApk != null) Slog.i(TAG, "isUptoDate " + loadedApk.mResDir
- // + ": " + loadedApk.mResources.getAssets().isUpToDate());
- if (loadedApk != null && (loadedApk.mResources == null
- || loadedApk.mResources.getAssets().isUpToDate())) {
- if (loadedApk.isSecurityViolation()
+ LoadedApk packageInfo = ref != null ? ref.get() : null;
+ //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
+ //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
+ // + ": " + packageInfo.mResources.getAssets().isUpToDate());
+ if (packageInfo != null && (packageInfo.mResources == null
+ || packageInfo.mResources.getAssets().isUpToDate())) {
+ if (packageInfo.isSecurityViolation()
&& (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
throw new SecurityException(
"Requesting code from " + packageName
@@ -1946,7 +1947,7 @@
+ mBoundApplication.processName
+ "/" + mBoundApplication.appInfo.uid);
}
- return loadedApk;
+ return packageInfo;
}
}
@@ -1961,13 +1962,13 @@
}
if (ai != null) {
- return getLoadedApk(ai, compatInfo, flags);
+ return getPackageInfo(ai, compatInfo, flags);
}
return null;
}
- public final LoadedApk getLoadedApk(ApplicationInfo ai, CompatibilityInfo compatInfo,
+ public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
int flags) {
boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
boolean securityViolation = includeCode && ai.uid != 0
@@ -1989,17 +1990,17 @@
throw new SecurityException(msg);
}
}
- return getLoadedApk(ai, compatInfo, null, securityViolation, includeCode,
+ return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode,
registerPackage);
}
@Override
- public final LoadedApk getLoadedApkNoCheck(ApplicationInfo ai,
+ public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
- return getLoadedApk(ai, compatInfo, null, false, true, false);
+ return getPackageInfo(ai, compatInfo, null, false, true, false);
}
- public final LoadedApk peekLoadedApk(String packageName, boolean includeCode) {
+ public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (includeCode) {
@@ -2011,7 +2012,7 @@
}
}
- private LoadedApk getLoadedApk(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
+ private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage) {
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
@@ -2026,35 +2027,35 @@
ref = mResourcePackages.get(aInfo.packageName);
}
- LoadedApk loadedApk = ref != null ? ref.get() : null;
- if (loadedApk == null || (loadedApk.mResources != null
- && !loadedApk.mResources.getAssets().isUpToDate())) {
+ LoadedApk packageInfo = ref != null ? ref.get() : null;
+ if (packageInfo == null || (packageInfo.mResources != null
+ && !packageInfo.mResources.getAssets().isUpToDate())) {
if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
: "Loading resource-only package ") + aInfo.packageName
+ " (in " + (mBoundApplication != null
? mBoundApplication.processName : null)
+ ")");
- loadedApk =
+ packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
if (mSystemThread && "android".equals(aInfo.packageName)) {
- loadedApk.installSystemApplicationInfo(aInfo,
- getSystemContext().mLoadedApk.getClassLoader());
+ packageInfo.installSystemApplicationInfo(aInfo,
+ getSystemContext().mPackageInfo.getClassLoader());
}
if (differentUser) {
// Caching not supported across users
} else if (includeCode) {
mPackages.put(aInfo.packageName,
- new WeakReference<LoadedApk>(loadedApk));
+ new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
- new WeakReference<LoadedApk>(loadedApk));
+ new WeakReference<LoadedApk>(packageInfo));
}
}
- return loadedApk;
+ return packageInfo;
}
}
@@ -2778,8 +2779,8 @@
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r) {
ActivityInfo aInfo = r.activityInfo;
- if (r.loadedApk == null) {
- r.loadedApk = getLoadedApk(aInfo.applicationInfo, r.compatInfo,
+ if (r.packageInfo == null) {
+ r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
@@ -2816,15 +2817,15 @@
}
try {
- Application app = r.loadedApk.makeApplication(false, mInstrumentation);
+ Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
- + ", pkg=" + r.loadedApk.getPackageName()
+ + ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
- + ", dir=" + r.loadedApk.getAppDir());
+ + ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
@@ -2969,7 +2970,7 @@
}
ContextImpl appContext = ContextImpl.createActivityContext(
- this, r.loadedApk, r.activityInfo, r.token, displayId, r.overrideConfig);
+ this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
// For debugging purposes, if the activity's package name contains the value of
@@ -2977,7 +2978,7 @@
// its content on a secondary display if there is one.
String pkgName = SystemProperties.get("debug.second-display.pkg");
if (pkgName != null && !pkgName.isEmpty()
- && r.loadedApk.mPackageName.contains(pkgName)) {
+ && r.packageInfo.mPackageName.contains(pkgName)) {
for (int id : dm.getDisplayIds()) {
if (id != Display.DEFAULT_DISPLAY) {
Display display =
@@ -3309,7 +3310,7 @@
String component = data.intent.getComponent().getClassName();
- LoadedApk loadedApk = getLoadedApkNoCheck(
+ LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
IActivityManager mgr = ActivityManager.getService();
@@ -3318,7 +3319,7 @@
BroadcastReceiver receiver;
ContextImpl context;
try {
- app = loadedApk.makeApplication(false, mInstrumentation);
+ app = packageInfo.makeApplication(false, mInstrumentation);
context = (ContextImpl) app.getBaseContext();
if (data.info.splitName != null) {
context = (ContextImpl) context.createContextForSplit(data.info.splitName);
@@ -3327,7 +3328,7 @@
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
- receiver = loadedApk.getAppFactory()
+ receiver = packageInfo.getAppFactory()
.instantiateReceiver(cl, data.info.name, data.intent);
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
@@ -3343,9 +3344,9 @@
TAG, "Performing receive of " + data.intent
+ ": app=" + app
+ ", appName=" + app.getPackageName()
- + ", pkg=" + loadedApk.getPackageName()
+ + ", pkg=" + packageInfo.getPackageName()
+ ", comp=" + data.intent.getComponent().toShortString()
- + ", dir=" + loadedApk.getAppDir());
+ + ", dir=" + packageInfo.getAppDir());
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
@@ -3390,8 +3391,8 @@
unscheduleGcIdler();
// instantiate the BackupAgent class named in the manifest
- LoadedApk loadedApk = getLoadedApkNoCheck(data.appInfo, data.compatInfo);
- String packageName = loadedApk.mPackageName;
+ LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
+ String packageName = packageInfo.mPackageName;
if (packageName == null) {
Slog.d(TAG, "Asked to create backup agent for nonexistent package");
return;
@@ -3417,11 +3418,11 @@
try {
if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
- java.lang.ClassLoader cl = loadedApk.getClassLoader();
+ java.lang.ClassLoader cl = packageInfo.getClassLoader();
agent = (BackupAgent) cl.loadClass(classname).newInstance();
// set up the agent's context
- ContextImpl context = ContextImpl.createAppContext(this, loadedApk);
+ ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(agent);
agent.attach(context);
@@ -3457,8 +3458,8 @@
private void handleDestroyBackupAgent(CreateBackupAgentData data) {
if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
- LoadedApk loadedApk = getLoadedApkNoCheck(data.appInfo, data.compatInfo);
- String packageName = loadedApk.mPackageName;
+ LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
+ String packageName = packageInfo.mPackageName;
BackupAgent agent = mBackupAgents.get(packageName);
if (agent != null) {
try {
@@ -3478,12 +3479,12 @@
// we are back active so skip it.
unscheduleGcIdler();
- LoadedApk loadedApk = getLoadedApkNoCheck(
+ LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
- java.lang.ClassLoader cl = loadedApk.getClassLoader();
- service = loadedApk.getAppFactory()
+ java.lang.ClassLoader cl = packageInfo.getClassLoader();
+ service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
@@ -3496,10 +3497,10 @@
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
- ContextImpl context = ContextImpl.createAppContext(this, loadedApk);
+ ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
- Application app = loadedApk.makeApplication(false, mInstrumentation);
+ Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
@@ -3969,8 +3970,7 @@
}
r.activity.mConfigChangeFlags |= configChanges;
- performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity",
- pendingActions);
+ performPauseActivity(r, finished, "handlePauseActivity", pendingActions);
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
@@ -3993,16 +3993,18 @@
mInstrumentation.callActivityOnUserLeaving(r.activity);
}
- final Bundle performPauseActivity(IBinder token, boolean finished,
- boolean saveState, String reason, PendingTransactionActions pendingActions) {
+ final Bundle performPauseActivity(IBinder token, boolean finished, String reason,
+ PendingTransactionActions pendingActions) {
ActivityClientRecord r = mActivities.get(token);
- return r != null
- ? performPauseActivity(r, finished, saveState, reason, pendingActions)
- : null;
+ return r != null ? performPauseActivity(r, finished, reason, pendingActions) : null;
}
- private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, boolean saveState,
- String reason, PendingTransactionActions pendingActions) {
+ /**
+ * Pause the activity.
+ * @return Saved instance state for pre-Honeycomb apps if it was saved, {@code null} otherwise.
+ */
+ private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
+ PendingTransactionActions pendingActions) {
if (r.paused) {
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain cases.
@@ -4019,9 +4021,10 @@
r.activity.mFinished = true;
}
- // Next have the activity save its current state and managed dialogs...
- if (!r.activity.mFinished && saveState) {
- callCallActivityOnSaveInstanceState(r);
+ // Pre-Honeycomb apps always save their state before pausing
+ final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
+ if (shouldSaveState) {
+ callActivityOnSaveInstanceState(r);
}
performPauseActivityIfNeeded(r, reason);
@@ -4048,7 +4051,7 @@
}
}
- return !r.activity.mFinished && saveState ? r.state : null;
+ return shouldSaveState ? r.state : null;
}
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
@@ -4149,32 +4152,42 @@
}
}
- // Next have the activity save its current state and managed dialogs...
- if (!r.activity.mFinished && saveState) {
- if (r.state == null) {
- callCallActivityOnSaveInstanceState(r);
- }
- }
-
if (!keepShown) {
- try {
- // Now we are idle.
- r.activity.performStop(false /*preserveWindow*/);
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to stop activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- r.setState(ON_STOP);
- EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
- r.activity.getComponentName().getClassName(), reason);
+ callActivityOnStop(r, saveState, reason);
}
}
}
+ /**
+ * Calls {@link Activity#onStop()} and {@link Activity#onSaveInstanceState(Bundle)}, and updates
+ * the client record's state.
+ * All calls to stop an activity must be done through this method to make sure that
+ * {@link Activity#onSaveInstanceState(Bundle)} is also executed in the same call.
+ */
+ private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {
+ final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null
+ && !r.isPreHoneycomb();
+ if (shouldSaveState) {
+ callActivityOnSaveInstanceState(r);
+ }
+
+ try {
+ r.activity.performStop(false /*preserveWindow*/);
+ } catch (SuperNotCalledException e) {
+ throw e;
+ } catch (Exception e) {
+ if (!mInstrumentation.onException(r.activity, e)) {
+ throw new RuntimeException(
+ "Unable to stop activity "
+ + r.intent.getComponent().toShortString()
+ + ": " + e.toString(), e);
+ }
+ }
+ r.setState(ON_STOP);
+ EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
+ r.activity.getComponentName().getClassName(), reason);
+ }
+
private void updateVisibility(ActivityClientRecord r, boolean show) {
View v = r.activity.mDecor;
if (v != null) {
@@ -4292,24 +4305,7 @@
if (sleeping) {
if (!r.stopped && !r.isPreHoneycomb()) {
- if (!r.activity.mFinished && r.state == null) {
- callCallActivityOnSaveInstanceState(r);
- }
-
- try {
- // Now we are idle.
- r.activity.performStop(false /*preserveWindow*/);
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to stop activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- r.setState(ON_STOP);
- EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
- r.activity.getComponentName().getClassName(), "sleeping");
+ callActivityOnStop(r, true /* saveState */, "sleeping");
}
// Make sure any pending writes are now committed.
@@ -4363,11 +4359,11 @@
}
private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
- LoadedApk apk = peekLoadedApk(data.pkg, false);
+ LoadedApk apk = peekPackageInfo(data.pkg, false);
if (apk != null) {
apk.setCompatibilityInfo(data.info);
}
- apk = peekLoadedApk(data.pkg, true);
+ apk = peekPackageInfo(data.pkg, true);
if (apk != null) {
apk.setCompatibilityInfo(data.info);
}
@@ -4459,21 +4455,7 @@
performPauseActivityIfNeeded(r, "destroy");
if (!r.stopped) {
- try {
- r.activity.performStop(r.mPreserveWindow);
- } catch (SuperNotCalledException e) {
- throw e;
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to stop activity "
- + safeToComponentShortString(r.intent)
- + ": " + e.toString(), e);
- }
- }
- r.setState(ON_STOP);
- EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
- r.activity.getComponentName().getClassName(), "destroy");
+ callActivityOnStop(r, false /* saveState */, "destroy");
}
if (getNonConfigInstance) {
try {
@@ -4779,11 +4761,11 @@
// Need to ensure state is saved.
if (!r.paused) {
- performPauseActivity(r.token, false, r.isPreHoneycomb(), "handleRelaunchActivity",
+ performPauseActivity(r, false, "handleRelaunchActivity",
null /* pendingActions */);
}
- if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
- callCallActivityOnSaveInstanceState(r);
+ if (!r.stopped) {
+ callActivityOnStop(r, true /* saveState */, "handleRelaunchActivity");
}
handleDestroyActivity(r.token, false, configChanges, true);
@@ -4816,8 +4798,7 @@
handleStartActivity(r, pendingActions);
handleResumeActivity(r.token, false /* clearHide */, r.isForward, "relaunch");
if (r.startsNotResumed) {
- performPauseActivity(r, false /* finished */, r.isPreHoneycomb(), "relaunch",
- pendingActions);
+ performPauseActivity(r, false /* finished */, "relaunch", pendingActions);
}
if (!tmp.onlyLocalRequest) {
@@ -4832,7 +4813,7 @@
}
}
- private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
+ private void callActivityOnSaveInstanceState(ActivityClientRecord r) {
r.state = new Bundle();
r.state.setAllowFds(false);
if (r.isPersistable()) {
@@ -4861,7 +4842,7 @@
if (a != null) {
Configuration thisConfig = applyConfigCompatMainThread(
mCurDefaultDisplayDpi, newConfig,
- ar.loadedApk.getCompatibilityInfo());
+ ar.packageInfo.getCompatibilityInfo());
if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
// If the activity is currently resumed, its configuration
// needs to change right now.
@@ -5114,6 +5095,8 @@
// as that method uses the same check on the activity config override as well.
final boolean equivalent = config != null && mConfiguration != null
&& (0 == mConfiguration.diffPublicOnly(config));
+ final Theme systemTheme = getSystemContext().getTheme();
+ final Theme systemUiTheme = getSystemUiContext().getTheme();
synchronized (mResourcesManager) {
if (mPendingConfiguration != null) {
@@ -5146,12 +5129,10 @@
configDiff = mConfiguration.updateFrom(config);
config = applyCompatConfiguration(mCurDefaultDisplayDpi);
- final Theme systemTheme = getSystemContext().getTheme();
if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
systemTheme.rebase();
}
- final Theme systemUiTheme = getSystemUiContext().getTheme();
if ((systemUiTheme.getChangingConfigurations() & configDiff) != 0) {
systemUiTheme.rebase();
}
@@ -5347,7 +5328,7 @@
}
final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
- boolean hasLoadedApk = false;
+ boolean hasPkgInfo = false;
switch (cmd) {
case ApplicationThreadConstants.PACKAGE_REMOVED:
case ApplicationThreadConstants.PACKAGE_REMOVED_DONT_KILL:
@@ -5358,14 +5339,14 @@
}
synchronized (mResourcesManager) {
for (int i = packages.length - 1; i >= 0; i--) {
- if (!hasLoadedApk) {
+ if (!hasPkgInfo) {
WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
if (ref != null && ref.get() != null) {
- hasLoadedApk = true;
+ hasPkgInfo = true;
} else {
ref = mResourcePackages.get(packages[i]);
if (ref != null && ref.get() != null) {
- hasLoadedApk = true;
+ hasPkgInfo = true;
}
}
}
@@ -5385,21 +5366,21 @@
synchronized (mResourcesManager) {
for (int i = packages.length - 1; i >= 0; i--) {
WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
- LoadedApk loadedApk = ref != null ? ref.get() : null;
- if (loadedApk != null) {
- hasLoadedApk = true;
+ LoadedApk pkgInfo = ref != null ? ref.get() : null;
+ if (pkgInfo != null) {
+ hasPkgInfo = true;
} else {
ref = mResourcePackages.get(packages[i]);
- loadedApk = ref != null ? ref.get() : null;
- if (loadedApk != null) {
- hasLoadedApk = true;
+ pkgInfo = ref != null ? ref.get() : null;
+ if (pkgInfo != null) {
+ hasPkgInfo = true;
}
}
// If the package is being replaced, yet it still has a valid
// LoadedApk object, the package was updated with _DONT_KILL.
// Adjust it's internal references to the application info and
// resources.
- if (loadedApk != null) {
+ if (pkgInfo != null) {
try {
final String packageName = packages[i];
final ApplicationInfo aInfo =
@@ -5413,13 +5394,13 @@
if (ar.activityInfo.applicationInfo.packageName
.equals(packageName)) {
ar.activityInfo.applicationInfo = aInfo;
- ar.loadedApk = loadedApk;
+ ar.packageInfo = pkgInfo;
}
}
}
final List<String> oldPaths =
sPackageManager.getPreviousCodePaths(packageName);
- loadedApk.updateApplicationInfo(aInfo, oldPaths);
+ pkgInfo.updateApplicationInfo(aInfo, oldPaths);
} catch (RemoteException e) {
}
}
@@ -5428,7 +5409,7 @@
break;
}
}
- ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasLoadedApk);
+ ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasPkgInfo);
}
final void handleLowMemory() {
@@ -5636,10 +5617,10 @@
applyCompatConfiguration(mCurDefaultDisplayDpi);
}
- data.loadedApk = getLoadedApkNoCheck(data.appInfo, data.compatInfo);
+ data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
if (agent != null) {
- handleAttachAgent(agent, data.loadedApk);
+ handleAttachAgent(agent, data.info);
}
/**
@@ -5684,7 +5665,7 @@
// XXX should have option to change the port.
Debug.changeDebugPort(8100);
if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
- Slog.w(TAG, "Application " + data.loadedApk.getPackageName()
+ Slog.w(TAG, "Application " + data.info.getPackageName()
+ " is waiting for the debugger on port 8100...");
IActivityManager mgr = ActivityManager.getService();
@@ -5703,7 +5684,7 @@
}
} else {
- Slog.w(TAG, "Application " + data.loadedApk.getPackageName()
+ Slog.w(TAG, "Application " + data.info.getPackageName()
+ " can be debugged on port 8100...");
}
}
@@ -5751,14 +5732,14 @@
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationSplitAppDirs = ii.splitSourceDirs;
mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
- mInstrumentedAppDir = data.loadedApk.getAppDir();
- mInstrumentedSplitAppDirs = data.loadedApk.getSplitAppDirs();
- mInstrumentedLibDir = data.loadedApk.getLibDir();
+ mInstrumentedAppDir = data.info.getAppDir();
+ mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
+ mInstrumentedLibDir = data.info.getLibDir();
} else {
ii = null;
}
- final ContextImpl appContext = ContextImpl.createAppContext(this, data.loadedApk);
+ final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
updateLocaleListFromAppContext(appContext,
mResourcesManager.getConfiguration().getLocales());
@@ -5802,9 +5783,9 @@
}
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
- final LoadedApk loadedApk = getLoadedApk(instrApp, data.compatInfo,
+ final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
- final ContextImpl instrContext = ContextImpl.createAppContext(this, loadedApk);
+ final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
final ClassLoader cl = instrContext.getClassLoader();
@@ -5849,7 +5830,7 @@
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
- app = data.loadedApk.makeApplication(data.restrictedBackupMode, null);
+ app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
// don't bring up providers in restricted mode; they may depend on the
@@ -5903,7 +5884,7 @@
final int preloadedFontsResource = info.metaData.getInt(
ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
if (preloadedFontsResource != 0) {
- data.loadedApk.getResources().preloadFonts(preloadedFontsResource);
+ data.info.getResources().preloadFonts(preloadedFontsResource);
}
}
} catch (RemoteException e) {
@@ -6361,12 +6342,12 @@
try {
final java.lang.ClassLoader cl = c.getClassLoader();
- LoadedApk loadedApk = peekLoadedApk(ai.packageName, true);
- if (loadedApk == null) {
+ LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
+ if (packageInfo == null) {
// System startup case.
- loadedApk = getSystemContext().mLoadedApk;
+ packageInfo = getSystemContext().mPackageInfo;
}
- localProvider = loadedApk.getAppFactory()
+ localProvider = packageInfo.getAppFactory()
.instantiateProvider(cl, info.name);
provider = localProvider.getIContentProvider();
if (provider == null) {
@@ -6515,8 +6496,8 @@
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
ContextImpl context = ContextImpl.createAppContext(
- this, getSystemContext().mLoadedApk);
- mInitialApplication = context.mLoadedApk.makeApplication(true, null);
+ this, getSystemContext().mPackageInfo);
+ mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 5822f5c..a13ac49 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -86,11 +86,21 @@
/**
* Called when the application is starting, before any activity, service,
* or receiver objects (excluding content providers) have been created.
- * Implementations should be as quick as possible (for example using
+ *
+ * <p>Implementations should be as quick as possible (for example using
* lazy initialization of state) since the time spent in this function
* directly impacts the performance of starting the first activity,
- * service, or receiver in a process.
- * If you override this method, be sure to call super.onCreate().
+ * service, or receiver in a process.</p>
+ *
+ * <p>If you override this method, be sure to call {@code super.onCreate()}.</p>
+ *
+ * <p class="note">Be aware that direct boot may also affect callback order on
+ * Android {@link android.os.Build.VERSION_CODES#N} and later devices.
+ * Until the user unlocks the device, only direct boot aware components are
+ * allowed to run. You should consider that all direct boot unaware
+ * components, including such {@link android.content.ContentProvider}, are
+ * disabled until user unlock happens, especially when component callback
+ * order matters.</p>
*/
@CallSuper
public void onCreate() {
@@ -187,7 +197,7 @@
*/
/* package */ final void attach(Context context) {
attachBaseContext(context);
- mLoadedApk = ContextImpl.getImpl(context).mLoadedApk;
+ mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
/* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index cc68c05..6b0a2f9 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1409,7 +1409,7 @@
sameUid ? app.sourceDir : app.publicSourceDir,
sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs,
app.resourceDirs, app.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
- mContext.mLoadedApk);
+ mContext.mPackageInfo);
if (r != null) {
return r;
}
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 0f66652..5b61fdf 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -111,7 +111,7 @@
PendingTransactionActions pendingActions);
/** Get package info. */
- public abstract LoadedApk getLoadedApkNoCheck(ApplicationInfo ai,
+ public abstract LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo);
/** Deliver app configuration change notification. */
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index ea94042..6496110 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -159,7 +159,7 @@
private ArrayMap<String, File> mSharedPrefsPaths;
final @NonNull ActivityThread mMainThread;
- final @NonNull LoadedApk mLoadedApk;
+ final @NonNull LoadedApk mPackageInfo;
private @Nullable ClassLoader mClassLoader;
private final @Nullable IBinder mActivityToken;
@@ -257,8 +257,8 @@
@Override
public Context getApplicationContext() {
- return (mLoadedApk != null) ?
- mLoadedApk.getApplication() : mMainThread.getApplication();
+ return (mPackageInfo != null) ?
+ mPackageInfo.getApplication() : mMainThread.getApplication();
}
@Override
@@ -302,15 +302,15 @@
@Override
public ClassLoader getClassLoader() {
- return mClassLoader != null ? mClassLoader : (mLoadedApk != null ? mLoadedApk.getClassLoader() : ClassLoader.getSystemClassLoader());
+ return mClassLoader != null ? mClassLoader : (mPackageInfo != null ? mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader());
}
@Override
public String getPackageName() {
- if (mLoadedApk != null) {
- return mLoadedApk.getPackageName();
+ if (mPackageInfo != null) {
+ return mPackageInfo.getPackageName();
}
- // No mLoadedApk means this is a Context for the system itself,
+ // No mPackageInfo means this is a Context for the system itself,
// and this here is its name.
return "android";
}
@@ -329,24 +329,24 @@
@Override
public ApplicationInfo getApplicationInfo() {
- if (mLoadedApk != null) {
- return mLoadedApk.getApplicationInfo();
+ if (mPackageInfo != null) {
+ return mPackageInfo.getApplicationInfo();
}
throw new RuntimeException("Not supported in system context");
}
@Override
public String getPackageResourcePath() {
- if (mLoadedApk != null) {
- return mLoadedApk.getResDir();
+ if (mPackageInfo != null) {
+ return mPackageInfo.getResDir();
}
throw new RuntimeException("Not supported in system context");
}
@Override
public String getPackageCodePath() {
- if (mLoadedApk != null) {
- return mLoadedApk.getAppDir();
+ if (mPackageInfo != null) {
+ return mPackageInfo.getAppDir();
}
throw new RuntimeException("Not supported in system context");
}
@@ -356,7 +356,7 @@
// At least one application in the world actually passes in a null
// name. This happened to work because when we generated the file name
// we would stringify it to "null.xml". Nice.
- if (mLoadedApk.getApplicationInfo().targetSdkVersion <
+ if (mPackageInfo.getApplicationInfo().targetSdkVersion <
Build.VERSION_CODES.KITKAT) {
if (name == null) {
name = "null";
@@ -1104,11 +1104,11 @@
warnIfCallingFromSystemProcess();
IIntentReceiver rd = null;
if (resultReceiver != null) {
- if (mLoadedApk != null) {
+ if (mPackageInfo != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = mLoadedApk.getReceiverDispatcher(
+ rd = mPackageInfo.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
@@ -1208,11 +1208,11 @@
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
IIntentReceiver rd = null;
if (resultReceiver != null) {
- if (mLoadedApk != null) {
+ if (mPackageInfo != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = mLoadedApk.getReceiverDispatcher(
+ rd = mPackageInfo.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
@@ -1262,11 +1262,11 @@
warnIfCallingFromSystemProcess();
IIntentReceiver rd = null;
if (resultReceiver != null) {
- if (mLoadedApk != null) {
+ if (mPackageInfo != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = mLoadedApk.getReceiverDispatcher(
+ rd = mPackageInfo.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
@@ -1344,11 +1344,11 @@
Bundle initialExtras) {
IIntentReceiver rd = null;
if (resultReceiver != null) {
- if (mLoadedApk != null) {
+ if (mPackageInfo != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = mLoadedApk.getReceiverDispatcher(
+ rd = mPackageInfo.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
@@ -1425,11 +1425,11 @@
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (receiver != null) {
- if (mLoadedApk != null && context != null) {
+ if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = mLoadedApk.getReceiverDispatcher(
+ rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
@@ -1456,8 +1456,8 @@
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
- if (mLoadedApk != null) {
- IIntentReceiver rd = mLoadedApk.forgetReceiverDispatcher(
+ if (mPackageInfo != null) {
+ IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
getOuterContext(), receiver);
try {
ActivityManager.getService().unregisterReceiver(rd);
@@ -1590,7 +1590,7 @@
@Override
public IServiceConnection getServiceDispatcher(ServiceConnection conn, Handler handler,
int flags) {
- return mLoadedApk.getServiceDispatcher(conn, getOuterContext(), handler, flags);
+ return mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
/** @hide */
@@ -1612,16 +1612,16 @@
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
- if (mLoadedApk != null) {
- sd = mLoadedApk.getServiceDispatcher(conn, getOuterContext(), handler, flags);
+ if (mPackageInfo != null) {
+ sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
- if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mLoadedApk != null
- && mLoadedApk.getApplicationInfo().targetSdkVersion
+ if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
+ && mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
@@ -1645,8 +1645,8 @@
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
- if (mLoadedApk != null) {
- IServiceConnection sd = mLoadedApk.forgetServiceDispatcher(
+ if (mPackageInfo != null) {
+ IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
getOuterContext(), conn);
try {
ActivityManager.getService().unbindService(sd);
@@ -1991,20 +1991,40 @@
}
}
+ private static Resources createResources(IBinder activityToken, LoadedApk pi, String splitName,
+ int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) {
+ final String[] splitResDirs;
+ final ClassLoader classLoader;
+ try {
+ splitResDirs = pi.getSplitPaths(splitName);
+ classLoader = pi.getSplitClassLoader(splitName);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ return ResourcesManager.getInstance().getResources(activityToken,
+ pi.getResDir(),
+ splitResDirs,
+ pi.getOverlayDirs(),
+ pi.getApplicationInfo().sharedLibraryFiles,
+ displayId,
+ overrideConfig,
+ compatInfo,
+ classLoader);
+ }
+
@Override
public Context createApplicationContext(ApplicationInfo application, int flags)
throws NameNotFoundException {
- LoadedApk loadedApk = mMainThread.getLoadedApk(application,
- mResources.getCompatibilityInfo(),
+ LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE);
- if (loadedApk != null) {
- ContextImpl c = new ContextImpl(this, mMainThread, loadedApk, null, mActivityToken,
+ if (pi != null) {
+ ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken,
new UserHandle(UserHandle.getUserId(application.uid)), flags, null);
final int displayId = mDisplay != null
? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- c.setResources(loadedApk.createResources(mActivityToken, null, displayId, null,
+ c.setResources(createResources(mActivityToken, pi, null, displayId, null,
getDisplayAdjustments(displayId).getCompatibilityInfo()));
if (c.mResources != null) {
return c;
@@ -2028,21 +2048,20 @@
if (packageName.equals("system") || packageName.equals("android")) {
// The system resources are loaded in every application, so we can safely copy
// the context without reloading Resources.
- return new ContextImpl(this, mMainThread, mLoadedApk, null, mActivityToken, user,
+ return new ContextImpl(this, mMainThread, mPackageInfo, null, mActivityToken, user,
flags, null);
}
- LoadedApk loadedApk = mMainThread.getLoadedApkForPackageName(packageName,
- mResources.getCompatibilityInfo(),
+ LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
- if (loadedApk != null) {
- ContextImpl c = new ContextImpl(this, mMainThread, loadedApk, null, mActivityToken, user,
+ if (pi != null) {
+ ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user,
flags, null);
final int displayId = mDisplay != null
? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- c.setResources(loadedApk.createResources(mActivityToken, null, displayId, null,
+ c.setResources(createResources(mActivityToken, pi, null, displayId, null,
getDisplayAdjustments(displayId).getCompatibilityInfo()));
if (c.mResources != null) {
return c;
@@ -2056,21 +2075,30 @@
@Override
public Context createContextForSplit(String splitName) throws NameNotFoundException {
- if (!mLoadedApk.getApplicationInfo().requestsIsolatedSplitLoading()) {
+ if (!mPackageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) {
// All Splits are always loaded.
return this;
}
- final ClassLoader classLoader = mLoadedApk.getSplitClassLoader(splitName);
+ final ClassLoader classLoader = mPackageInfo.getSplitClassLoader(splitName);
+ final String[] paths = mPackageInfo.getSplitPaths(splitName);
- final ContextImpl context = new ContextImpl(this, mMainThread, mLoadedApk, splitName,
+ final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, splitName,
mActivityToken, mUser, mFlags, classLoader);
final int displayId = mDisplay != null
? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- context.setResources(mLoadedApk.getOrCreateResourcesForSplit(splitName,
- mActivityToken, displayId));
+ context.setResources(ResourcesManager.getInstance().getResources(
+ mActivityToken,
+ mPackageInfo.getResDir(),
+ paths,
+ mPackageInfo.getOverlayDirs(),
+ mPackageInfo.getApplicationInfo().sharedLibraryFiles,
+ displayId,
+ null,
+ mPackageInfo.getCompatibilityInfo(),
+ classLoader));
return context;
}
@@ -2080,11 +2108,11 @@
throw new IllegalArgumentException("overrideConfiguration must not be null");
}
- ContextImpl context = new ContextImpl(this, mMainThread, mLoadedApk, mSplitName,
+ ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName,
mActivityToken, mUser, mFlags, mClassLoader);
final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- context.setResources(mLoadedApk.createResources(mActivityToken, mSplitName, displayId,
+ context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo()));
return context;
}
@@ -2095,11 +2123,11 @@
throw new IllegalArgumentException("display must not be null");
}
- ContextImpl context = new ContextImpl(this, mMainThread, mLoadedApk, mSplitName,
+ ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName,
mActivityToken, mUser, mFlags, mClassLoader);
final int displayId = display.getDisplayId();
- context.setResources(mLoadedApk.createResources(mActivityToken, mSplitName, displayId,
+ context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
null, getDisplayAdjustments(displayId).getCompatibilityInfo()));
context.mDisplay = display;
return context;
@@ -2109,7 +2137,7 @@
public Context createDeviceProtectedStorageContext() {
final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
| Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
- return new ContextImpl(this, mMainThread, mLoadedApk, mSplitName, mActivityToken, mUser,
+ return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser,
flags, mClassLoader);
}
@@ -2117,7 +2145,7 @@
public Context createCredentialProtectedStorageContext() {
final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
| Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
- return new ContextImpl(this, mMainThread, mLoadedApk, mSplitName, mActivityToken, mUser,
+ return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser,
flags, mClassLoader);
}
@@ -2166,14 +2194,14 @@
@Override
public File getDataDir() {
- if (mLoadedApk != null) {
+ if (mPackageInfo != null) {
File res = null;
if (isCredentialProtectedStorage()) {
- res = mLoadedApk.getCredentialProtectedDataDirFile();
+ res = mPackageInfo.getCredentialProtectedDataDirFile();
} else if (isDeviceProtectedStorage()) {
- res = mLoadedApk.getDeviceProtectedDataDirFile();
+ res = mPackageInfo.getDeviceProtectedDataDirFile();
} else {
- res = mLoadedApk.getDataDirFile();
+ res = mPackageInfo.getDataDirFile();
}
if (res != null) {
@@ -2224,10 +2252,10 @@
}
static ContextImpl createSystemContext(ActivityThread mainThread) {
- LoadedApk loadedApk = new LoadedApk(mainThread);
- ContextImpl context = new ContextImpl(null, mainThread, loadedApk, null, null, null, 0,
+ LoadedApk packageInfo = new LoadedApk(mainThread);
+ ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
null);
- context.setResources(loadedApk.getResources());
+ context.setResources(packageInfo.getResources());
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetrics());
return context;
@@ -2238,35 +2266,35 @@
* Make sure that the created system UI context shares the same LoadedApk as the system context.
*/
static ContextImpl createSystemUiContext(ContextImpl systemContext) {
- final LoadedApk loadedApk = systemContext.mLoadedApk;
- ContextImpl context = new ContextImpl(null, systemContext.mMainThread, loadedApk, null,
+ final LoadedApk packageInfo = systemContext.mPackageInfo;
+ ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
null, null, 0, null);
- context.setResources(loadedApk.createResources(null, null, Display.DEFAULT_DISPLAY, null,
- loadedApk.getCompatibilityInfo()));
+ context.setResources(createResources(null, packageInfo, null, Display.DEFAULT_DISPLAY, null,
+ packageInfo.getCompatibilityInfo()));
return context;
}
- static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk loadedApk) {
- if (loadedApk == null) throw new IllegalArgumentException("loadedApk");
- ContextImpl context = new ContextImpl(null, mainThread, loadedApk, null, null, null, 0,
+ static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
+ if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
+ ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
null);
- context.setResources(loadedApk.getResources());
+ context.setResources(packageInfo.getResources());
return context;
}
static ContextImpl createActivityContext(ActivityThread mainThread,
- LoadedApk loadedApk, ActivityInfo activityInfo, IBinder activityToken, int displayId,
+ LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
Configuration overrideConfiguration) {
- if (loadedApk == null) throw new IllegalArgumentException("loadedApk");
+ if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
- String[] splitDirs = loadedApk.getSplitResDirs();
- ClassLoader classLoader = loadedApk.getClassLoader();
+ String[] splitDirs = packageInfo.getSplitResDirs();
+ ClassLoader classLoader = packageInfo.getClassLoader();
- if (loadedApk.getApplicationInfo().requestsIsolatedSplitLoading()) {
+ if (packageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "SplitDependencies");
try {
- classLoader = loadedApk.getSplitClassLoader(activityInfo.splitName);
- splitDirs = loadedApk.getSplitPaths(activityInfo.splitName);
+ classLoader = packageInfo.getSplitClassLoader(activityInfo.splitName);
+ splitDirs = packageInfo.getSplitPaths(activityInfo.splitName);
} catch (NameNotFoundException e) {
// Nothing above us can handle a NameNotFoundException, better crash.
throw new RuntimeException(e);
@@ -2275,14 +2303,14 @@
}
}
- ContextImpl context = new ContextImpl(null, mainThread, loadedApk, activityInfo.splitName,
+ ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
activityToken, null, 0, classLoader);
// Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY.
displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY;
final CompatibilityInfo compatInfo = (displayId == Display.DEFAULT_DISPLAY)
- ? loadedApk.getCompatibilityInfo()
+ ? packageInfo.getCompatibilityInfo()
: CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
final ResourcesManager resourcesManager = ResourcesManager.getInstance();
@@ -2290,10 +2318,10 @@
// Create the base resources for which all configuration contexts for this Activity
// will be rebased upon.
context.setResources(resourcesManager.createBaseActivityResources(activityToken,
- loadedApk.getResDir(),
+ packageInfo.getResDir(),
splitDirs,
- loadedApk.getOverlayDirs(),
- loadedApk.getApplicationInfo().sharedLibraryFiles,
+ packageInfo.getOverlayDirs(),
+ packageInfo.getApplicationInfo().sharedLibraryFiles,
displayId,
overrideConfiguration,
compatInfo,
@@ -2304,7 +2332,7 @@
}
private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
- @NonNull LoadedApk loadedApk, @Nullable String splitName,
+ @NonNull LoadedApk packageInfo, @Nullable String splitName,
@Nullable IBinder activityToken, @Nullable UserHandle user, int flags,
@Nullable ClassLoader classLoader) {
mOuterContext = this;
@@ -2313,10 +2341,10 @@
// location for application.
if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE
| Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) {
- final File dataDir = loadedApk.getDataDirFile();
- if (Objects.equals(dataDir, loadedApk.getCredentialProtectedDataDirFile())) {
+ final File dataDir = packageInfo.getDataDirFile();
+ if (Objects.equals(dataDir, packageInfo.getCredentialProtectedDataDirFile())) {
flags |= Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
- } else if (Objects.equals(dataDir, loadedApk.getDeviceProtectedDataDirFile())) {
+ } else if (Objects.equals(dataDir, packageInfo.getDeviceProtectedDataDirFile())) {
flags |= Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
}
}
@@ -2330,7 +2358,7 @@
}
mUser = user;
- mLoadedApk = loadedApk;
+ mPackageInfo = packageInfo;
mSplitName = splitName;
mClassLoader = classLoader;
mResourcesManager = ResourcesManager.getInstance();
@@ -2341,8 +2369,8 @@
setResources(container.mResources);
mDisplay = container.mDisplay;
} else {
- mBasePackageName = loadedApk.mPackageName;
- ApplicationInfo ainfo = loadedApk.getApplicationInfo();
+ mBasePackageName = packageInfo.mPackageName;
+ ApplicationInfo ainfo = packageInfo.getApplicationInfo();
if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {
// Special case: system components allow themselves to be loaded in to other
// processes. For purposes of app ops, we must then consider the context as
@@ -2365,7 +2393,7 @@
}
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
- mLoadedApk.installSystemApplicationInfo(info, classLoader);
+ mPackageInfo.installSystemApplicationInfo(info, classLoader);
}
final void scheduleFinalCleanup(String who, String what) {
@@ -2374,7 +2402,7 @@
final void performFinalCleanup(String who, String what) {
//Log.i(TAG, "Cleanup up context: " + this);
- mLoadedApk.removeContextRegistrations(getOuterContext(), who, what);
+ mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
}
final Context getReceiverRestrictedContext() {
diff --git a/core/java/android/app/EphemeralResolverService.java b/core/java/android/app/EphemeralResolverService.java
deleted file mode 100644
index 427a0386..0000000
--- a/core/java/android/app/EphemeralResolverService.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.annotation.SystemApi;
-import android.app.Service;
-import android.app.InstantAppResolverService.InstantAppResolutionCallback;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.EphemeralResolveInfo;
-import android.content.pm.InstantAppResolveInfo;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.IRemoteCallback;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Base class for implementing the resolver service.
- * @hide
- * @removed
- * @deprecated use InstantAppResolverService instead
- */
-@Deprecated
-@SystemApi
-public abstract class EphemeralResolverService extends InstantAppResolverService {
- private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
- private static final String TAG = "PackageManager";
-
- /**
- * Called to retrieve resolve info for ephemeral applications.
- *
- * @param digestPrefix The hash prefix of the ephemeral's domain.
- * @param prefixMask A mask that was applied to each digest prefix. This should
- * be used when comparing against the digest prefixes as all bits might
- * not be set.
- * @deprecated use {@link #onGetEphemeralResolveInfo(int[])} instead
- */
- @Deprecated
- public abstract List<EphemeralResolveInfo> onEphemeralResolveInfoList(
- int digestPrefix[], int prefix);
-
- /**
- * Called to retrieve resolve info for ephemeral applications.
- *
- * @param digestPrefix The hash prefix of the ephemeral's domain.
- */
- public List<EphemeralResolveInfo> onGetEphemeralResolveInfo(int digestPrefix[]) {
- return onEphemeralResolveInfoList(digestPrefix, 0xFFFFF000);
- }
-
- /**
- * Called to retrieve intent filters for ephemeral applications.
- *
- * @param hostName The name of the host to get intent filters for.
- */
- public EphemeralResolveInfo onGetEphemeralIntentFilter(String hostName) {
- throw new IllegalStateException("Must define");
- }
-
- @Override
- public Looper getLooper() {
- return super.getLooper();
- }
-
- @Override
- void _onGetInstantAppResolveInfo(int[] digestPrefix, String token,
- InstantAppResolutionCallback callback) {
- if (DEBUG_EPHEMERAL) {
- Log.d(TAG, "Legacy resolver; getInstantAppResolveInfo;"
- + " prefix: " + Arrays.toString(digestPrefix));
- }
- final List<EphemeralResolveInfo> response = onGetEphemeralResolveInfo(digestPrefix);
- final int responseSize = response == null ? 0 : response.size();
- final List<InstantAppResolveInfo> resultList = new ArrayList<>(responseSize);
- for (int i = 0; i < responseSize; i++) {
- resultList.add(response.get(i).getInstantAppResolveInfo());
- }
- callback.onInstantAppResolveInfo(resultList);
- }
-
- @Override
- void _onGetInstantAppIntentFilter(int[] digestPrefix, String token,
- String hostName, InstantAppResolutionCallback callback) {
- if (DEBUG_EPHEMERAL) {
- Log.d(TAG, "Legacy resolver; getInstantAppIntentFilter;"
- + " prefix: " + Arrays.toString(digestPrefix));
- }
- final EphemeralResolveInfo response = onGetEphemeralIntentFilter(hostName);
- final List<InstantAppResolveInfo> resultList = new ArrayList<>(1);
- resultList.add(response.getInstantAppResolveInfo());
- callback.onInstantAppResolveInfo(resultList);
- }
-}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index b25deea..02be002 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -66,6 +66,7 @@
import android.os.StrictMode;
import android.os.WorkSource;
import android.service.voice.IVoiceInteractionSession;
+import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationDefinition;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.IResultReceiver;
@@ -443,8 +444,9 @@
in Bundle options, int userId);
int startAssistantActivity(in String callingPackage, int callingPid, int callingUid,
in Intent intent, in String resolvedType, in Bundle options, int userId);
- int startRecentsActivity(in IAssistDataReceiver assistDataReceiver, in Bundle options,
- in Bundle activityOptions, int userId);
+ void startRecentsActivity(in Intent intent, in IAssistDataReceiver assistDataReceiver,
+ in IRecentsAnimationRunner recentsAnimationRunner);
+ void cancelRecentsAnimation();
int startActivityFromRecents(int taskId, in Bundle options);
Bundle getActivityOptions(in IBinder token);
List<IBinder> getAppTasks(in String callingPackage);
@@ -454,11 +456,10 @@
boolean isTopOfTask(in IBinder token);
void notifyLaunchTaskBehindComplete(in IBinder token);
void notifyEnterAnimationComplete(in IBinder token);
- IBinder requestStartActivityPermissionToken(in IBinder delegatorToken);
int startActivityAsCaller(in IApplicationThread caller, in String callingPackage,
in Intent intent, in String resolvedType, in IBinder resultTo, in String resultWho,
int requestCode, int flags, in ProfilerInfo profilerInfo, in Bundle options,
- in IBinder permissionToken, boolean ignoreTargetSecurity, int userId);
+ boolean ignoreTargetSecurity, int userId);
int addAppTask(in IBinder activityToken, in Intent intent,
in ActivityManager.TaskDescription description, in Bitmap thumbnail);
Point getAppTaskThumbnailSize();
diff --git a/core/java/android/app/IInstantAppResolver.aidl b/core/java/android/app/IInstantAppResolver.aidl
index 805d8c0..ae20057 100644
--- a/core/java/android/app/IInstantAppResolver.aidl
+++ b/core/java/android/app/IInstantAppResolver.aidl
@@ -16,13 +16,15 @@
package android.app;
+import android.content.Intent;
import android.os.IRemoteCallback;
/** @hide */
oneway interface IInstantAppResolver {
- void getInstantAppResolveInfoList(in int[] digestPrefix,
+ void getInstantAppResolveInfoList(in Intent sanitizedIntent, in int[] hostDigestPrefix,
String token, int sequence, IRemoteCallback callback);
- void getInstantAppIntentFilterList(in int[] digestPrefix,
- String token, String hostName, IRemoteCallback callback);
+ void getInstantAppIntentFilterList(in Intent sanitizedIntent, in int[] hostDigestPrefix,
+ String token, IRemoteCallback callback);
+
}
diff --git a/core/java/android/app/InstantAppResolverService.java b/core/java/android/app/InstantAppResolverService.java
index c5dc86c..76a3682 100644
--- a/core/java/android/app/InstantAppResolverService.java
+++ b/core/java/android/app/InstantAppResolverService.java
@@ -17,7 +17,6 @@
package android.app;
import android.annotation.SystemApi;
-import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.InstantAppResolveInfo;
@@ -35,6 +34,7 @@
import com.android.internal.os.SomeArgs;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -43,7 +43,7 @@
*/
@SystemApi
public abstract class InstantAppResolverService extends Service {
- private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
+ private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;
private static final String TAG = "PackageManager";
/** @hide */
@@ -53,23 +53,65 @@
Handler mHandler;
/**
- * Called to retrieve resolve info for instant applications.
+ * Called to retrieve resolve info for instant applications immediately.
*
* @param digestPrefix The hash prefix of the instant app's domain.
+ * @deprecated should implement {@link #onGetInstantAppResolveInfo(Intent, int[], String,
+ * InstantAppResolutionCallback)}
*/
+ @Deprecated
public void onGetInstantAppResolveInfo(
int digestPrefix[], String token, InstantAppResolutionCallback callback) {
throw new IllegalStateException("Must define");
}
/**
- * Called to retrieve intent filters for instant applications.
+ * Called to retrieve intent filters for instant applications from potentially expensive
+ * sources.
*
* @param digestPrefix The hash prefix of the instant app's domain.
+ * @deprecated should implement {@link #onGetInstantAppIntentFilter(Intent, int[], String,
+ * InstantAppResolutionCallback)}
*/
+ @Deprecated
public void onGetInstantAppIntentFilter(
int digestPrefix[], String token, InstantAppResolutionCallback callback) {
- throw new IllegalStateException("Must define");
+ throw new IllegalStateException("Must define onGetInstantAppIntentFilter");
+ }
+
+ /**
+ * Called to retrieve resolve info for instant applications immediately.
+ *
+ * @param sanitizedIntent The sanitized {@link Intent} used for resolution.
+ * @param hostDigestPrefix The hash prefix of the instant app's domain.
+ */
+ public void onGetInstantAppResolveInfo(Intent sanitizedIntent, int[] hostDigestPrefix,
+ String token, InstantAppResolutionCallback callback) {
+ // if not overridden, forward to old methods and filter out non-web intents
+ if (sanitizedIntent.isBrowsableWebIntent()) {
+ onGetInstantAppResolveInfo(hostDigestPrefix, token, callback);
+ } else {
+ callback.onInstantAppResolveInfo(Collections.emptyList());
+ }
+ }
+
+ /**
+ * Called to retrieve intent filters for instant applications from potentially expensive
+ * sources.
+ *
+ * @param sanitizedIntent The sanitized {@link Intent} used for resolution.
+ * @param hostDigestPrefix The hash prefix of the instant app's domain or null if no host is
+ * defined.
+ */
+ public void onGetInstantAppIntentFilter(Intent sanitizedIntent, int[] hostDigestPrefix,
+ String token, InstantAppResolutionCallback callback) {
+ Log.e(TAG, "New onGetInstantAppIntentFilter is not overridden");
+ // if not overridden, forward to old methods and filter out non-web intents
+ if (sanitizedIntent.isBrowsableWebIntent()) {
+ onGetInstantAppIntentFilter(hostDigestPrefix, token, callback);
+ } else {
+ callback.onInstantAppResolveInfo(Collections.emptyList());
+ }
}
/**
@@ -89,33 +131,33 @@
public final IBinder onBind(Intent intent) {
return new IInstantAppResolver.Stub() {
@Override
- public void getInstantAppResolveInfoList(
- int digestPrefix[], String token, int sequence, IRemoteCallback callback) {
- if (DEBUG_EPHEMERAL) {
+ public void getInstantAppResolveInfoList(Intent sanitizedIntent, int[] digestPrefix,
+ String token, int sequence, IRemoteCallback callback) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "[" + token + "] Phase1 called; posting");
}
final SomeArgs args = SomeArgs.obtain();
args.arg1 = callback;
args.arg2 = digestPrefix;
args.arg3 = token;
- mHandler.obtainMessage(
- ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO, sequence, 0, args)
- .sendToTarget();
+ args.arg4 = sanitizedIntent;
+ mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO,
+ sequence, 0, args).sendToTarget();
}
@Override
- public void getInstantAppIntentFilterList(
- int digestPrefix[], String token, String hostName, IRemoteCallback callback) {
- if (DEBUG_EPHEMERAL) {
+ public void getInstantAppIntentFilterList(Intent sanitizedIntent,
+ int[] digestPrefix, String token, IRemoteCallback callback) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "[" + token + "] Phase2 called; posting");
}
final SomeArgs args = SomeArgs.obtain();
args.arg1 = callback;
args.arg2 = digestPrefix;
args.arg3 = token;
- args.arg4 = hostName;
- mHandler.obtainMessage(
- ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER, callback).sendToTarget();
+ args.arg4 = sanitizedIntent;
+ mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER,
+ callback).sendToTarget();
}
};
}
@@ -142,29 +184,9 @@
}
}
- @Deprecated
- void _onGetInstantAppResolveInfo(int[] digestPrefix, String token,
- InstantAppResolutionCallback callback) {
- if (DEBUG_EPHEMERAL) {
- Slog.d(TAG, "[" + token + "] Phase1 request;"
- + " prefix: " + Arrays.toString(digestPrefix));
- }
- onGetInstantAppResolveInfo(digestPrefix, token, callback);
- }
- @Deprecated
- void _onGetInstantAppIntentFilter(int digestPrefix[], String token, String hostName,
- InstantAppResolutionCallback callback) {
- if (DEBUG_EPHEMERAL) {
- Slog.d(TAG, "[" + token + "] Phase2 request;"
- + " prefix: " + Arrays.toString(digestPrefix));
- }
- onGetInstantAppIntentFilter(digestPrefix, token, callback);
- }
-
private final class ServiceHandler extends Handler {
public static final int MSG_GET_INSTANT_APP_RESOLVE_INFO = 1;
public static final int MSG_GET_INSTANT_APP_INTENT_FILTER = 2;
-
public ServiceHandler(Looper looper) {
super(looper, null /*callback*/, true /*async*/);
}
@@ -179,9 +201,13 @@
final IRemoteCallback callback = (IRemoteCallback) args.arg1;
final int[] digestPrefix = (int[]) args.arg2;
final String token = (String) args.arg3;
+ final Intent intent = (Intent) args.arg4;
final int sequence = message.arg1;
- _onGetInstantAppResolveInfo(
- digestPrefix, token,
+ if (DEBUG_INSTANT) {
+ Slog.d(TAG, "[" + token + "] Phase1 request;"
+ + " prefix: " + Arrays.toString(digestPrefix));
+ }
+ onGetInstantAppResolveInfo(intent, digestPrefix, token,
new InstantAppResolutionCallback(sequence, callback));
} break;
@@ -190,9 +216,12 @@
final IRemoteCallback callback = (IRemoteCallback) args.arg1;
final int[] digestPrefix = (int[]) args.arg2;
final String token = (String) args.arg3;
- final String hostName = (String) args.arg4;
- _onGetInstantAppIntentFilter(
- digestPrefix, token, hostName,
+ final Intent intent = (Intent) args.arg4;
+ if (DEBUG_INSTANT) {
+ Slog.d(TAG, "[" + token + "] Phase2 request;"
+ + " prefix: " + Arrays.toString(digestPrefix));
+ }
+ onGetInstantAppIntentFilter(intent, digestPrefix, token,
new InstantAppResolutionCallback(-1 /*sequence*/, callback));
} break;
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index f90b276..67f5a2e 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1216,10 +1216,10 @@
+ " disabling AppComponentFactory", new Throwable());
return AppComponentFactory.DEFAULT;
}
- LoadedApk loadedApk = mThread.peekLoadedApk(pkg, true);
+ LoadedApk apk = mThread.peekPackageInfo(pkg, true);
// This is in the case of starting up "android".
- if (loadedApk == null) loadedApk = mThread.getSystemContext().mLoadedApk;
- return loadedApk.getAppFactory();
+ if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
+ return apk.getAppFactory();
}
private void prePerformCreate(Activity activity) {
@@ -1879,8 +1879,8 @@
*/
public ActivityResult execStartActivityAsCaller(
Context who, IBinder contextThread, IBinder token, Activity target,
- Intent intent, int requestCode, Bundle options, IBinder permissionToken,
- boolean ignoreTargetSecurity, int userId) {
+ Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity,
+ int userId) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
@@ -1911,8 +1911,7 @@
.startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
- requestCode, 0, null, options, permissionToken,
- ignoreTargetSecurity, userId);
+ requestCode, 0, null, options, ignoreTargetSecurity, userId);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index d24d4f3..ea5932c 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -32,7 +32,6 @@
import android.content.pm.split.SplitDependencyLoader;
import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
@@ -964,78 +963,14 @@
throw new AssertionError("null split not found");
}
- mResources = ResourcesManager.getInstance().getResources(
- null,
- mResDir,
- splitPaths,
- mOverlayDirs,
- mApplicationInfo.sharedLibraryFiles,
- Display.DEFAULT_DISPLAY,
- null,
- getCompatibilityInfo(),
+ mResources = ResourcesManager.getInstance().getResources(null, mResDir,
+ splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
+ Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
getClassLoader());
}
return mResources;
}
- public Resources getOrCreateResourcesForSplit(@NonNull String splitName,
- @Nullable IBinder activityToken, int displayId) throws NameNotFoundException {
- return ResourcesManager.getInstance().getResources(
- activityToken,
- mResDir,
- getSplitPaths(splitName),
- mOverlayDirs,
- mApplicationInfo.sharedLibraryFiles,
- displayId,
- null,
- getCompatibilityInfo(),
- getSplitClassLoader(splitName));
- }
-
- /**
- * Creates the top level resources for the given package. Will return an existing
- * Resources if one has already been created.
- */
- public Resources getOrCreateTopLevelResources(@NonNull ApplicationInfo appInfo) {
- // Request for this app, short circuit
- if (appInfo.uid == Process.myUid()) {
- return getResources();
- }
-
- // Get resources for a different package
- return ResourcesManager.getInstance().getResources(
- null,
- appInfo.publicSourceDir,
- appInfo.splitPublicSourceDirs,
- appInfo.resourceDirs,
- appInfo.sharedLibraryFiles,
- Display.DEFAULT_DISPLAY,
- null,
- getCompatibilityInfo(),
- getClassLoader());
- }
-
- public Resources createResources(IBinder activityToken, String splitName,
- int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) {
- final String[] splitResDirs;
- final ClassLoader classLoader;
- try {
- splitResDirs = getSplitPaths(splitName);
- classLoader = getSplitClassLoader(splitName);
- } catch (NameNotFoundException e) {
- throw new RuntimeException(e);
- }
- return ResourcesManager.getInstance().getResources(activityToken,
- mResDir,
- splitResDirs,
- mOverlayDirs,
- mApplicationInfo.sharedLibraryFiles,
- displayId,
- overrideConfig,
- compatInfo,
- classLoader);
- }
-
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 998ac5f..1d34595 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -16,6 +16,8 @@
package android.app;
+import android.app.ActivityThread.ActivityClientRecord;
+import android.app.servertransaction.PendingTransactionActions;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Binder;
@@ -141,6 +143,21 @@
}
r.window = r.activity.getWindow();
r.instanceState = null;
+
+ final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r);
+ final PendingTransactionActions pendingActions;
+
+ if (!r.activity.mFinished) {
+ // This matches pending actions set in ActivityThread#handleLaunchActivity
+ pendingActions = new PendingTransactionActions();
+ pendingActions.setOldState(clientRecord.state);
+ pendingActions.setRestoreInstanceState(true);
+ pendingActions.setCallOnPostCreate(true);
+ } else {
+ pendingActions = null;
+ }
+
+ mActivityThread.handleStartActivity(clientRecord, pendingActions);
r.curState = STARTED;
if (desiredState == RESUMED) {
@@ -207,8 +224,8 @@
private void performPause(LocalActivityRecord r, boolean finishing) {
final boolean needState = r.instanceState == null;
- final Bundle instanceState = mActivityThread.performPauseActivity(
- r, finishing, needState, "performPause", null /* pendingActions */);
+ final Bundle instanceState = mActivityThread.performPauseActivity(r, finishing,
+ "performPause", null /* pendingActions */);
if (needState) {
r.instanceState = instanceState;
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0b5b363..6e40986 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -493,7 +493,7 @@
* </ul>
* <p>
* Since hardware varies, you are not guaranteed that any of the values
- * you pass are honored exactly. Use the system defaults (TODO) if possible
+ * you pass are honored exactly. Use the system defaults if possible
* because they will be set to values that work on any given hardware.
* <p>
* The alpha channel must be set for forward compatibility.
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index ea0fd75..256c479 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -471,6 +471,14 @@
* {@link #onStart} and returns either {@link #START_STICKY}
* or {@link #START_STICKY_COMPATIBILITY}.
*
+ * <p>If you need your application to run on platform versions prior to API
+ * level 5, you can use the following model to handle the older {@link #onStart}
+ * callback in that case. The <code>handleCommand</code> method is implemented by
+ * you as appropriate:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
+ * start_compatibility}
+ *
* <p class="caution">Note that the system calls this on your
* service's main thread. A service's main thread is the same
* thread where UI operations take place for Activities running in the
@@ -679,10 +687,6 @@
* {@link #startService(Intent)} first to tell the system it should keep the service running,
* and then use this method to tell it to keep it running harder.</p>
*
- * <p>Apps targeting API {@link android.os.Build.VERSION_CODES#P} or later must request
- * the permission {@link android.Manifest.permission#FOREGROUND_SERVICE} in order to use
- * this API.</p>
- *
* @param id The identifier for this notification as per
* {@link NotificationManager#notify(int, Notification)
* NotificationManager.notify(int, Notification)}; must not be 0.
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index ba39740..8f01685 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -24,6 +24,7 @@
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
@@ -46,14 +47,10 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
-
-import com.android.internal.util.CollectionUtils;
-
import libcore.io.IoUtils;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeoutException;
@@ -583,8 +580,6 @@
// Execute the command *without* the lock being held.
command.run();
- List<AccessibilityEvent> eventsReceived = Collections.emptyList();
-
// Acquire the lock and wait for the event.
try {
// Wait for the event.
@@ -605,14 +600,14 @@
if (filter.accept(event)) {
return event;
}
- eventsReceived = CollectionUtils.add(eventsReceived, event);
+ event.recycle();
}
// Check if timed out and if not wait.
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
final long remainingTimeMillis = timeoutMillis - elapsedTimeMillis;
if (remainingTimeMillis <= 0) {
throw new TimeoutException("Expected event not received within: "
- + timeoutMillis + " ms, among " + eventsReceived);
+ + timeoutMillis + " ms.");
}
synchronized (mLock) {
if (mEventQueue.isEmpty()) {
@@ -625,10 +620,6 @@
}
}
} finally {
- for (int i = 0; i < CollectionUtils.size(eventsReceived); i++) {
- AccessibilityEvent event = eventsReceived.get(i);
- event.recycle();
- }
synchronized (mLock) {
mWaitingForEventDelivery = false;
mEventQueue.clear();
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 085fc79..46566e7 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -146,6 +146,9 @@
})
public @interface WindowConfig {}
+ /** @hide */
+ public static final int PINNED_WINDOWING_MODE_ELEVATION_IN_DIP = 5;
+
public WindowConfiguration() {
unset();
}
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 1de1d2f..ed2aaf9 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -75,6 +75,10 @@
*
* <p>To control this policy, the device admin must have a "limit-password"
* tag in the "uses-policies" section of its meta-data.
+ *
+ * <p>This policy is deprecated for use by a device admin. In future releases, it will
+ * only be possible for a device owner or profile owner to enforce constraints on user
+ * passwords.
*/
public static final int USES_POLICY_LIMIT_PASSWORD = 0;
@@ -136,6 +140,9 @@
*
* <p>To control this policy, the device admin must have an "expire-password"
* tag in the "uses-policies" section of its meta-data.
+ *
+ * <p>This policy is deprecated for use by a device admin. In future releases, it will
+ * only be possible for a device owner or profile owner to enforce password expiry.
*/
public static final int USES_POLICY_EXPIRE_PASSWORD = 6;
@@ -152,6 +159,9 @@
*
* <p>To control this policy, the device admin must have a "disable-camera"
* tag in the "uses-policies" section of its meta-data.
+ *
+ * <p>This policy is deprecated for use by a device admin. In future releases, it will
+ * only be possible for a device owner or profile owner to disable use of the camera.
*/
public static final int USES_POLICY_DISABLE_CAMERA = 8;
@@ -160,6 +170,10 @@
*
* <p>To control this policy, the device admin must have a "disable-keyguard-features"
* tag in the "uses-policies" section of its meta-data.
+ *
+ * <p>This policy is deprecated for use by a device admin. In future releases, it will
+ * only be possible for a device owner or profile owner to disable use of keyguard
+ * features.
*/
public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8f76032..e190fd4 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6609,15 +6609,81 @@
}
/**
+ * Indicates user operation is successful.
+ *
+ * @see #startUserInBackground(ComponentName, UserHandle)
+ * @see #stopUser(ComponentName, UserHandle)
+ * @see #logoutUser(ComponentName)
+ */
+ public static final int USER_OPERATION_SUCCESS = 0;
+
+ /**
+ * Indicates user operation failed for unknown reason.
+ *
+ * @see #startUserInBackground(ComponentName, UserHandle)
+ * @see #stopUser(ComponentName, UserHandle)
+ * @see #logoutUser(ComponentName)
+ */
+ public static final int USER_OPERATION_ERROR_UNKNOWN = 1;
+
+ /**
+ * Indicates user operation failed because target user is a managed profile.
+ *
+ * @see #startUserInBackground(ComponentName, UserHandle)
+ * @see #stopUser(ComponentName, UserHandle)
+ * @see #logoutUser(ComponentName)
+ */
+ public static final int USER_OPERATION_ERROR_MANAGED_PROFILE = 2;
+
+ /**
+ * Indicates user operation failed because maximum running user limit has reached.
+ *
+ * @see #startUserInBackground(ComponentName, UserHandle)
+ */
+ public static final int USER_OPERATION_ERROR_MAX_RUNNING_USERS = 3;
+
+ /**
+ * Indicates user operation failed because the target user is in foreground.
+ *
+ * @see #stopUser(ComponentName, UserHandle)
+ * @see #logoutUser(ComponentName)
+ */
+ public static final int USER_OPERATION_ERROR_CURRENT_USER = 4;
+
+ /**
+ * Result returned from
+ * <ul>
+ * <li>{@link #startUserInBackground(ComponentName, UserHandle)}</li>
+ * <li>{@link #stopUser(ComponentName, UserHandle)}</li>
+ * <li>{@link #logoutUser(ComponentName)}</li>
+ * </ul>
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "USER_OPERATION_" }, value = {
+ USER_OPERATION_SUCCESS,
+ USER_OPERATION_ERROR_UNKNOWN,
+ USER_OPERATION_ERROR_MANAGED_PROFILE,
+ USER_OPERATION_ERROR_MAX_RUNNING_USERS,
+ USER_OPERATION_ERROR_CURRENT_USER
+ })
+ public @interface UserOperationResult {}
+
+ /**
* Called by a device owner to start the specified secondary user in background.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param userHandle the user to be stopped.
- * @return {@code true} if the user can be started, {@code false} otherwise.
+ * @param userHandle the user to be started in background.
+ * @return one of the following result codes:
+ * {@link #USER_OPERATION_ERROR_UNKNOWN},
+ * {@link #USER_OPERATION_SUCCESS},
+ * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE},
+ * {@link #USER_OPERATION_ERROR_MAX_RUNNING_USERS},
* @throws SecurityException if {@code admin} is not a device owner.
* @see #getSecondaryUsers(ComponentName)
*/
- public boolean startUserInBackground(
+ public @UserOperationResult int startUserInBackground(
@NonNull ComponentName admin, @NonNull UserHandle userHandle) {
throwIfParentInstance("startUserInBackground");
try {
@@ -6632,11 +6698,16 @@
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param userHandle the user to be stopped.
- * @return {@code true} if the user can be stopped, {@code false} otherwise.
+ * @return one of the following result codes:
+ * {@link #USER_OPERATION_ERROR_UNKNOWN},
+ * {@link #USER_OPERATION_SUCCESS},
+ * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE},
+ * {@link #USER_OPERATION_ERROR_CURRENT_USER}
* @throws SecurityException if {@code admin} is not a device owner.
* @see #getSecondaryUsers(ComponentName)
*/
- public boolean stopUser(@NonNull ComponentName admin, @NonNull UserHandle userHandle) {
+ public @UserOperationResult int stopUser(
+ @NonNull ComponentName admin, @NonNull UserHandle userHandle) {
throwIfParentInstance("stopUser");
try {
return mService.stopUser(admin, userHandle);
@@ -6650,11 +6721,15 @@
* calling user and switch back to primary.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @return {@code true} if the exit was successful, {@code false} otherwise.
+ * @return one of the following result codes:
+ * {@link #USER_OPERATION_ERROR_UNKNOWN},
+ * {@link #USER_OPERATION_SUCCESS},
+ * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE},
+ * {@link #USER_OPERATION_ERROR_CURRENT_USER}
* @throws SecurityException if {@code admin} is not a profile owner affiliated with the device.
* @see #getSecondaryUsers(ComponentName)
*/
- public boolean logoutUser(@NonNull ComponentName admin) {
+ public @UserOperationResult int logoutUser(@NonNull ComponentName admin) {
throwIfParentInstance("logoutUser");
try {
return mService.logoutUser(admin);
@@ -7540,13 +7615,28 @@
/**
* Called by device owners to set a local system update policy. When a new policy is set,
* {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted.
+ * <p>
+ * If the supplied system update policy has freeze periods set but the freeze periods do not
+ * meet 90-day maximum length or 60-day minimum separation requirement set out in
+ * {@link SystemUpdatePolicy#setFreezePeriods},
+ * {@link SystemUpdatePolicy.ValidationFailedException} will the thrown. Note that the system
+ * keeps a record of freeze periods the device experienced previously, and combines them with
+ * the new freeze periods to be set when checking the maximum freeze length and minimum freeze
+ * separation constraints. As a result, freeze periods that passed validation during
+ * {@link SystemUpdatePolicy#setFreezePeriods} might fail the additional checks here due to
+ * the freeze period history. If this is causing issues during development,
+ * {@code adb shell dpm clear-freeze-period-record} can be used to clear the record.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with. All
* components in the device owner package can set system update policies and the most
* recent policy takes effect.
* @param policy the new policy, or {@code null} to clear the current policy.
* @throws SecurityException if {@code admin} is not a device owner.
+ * @throws IllegalArgumentException if the policy type or maintenance window is not valid.
+ * @throws SystemUpdatePolicy.ValidationFailedException if the policy's freeze period does not
+ * meet the requirement.
* @see SystemUpdatePolicy
+ * @see SystemUpdatePolicy#setFreezePeriods(List)
*/
public void setSystemUpdatePolicy(@NonNull ComponentName admin, SystemUpdatePolicy policy) {
throwIfParentInstance("setSystemUpdatePolicy");
@@ -7577,6 +7667,22 @@
}
/**
+ * Reset record of previous system update freeze period the device went through.
+ * Only callable by ADB.
+ * @hide
+ */
+ public void clearSystemUpdatePolicyFreezePeriodRecord() {
+ throwIfParentInstance("clearSystemUpdatePolicyFreezePeriodRecord");
+ if (mService == null) {
+ return;
+ }
+ try {
+ mService.clearSystemUpdatePolicyFreezePeriodRecord();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ /**
* Called by a device owner or profile owner of secondary users that is affiliated with the
* device to disable the keyguard altogether.
* <p>
@@ -8230,7 +8336,7 @@
}
/**
- * Called by a device or profile owner to restrict packages from accessing metered data.
+ * Called by a device or profile owner to restrict packages from using metered data.
*
* @param admin which {@link DeviceAdminReceiver} this request is associated with.
* @param packageNames the list of package names to be restricted.
@@ -8252,7 +8358,7 @@
/**
* Called by a device or profile owner to retrieve the list of packages which are restricted
- * by the admin from accessing metered data.
+ * by the admin from using metered data.
*
* @param admin which {@link DeviceAdminReceiver} this request is associated with.
* @return the list of restricted package names.
@@ -8271,6 +8377,30 @@
}
/**
+ * Called by the system to check if a package is restricted from using metered data
+ * by {@param admin}.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageName the package whose restricted status is needed.
+ * @param userId the user to which {@param packageName} belongs.
+ * @return {@code true} if the package is restricted by admin, otherwise {@code false}
+ * @throws SecurityException if the caller doesn't run with {@link Process#SYSTEM_UID}
+ * @hide
+ */
+ public boolean isMeteredDataDisabledForUser(@NonNull ComponentName admin, String packageName,
+ @UserIdInt int userId) {
+ throwIfParentInstance("getMeteredDataDisabledForUser");
+ if (mService != null) {
+ try {
+ return mService.isMeteredDataDisabledForUser(admin, packageName, userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
+
+ /**
* Called by device owners to retrieve device logs from before the device's last reboot.
* <p>
* <strong> This API is not supported on all devices. Calling this API on unsupported devices
@@ -8733,6 +8863,7 @@
*/
public void setMandatoryBackupTransport(
@NonNull ComponentName admin, @Nullable ComponentName backupTransportComponent) {
+ throwIfParentInstance("setMandatoryBackupTransport");
try {
mService.setMandatoryBackupTransport(admin, backupTransportComponent);
} catch (RemoteException re) {
@@ -8748,6 +8879,7 @@
* mandatory or {@code null} if backups are not mandatory.
*/
public ComponentName getMandatoryBackupTransport() {
+ throwIfParentInstance("getMandatoryBackupTransport");
try {
return mService.getMandatoryBackupTransport();
} catch (RemoteException re) {
@@ -9045,15 +9177,15 @@
* @param executor The executor through which the listener should be invoked.
* @param listener A callback object that will inform the caller when the clearing is done.
* @throws SecurityException if the caller is not the device owner/profile owner.
- * @return whether the clearing succeeded.
*/
- public boolean clearApplicationUserData(@NonNull ComponentName admin,
+ public void clearApplicationUserData(@NonNull ComponentName admin,
@NonNull String packageName, @NonNull @CallbackExecutor Executor executor,
@NonNull OnClearApplicationUserDataListener listener) {
throwIfParentInstance("clearAppData");
Preconditions.checkNotNull(executor);
+ Preconditions.checkNotNull(listener);
try {
- return mService.clearApplicationUserData(admin, packageName,
+ mService.clearApplicationUserData(admin, packageName,
new IPackageDataObserver.Stub() {
public void onRemoveCompleted(String pkg, boolean succeeded) {
executor.execute(() ->
diff --git a/core/java/android/app/admin/FreezeInterval.java b/core/java/android/app/admin/FreezeInterval.java
new file mode 100644
index 0000000..7acdfc8
--- /dev/null
+++ b/core/java/android/app/admin/FreezeInterval.java
@@ -0,0 +1,299 @@
+/*
+ * 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.app.admin;
+
+import android.app.admin.SystemUpdatePolicy.ValidationFailedException;
+import android.util.Log;
+import android.util.Pair;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An interval representing one freeze period which repeats annually. We use the number of days
+ * since the start of (non-leap) year to define the start and end dates of an interval, both
+ * inclusive. If the end date is smaller than the start date, the interval is considered wrapped
+ * around the year-end. As far as an interval is concerned, February 29th should be treated as
+ * if it were February 28th: so an interval starting or ending on February 28th are not
+ * distinguishable from an interval on February 29th. When calulating interval length or
+ * distance between two dates, February 29th is also disregarded.
+ *
+ * @see SystemUpdatePolicy#setFreezePeriods
+ * @hide
+ */
+public class FreezeInterval {
+ private static final String TAG = "FreezeInterval";
+
+ private static final int DUMMY_YEAR = 2001;
+ static final int DAYS_IN_YEAR = 365; // 365 since DUMMY_YEAR is not a leap year
+
+ final int mStartDay; // [1,365]
+ final int mEndDay; // [1,365]
+
+ FreezeInterval(int startDay, int endDay) {
+ if (startDay < 1 || startDay > 365 || endDay < 1 || endDay > 365) {
+ throw new RuntimeException("Bad dates for Interval: " + startDay + "," + endDay);
+ }
+ mStartDay = startDay;
+ mEndDay = endDay;
+ }
+
+ int getLength() {
+ return getEffectiveEndDay() - mStartDay + 1;
+ }
+
+ boolean isWrapped() {
+ return mEndDay < mStartDay;
+ }
+
+ /**
+ * Returns the effective end day, taking wrapping around year-end into consideration
+ */
+ int getEffectiveEndDay() {
+ if (!isWrapped()) {
+ return mEndDay;
+ } else {
+ return mEndDay + DAYS_IN_YEAR;
+ }
+ }
+
+ boolean contains(LocalDate localDate) {
+ final int daysOfYear = dayOfYearDisregardLeapYear(localDate);
+ if (!isWrapped()) {
+ // ---[start---now---end]---
+ return (mStartDay <= daysOfYear) && (daysOfYear <= mEndDay);
+ } else {
+ // ---end]---[start---now---
+ // or ---now---end]---[start---
+ return (mStartDay <= daysOfYear) || (daysOfYear <= mEndDay);
+ }
+ }
+
+ /**
+ * Instantiate the current interval to real calendar dates, given a calendar date
+ * {@code now}. If the interval contains now, the returned calendar dates should be the
+ * current interval (in real calendar dates) that includes now. If the interval does not
+ * include now, the returned dates represents the next future interval.
+ * The result will always have the same month and dayOfMonth value as the non-instantiated
+ * interval itself.
+ */
+ Pair<LocalDate, LocalDate> toCurrentOrFutureRealDates(LocalDate now) {
+ final int nowDays = dayOfYearDisregardLeapYear(now);
+ final int startYearAdjustment, endYearAdjustment;
+ if (contains(now)) {
+ // current interval
+ if (mStartDay <= nowDays) {
+ // ----------[start---now---end]---
+ // or ---end]---[start---now----------
+ startYearAdjustment = 0;
+ endYearAdjustment = isWrapped() ? 1 : 0;
+ } else /* nowDays <= mEndDay */ {
+ // or ---now---end]---[start----------
+ startYearAdjustment = -1;
+ endYearAdjustment = 0;
+ }
+ } else {
+ // next interval
+ if (mStartDay > nowDays) {
+ // ----------now---[start---end]---
+ // or ---end]---now---[start----------
+ startYearAdjustment = 0;
+ endYearAdjustment = isWrapped() ? 1 : 0;
+ } else /* mStartDay <= nowDays */ {
+ // or ---[start---end]---now----------
+ startYearAdjustment = 1;
+ endYearAdjustment = 1;
+ }
+ }
+ final LocalDate startDate = LocalDate.ofYearDay(DUMMY_YEAR, mStartDay).withYear(
+ now.getYear() + startYearAdjustment);
+ final LocalDate endDate = LocalDate.ofYearDay(DUMMY_YEAR, mEndDay).withYear(
+ now.getYear() + endYearAdjustment);
+ return new Pair<>(startDate, endDate);
+ }
+
+ @Override
+ public String toString() {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd");
+ return LocalDate.ofYearDay(DUMMY_YEAR, mStartDay).format(formatter) + " - "
+ + LocalDate.ofYearDay(DUMMY_YEAR, mEndDay).format(formatter);
+ }
+
+ // Treat the supplied date as in a non-leap year and return its day of year.
+ static int dayOfYearDisregardLeapYear(LocalDate date) {
+ return date.withYear(DUMMY_YEAR).getDayOfYear();
+ }
+
+ /**
+ * Compute the number of days between first (inclusive) and second (exclusive),
+ * treating all years in between as non-leap.
+ */
+ public static int distanceWithoutLeapYear(LocalDate first, LocalDate second) {
+ return dayOfYearDisregardLeapYear(first) - dayOfYearDisregardLeapYear(second)
+ + DAYS_IN_YEAR * (first.getYear() - second.getYear());
+ }
+
+ /**
+ * Sort, de-duplicate and merge an interval list
+ *
+ * Instead of using any fancy logic for merging intervals which has loads of corner cases,
+ * simply flatten the interval onto a list of 365 calendar days and recreate the interval list
+ * from that.
+ *
+ * This method should return a list of intervals with the following post-conditions:
+ * 1. Interval.startDay in strictly ascending order
+ * 2. No two intervals should overlap or touch
+ * 3. At most one wrapped Interval remains, and it will be at the end of the list
+ * @hide
+ */
+ private static List<FreezeInterval> canonicalizeIntervals(List<FreezeInterval> intervals) {
+ boolean[] taken = new boolean[DAYS_IN_YEAR];
+ // First convert the intervals into flat array
+ for (FreezeInterval interval : intervals) {
+ for (int i = interval.mStartDay; i <= interval.getEffectiveEndDay(); i++) {
+ taken[(i - 1) % DAYS_IN_YEAR] = true;
+ }
+ }
+ // Then reconstruct intervals from the array
+ List<FreezeInterval> result = new ArrayList<>();
+ int i = 0;
+ while (i < DAYS_IN_YEAR) {
+ if (!taken[i]) {
+ i++;
+ continue;
+ }
+ final int intervalStart = i + 1;
+ while (i < DAYS_IN_YEAR && taken[i]) i++;
+ result.add(new FreezeInterval(intervalStart, i));
+ }
+ // Check if the last entry can be merged to the first entry to become one single
+ // wrapped interval
+ final int lastIndex = result.size() - 1;
+ if (lastIndex > 0 && result.get(lastIndex).mEndDay == DAYS_IN_YEAR
+ && result.get(0).mStartDay == 1) {
+ FreezeInterval wrappedInterval = new FreezeInterval(result.get(lastIndex).mStartDay,
+ result.get(0).mEndDay);
+ result.set(lastIndex, wrappedInterval);
+ result.remove(0);
+ }
+ return result;
+ }
+
+ /**
+ * Verifies if the supplied freeze periods satisfies the constraints set out in
+ * {@link SystemUpdatePolicy#setFreezePeriods(List)}, and in particular, any single freeze
+ * period cannot exceed {@link SystemUpdatePolicy#FREEZE_PERIOD_MAX_LENGTH} days, and two freeze
+ * periods need to be at least {@link SystemUpdatePolicy#FREEZE_PERIOD_MIN_SEPARATION} days
+ * apart.
+ *
+ * @hide
+ */
+ protected static void validatePeriods(List<FreezeInterval> periods) {
+ List<FreezeInterval> allPeriods = FreezeInterval.canonicalizeIntervals(periods);
+ if (allPeriods.size() != periods.size()) {
+ throw SystemUpdatePolicy.ValidationFailedException.duplicateOrOverlapPeriods();
+ }
+ for (int i = 0; i < allPeriods.size(); i++) {
+ FreezeInterval current = allPeriods.get(i);
+ if (current.getLength() > SystemUpdatePolicy.FREEZE_PERIOD_MAX_LENGTH) {
+ throw SystemUpdatePolicy.ValidationFailedException.freezePeriodTooLong("Freeze "
+ + "period " + current + " is too long: " + current.getLength() + " days");
+ }
+ FreezeInterval previous = i > 0 ? allPeriods.get(i - 1)
+ : allPeriods.get(allPeriods.size() - 1);
+ if (previous != current) {
+ final int separation;
+ if (i == 0 && !previous.isWrapped()) {
+ // -->[current]---[-previous-]<---
+ separation = current.mStartDay
+ + (DAYS_IN_YEAR - previous.mEndDay) - 1;
+ } else {
+ // --[previous]<--->[current]---------
+ // OR ----prev---]<--->[current]---[prev-
+ separation = current.mStartDay - previous.mEndDay - 1;
+ }
+ if (separation < SystemUpdatePolicy.FREEZE_PERIOD_MIN_SEPARATION) {
+ throw SystemUpdatePolicy.ValidationFailedException.freezePeriodTooClose("Freeze"
+ + " periods " + previous + " and " + current + " are too close "
+ + "together: " + separation + " days apart");
+ }
+ }
+ }
+ }
+
+ /**
+ * Verifies that the current freeze periods are still legal, considering the previous freeze
+ * periods the device went through. In particular, when combined with the previous freeze
+ * period, the maximum freeze length or the minimum freeze separation should not be violated.
+ *
+ * @hide
+ */
+ protected static void validateAgainstPreviousFreezePeriod(List<FreezeInterval> periods,
+ LocalDate prevPeriodStart, LocalDate prevPeriodEnd, LocalDate now) {
+ if (periods.size() == 0 || prevPeriodStart == null || prevPeriodEnd == null) {
+ return;
+ }
+ if (prevPeriodStart.isAfter(now) || prevPeriodEnd.isAfter(now)) {
+ Log.w(TAG, "Previous period (" + prevPeriodStart + "," + prevPeriodEnd + ") is after"
+ + " current date " + now);
+ // Clock was adjusted backwards. We can continue execution though, the separation
+ // and length validation below still works under this condition.
+ }
+ List<FreezeInterval> allPeriods = FreezeInterval.canonicalizeIntervals(periods);
+ // Given current time now, find the freeze period that's either current, or the one
+ // that's immediately afterwards. For the later case, it might be after the year-end,
+ // but this can only happen if there is only one freeze period.
+ FreezeInterval curOrNextFreezePeriod = allPeriods.get(0);
+ for (FreezeInterval interval : allPeriods) {
+ if (interval.contains(now)
+ || interval.mStartDay > FreezeInterval.dayOfYearDisregardLeapYear(now)) {
+ curOrNextFreezePeriod = interval;
+ break;
+ }
+ }
+ Pair<LocalDate, LocalDate> curOrNextFreezeDates = curOrNextFreezePeriod
+ .toCurrentOrFutureRealDates(now);
+ if (now.isAfter(curOrNextFreezeDates.first)) {
+ curOrNextFreezeDates = new Pair<>(now, curOrNextFreezeDates.second);
+ }
+ if (curOrNextFreezeDates.first.isAfter(curOrNextFreezeDates.second)) {
+ throw new IllegalStateException("Current freeze dates inverted: "
+ + curOrNextFreezeDates.first + "-" + curOrNextFreezeDates.second);
+ }
+ // Now validate [prevPeriodStart, prevPeriodEnd] against curOrNextFreezeDates
+ final String periodsDescription = "Prev: " + prevPeriodStart + "," + prevPeriodEnd
+ + "; cur: " + curOrNextFreezeDates.first + "," + curOrNextFreezeDates.second;
+ long separation = FreezeInterval.distanceWithoutLeapYear(curOrNextFreezeDates.first,
+ prevPeriodEnd) - 1;
+ if (separation > 0) {
+ // Two intervals do not overlap, check separation
+ if (separation < SystemUpdatePolicy.FREEZE_PERIOD_MIN_SEPARATION) {
+ throw ValidationFailedException.combinedPeriodTooClose("Previous freeze period "
+ + "too close to new period: " + separation + ", " + periodsDescription);
+ }
+ } else {
+ // Two intervals overlap, check combined length
+ long length = FreezeInterval.distanceWithoutLeapYear(curOrNextFreezeDates.second,
+ prevPeriodStart) + 1;
+ if (length > SystemUpdatePolicy.FREEZE_PERIOD_MAX_LENGTH) {
+ throw ValidationFailedException.combinedPeriodTooLong("Combined freeze period "
+ + "exceeds maximum days: " + length + ", " + periodsDescription);
+ }
+ }
+ }
+}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index daee6b4..5197de4 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -227,9 +227,9 @@
UserHandle createAndManageUser(in ComponentName who, in String name, in ComponentName profileOwner, in PersistableBundle adminExtras, in int flags);
boolean removeUser(in ComponentName who, in UserHandle userHandle);
boolean switchUser(in ComponentName who, in UserHandle userHandle);
- boolean startUserInBackground(in ComponentName who, in UserHandle userHandle);
- boolean stopUser(in ComponentName who, in UserHandle userHandle);
- boolean logoutUser(in ComponentName who);
+ int startUserInBackground(in ComponentName who, in UserHandle userHandle);
+ int stopUser(in ComponentName who, in UserHandle userHandle);
+ int logoutUser(in ComponentName who);
List<UserHandle> getSecondaryUsers(in ComponentName who);
void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName);
@@ -295,6 +295,7 @@
void setSystemUpdatePolicy(in ComponentName who, in SystemUpdatePolicy policy);
SystemUpdatePolicy getSystemUpdatePolicy();
+ void clearSystemUpdatePolicyFreezePeriodRecord();
boolean setKeyguardDisabled(in ComponentName admin, boolean disabled);
boolean setStatusBarDisabled(in ComponentName who, boolean disabled);
@@ -385,7 +386,7 @@
boolean isCurrentInputMethodSetByOwner();
StringParceledListSlice getOwnerInstalledCaCerts(in UserHandle user);
- boolean clearApplicationUserData(in ComponentName admin, in String packageName, in IPackageDataObserver callback);
+ void clearApplicationUserData(in ComponentName admin, in String packageName, in IPackageDataObserver callback);
void setLogoutEnabled(in ComponentName admin, boolean enabled);
boolean isLogoutEnabled();
@@ -412,4 +413,6 @@
List<ApnSetting> getOverrideApns(in ComponentName admin);
void setOverrideApnsEnabled(in ComponentName admin, boolean enabled);
boolean isOverrideApnEnabled(in ComponentName admin);
+
+ boolean isMeteredDataDisabledForUser(in ComponentName admin, String packageName, int userId);
}
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index d3b66d0..08effd9 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.TestApi;
+import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemProperties;
@@ -53,64 +54,367 @@
TAG_APP_PROCESS_START,
TAG_KEYGUARD_DISMISSED,
TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT,
- TAG_KEYGUARD_SECURED
+ TAG_KEYGUARD_SECURED,
+ TAG_OS_STARTUP,
+ TAG_OS_SHUTDOWN,
+ TAG_LOGGING_STARTED,
+ TAG_LOGGING_STOPPED,
+ TAG_MEDIA_MOUNT,
+ TAG_MEDIA_UNMOUNT,
+ TAG_LOG_BUFFER_SIZE_CRITICAL,
+ TAG_PASSWORD_EXPIRATION_SET,
+ TAG_PASSWORD_COMPLEXITY_SET,
+ TAG_PASSWORD_HISTORY_LENGTH_SET,
+ TAG_MAX_SCREEN_LOCK_TIMEOUT_SET,
+ TAG_MAX_PASSWORD_ATTEMPTS_SET,
+ TAG_KEYGUARD_DISABLED_FEATURES_SET,
+ TAG_REMOTE_LOCK,
+ TAG_USER_RESTRICTION_ADDED,
+ TAG_USER_RESTRICTION_REMOVED,
+ TAG_WIPE_FAILURE,
+ TAG_KEY_GENERATED,
+ TAG_KEY_IMPORT,
+ TAG_KEY_DESTRUCTION,
+ TAG_CERT_AUTHORITY_INSTALLED,
+ TAG_CERT_AUTHORITY_REMOVED,
})
public @interface SecurityLogTag {}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "LEVEL_" }, value = {
+ LEVEL_INFO,
+ LEVEL_WARNING,
+ LEVEL_ERROR
+ })
+ public @interface SecurityLogLevel {}
+
/**
- * Indicate that an ADB interactive shell was opened via "adb shell".
+ * Indicates that an ADB interactive shell was opened via "adb shell".
* There is no extra payload in the log event.
*/
public static final int TAG_ADB_SHELL_INTERACTIVE =
SecurityLogTags.SECURITY_ADB_SHELL_INTERACTIVE;
+
/**
- * Indicate that an shell command was issued over ADB via "adb shell command"
- * The log entry contains a string data of the shell command, accessible via
- * {@link SecurityEvent#getData()}
+ * Indicates that a shell command was issued over ADB via {@code adb shell <command>}
+ * The log entry contains a {@code String} payload containing the shell command, accessible
+ * via {@link SecurityEvent#getData()}.
*/
public static final int TAG_ADB_SHELL_CMD = SecurityLogTags.SECURITY_ADB_SHELL_COMMAND;
+
/**
- * Indicate that a file was pulled from the device via the adb daemon, for example via
- * "adb pull". The log entry contains a string data of the path of the pulled file,
- * accessible via {@link SecurityEvent#getData()}
+ * Indicates that a file was pulled from the device via the adb daemon, for example via
+ * {@code adb pull}. The log entry contains a {@code String} payload containing the path of the
+ * pulled file on the device, accessible via {@link SecurityEvent#getData()}.
*/
public static final int TAG_SYNC_RECV_FILE = SecurityLogTags.SECURITY_ADB_SYNC_RECV;
+
/**
- * Indicate that a file was pushed to the device via the adb daemon, for example via
- * "adb push". The log entry contains a string data of the destination path of the
- * pushed file, accessible via {@link SecurityEvent#getData()}
+ * Indicates that a file was pushed to the device via the adb daemon, for example via
+ * {@code adb push}. The log entry contains a {@code String} payload containing the destination
+ * path of the pushed file, accessible via {@link SecurityEvent#getData()}.
*/
public static final int TAG_SYNC_SEND_FILE = SecurityLogTags.SECURITY_ADB_SYNC_SEND;
+
/**
- * Indicate that an app process was started. The log entry contains the following
+ * Indicates that an app process was started. The log entry contains the following
* information about the process encapsulated in an {@link Object} array, accessible via
* {@link SecurityEvent#getData()}:
- * process name (String), exact start time (long), app Uid (integer), app Pid (integer),
- * seinfo tag (String), SHA-256 hash of the base APK in hexadecimal (String)
+ * <li> [0] process name ({@code String})
+ * <li> [1] exact start time in milliseconds according to {@code System.currentTimeMillis()}
+ * ({@code Long})
+ * <li> [2] app uid ({@code Integer})
+ * <li> [3] app pid ({@code Integer})
+ * <li> [4] seinfo tag ({@code String})
+ * <li> [5] SHA-256 hash of the base APK in hexadecimal ({@code String})
*/
public static final int TAG_APP_PROCESS_START = SecurityLogTags.SECURITY_APP_PROCESS_START;
+
/**
- * Indicate that keyguard is being dismissed.
+ * Indicates that keyguard has been dismissed.
* There is no extra payload in the log event.
*/
- public static final int TAG_KEYGUARD_DISMISSED =
- SecurityLogTags.SECURITY_KEYGUARD_DISMISSED;
+ public static final int TAG_KEYGUARD_DISMISSED = SecurityLogTags.SECURITY_KEYGUARD_DISMISSED;
+
/**
- * Indicate that there has been an authentication attempt to dismiss the keyguard. The log entry
- * contains the following information about the attempt encapsulated in an {@link Object} array,
- * accessible via {@link SecurityEvent#getData()}:
- * attempt result (integer, 1 for successful, 0 for unsuccessful), strength of auth method
- * (integer, 1 if strong auth method was used, 0 otherwise)
+ * Indicates that there has been an authentication attempt to dismiss the keyguard. The log
+ * entry contains the following information about the attempt encapsulated in an {@link Object}
+ * array, accessible via {@link SecurityEvent#getData()}:
+ * <li> [0] attempt result ({@code Integer}, 1 for successful, 0 for unsuccessful)
+ * <li> [1] strength of authentication method ({@code Integer}, 1 if strong authentication
+ * method was used, 0 otherwise)
*/
public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT =
SecurityLogTags.SECURITY_KEYGUARD_DISMISS_AUTH_ATTEMPT;
+
/**
- * Indicate that the device has been locked, either by user or by timeout.
- * There is no extra payload in the log event.
+ * Indicates that the device has been locked, either by the user or by a timeout. There is no
+ * extra payload in the log event.
*/
public static final int TAG_KEYGUARD_SECURED = SecurityLogTags.SECURITY_KEYGUARD_SECURED;
/**
+ * Indicates that the Android OS has started. The log entry contains the following information
+ * about the startup time software integrity check encapsulated in an {@link Object} array,
+ * accessible via {@link SecurityEvent#getData()}:
+ * <li> [0] Verified Boot state ({@code String})
+ * <li> [1] dm-verity mode ({@code String}).
+ * <p>Verified Boot state can be one of the following:
+ * <li> {@code green} indicates that there is a full chain of trust extending from the
+ * bootloader to verified partitions including the bootloader, boot partition, and all verified
+ * partitions.
+ * <li> {@code yellow} indicates that the boot partition has been verified using the embedded
+ * certificate and the signature is valid.
+ * <li> {@code orange} indicates that the device may be freely modified. Device integrity is
+ * left to the user to verify out-of-band.
+ * <p>dm-verity mode can be one of the following:
+ * <li> {@code enforcing} indicates that the device will be restarted when corruption is
+ * detected.
+ * <li> {@code eio} indicates that an I/O error will be returned for an attempt to read
+ * corrupted data blocks.
+ * For details see Verified Boot documentation.
+ */
+ public static final int TAG_OS_STARTUP = SecurityLogTags.SECURITY_OS_STARTUP;
+
+ /**
+ * Indicates that the Android OS has shutdown. There is no extra payload in the log event.
+ */
+ public static final int TAG_OS_SHUTDOWN = SecurityLogTags.SECURITY_OS_SHUTDOWN;
+
+ /**
+ * Indicates start-up of audit logging. There is no extra payload in the log event.
+ */
+ public static final int TAG_LOGGING_STARTED = SecurityLogTags.SECURITY_LOGGING_STARTED;
+
+ /**
+ * Indicates shutdown of audit logging. There is no extra payload in the log event.
+ */
+ public static final int TAG_LOGGING_STOPPED = SecurityLogTags.SECURITY_LOGGING_STOPPED;
+
+ /**
+ * Indicates that removable media has been mounted on the device. The log entry contains the
+ * following information about the event, encapsulated in an {@link Object} array and
+ * accessible via {@link SecurityEvent#getData()}:
+ * <li> [0] mount point ({@code String})
+ * <li> [1] volume label ({@code String}).
+ */
+ public static final int TAG_MEDIA_MOUNT = SecurityLogTags.SECURITY_MEDIA_MOUNTED;
+
+ /**
+ * Indicates that removable media was unmounted from the device. The log entry contains the
+ * following information about the event, encapsulated in an {@link Object} array and
+ * accessible via {@link SecurityEvent#getData()}:
+ * <li> [0] mount point ({@code String})
+ * <li> [1] volume label ({@code String}).
+ */
+ public static final int TAG_MEDIA_UNMOUNT = SecurityLogTags.SECURITY_MEDIA_UNMOUNTED;
+
+ /**
+ * Indicates that the audit log buffer has reached 90% of its capacity. There is no extra
+ * payload in the log event.
+ */
+ public static final int TAG_LOG_BUFFER_SIZE_CRITICAL =
+ SecurityLogTags.SECURITY_LOG_BUFFER_SIZE_CRITICAL;
+
+ /**
+ * Indicates that an admin has set a password expiration timeout. The log entry contains the
+ * following information about the event, encapsulated in an {@link Object} array and accessible
+ * via {@link SecurityEvent#getData()}:
+ * <li> [0] admin package name ({@code String})
+ * <li> [1] admin user ID ({@code Integer})
+ * <li> [2] target user ID ({@code Integer})
+ * <li> [3] new password expiration timeout in milliseconds ({@code Long}).
+ * @see DevicePolicyManager#setPasswordExpirationTimeout(ComponentName, long)
+ */
+ public static final int TAG_PASSWORD_EXPIRATION_SET =
+ SecurityLogTags.SECURITY_PASSWORD_EXPIRATION_SET;
+
+ /**
+ * Indicates that an admin has set a requirement for password complexity. The log entry contains
+ * the following information about the event, encapsulated in an {@link Object} array and
+ * accessible via {@link SecurityEvent#getData()}:
+ * <li> [0] admin package name ({@code String})
+ * <li> [1] admin user ID ({@code Integer})
+ * <li> [2] target user ID ({@code Integer})
+ * <li> [3] minimum password length ({@code Integer})
+ * <li> [4] password quality constraint ({@code Integer})
+ * <li> [5] minimum number of letters ({@code Integer})
+ * <li> [6] minimum number of non-letters ({@code Integer})
+ * <li> [7] minimum number of digits ({@code Integer})
+ * <li> [8] minimum number of uppercase letters ({@code Integer})
+ * <li> [9] minimum number of lowercase letters ({@code Integer})
+ * <li> [10] minimum number of symbols ({@code Integer})
+ *
+ * @see DevicePolicyManager#setPasswordMinimumLength(ComponentName, int)
+ * @see DevicePolicyManager#setPasswordQuality(ComponentName, int)
+ * @see DevicePolicyManager#setPasswordMinimumLetters(ComponentName, int)
+ * @see DevicePolicyManager#setPasswordMinimumNonLetter(ComponentName, int)
+ * @see DevicePolicyManager#setPasswordMinimumLowerCase(ComponentName, int)
+ * @see DevicePolicyManager#setPasswordMinimumUpperCase(ComponentName, int)
+ * @see DevicePolicyManager#setPasswordMinimumNumeric(ComponentName, int)
+ * @see DevicePolicyManager#setPasswordMinimumSymbols(ComponentName, int)
+ */
+ public static final int TAG_PASSWORD_COMPLEXITY_SET =
+ SecurityLogTags.SECURITY_PASSWORD_COMPLEXITY_SET;
+
+ /**
+ * Indicates that an admin has set a password history length. The log entry contains the
+ * following information about the event encapsulated in an {@link Object} array, accessible
+ * via {@link SecurityEvent#getData()}:
+ * <li> [0] admin package name ({@code String})
+ * <li> [1] admin user ID ({@code Integer})
+ * <li> [2] target user ID ({@code Integer})
+ * <li> [3] new password history length value ({@code Integer})
+ * @see DevicePolicyManager#setPasswordHistoryLength(ComponentName, int)
+ */
+ public static final int TAG_PASSWORD_HISTORY_LENGTH_SET =
+ SecurityLogTags.SECURITY_PASSWORD_HISTORY_LENGTH_SET;
+
+ /**
+ * Indicates that an admin has set a maximum screen lock timeout. The log entry contains the
+ * following information about the event encapsulated in an {@link Object} array, accessible
+ * via {@link SecurityEvent#getData()}:
+ * <li> [0] admin package name ({@code String})
+ * <li> [1] admin user ID ({@code Integer})
+ * <li> [2] target user ID ({@code Integer})
+ * <li> [3] new screen lock timeout in milliseconds ({@code Long})
+ * @see DevicePolicyManager#setMaximumTimeToLock(ComponentName, long)
+ */
+ public static final int TAG_MAX_SCREEN_LOCK_TIMEOUT_SET =
+ SecurityLogTags.SECURITY_MAX_SCREEN_LOCK_TIMEOUT_SET;
+
+ /**
+ * Indicates that an admin has set a maximum number of failed password attempts before wiping
+ * data. The log entry contains the following information about the event encapsulated in an
+ * {@link Object} array, accessible via {@link SecurityEvent#getData()}:
+ * <li> [0] admin package name ({@code String})
+ * <li> [1] admin user ID ({@code Integer})
+ * <li> [2] target user ID ({@code Integer})
+ * <li> [3] new maximum number of failed password attempts ({@code Integer})
+ * @see DevicePolicyManager#setMaximumTimeToLock(ComponentName, long)
+ */
+ public static final int TAG_MAX_PASSWORD_ATTEMPTS_SET =
+ SecurityLogTags.SECURITY_MAX_PASSWORD_ATTEMPTS_SET;
+
+ /**
+ * Indicates that an admin has set disabled keyguard features. The log entry contains the
+ * following information about the event encapsulated in an {@link Object} array, accessible via
+ * {@link SecurityEvent#getData()}:
+ * <li> [0] admin package name ({@code String})
+ * <li> [1] admin user ID ({@code Integer})
+ * <li> [2] target user ID ({@code Integer})
+ * <li> [3] disabled keyguard feature mask ({@code Integer}).
+ * @see DevicePolicyManager#setKeyguardDisabledFeatures(ComponentName, int)
+ */
+ public static final int TAG_KEYGUARD_DISABLED_FEATURES_SET =
+ SecurityLogTags.SECURITY_KEYGUARD_DISABLED_FEATURES_SET;
+
+ /**
+ * Indicates that an admin remotely locked the device or profile. The log entry contains the
+ * following information about the event encapsulated in an {@link Object} array, accessible via
+ * {@link SecurityEvent#getData()}:
+ * <li> [0] admin package name ({@code String}),
+ * <li> [1] admin user ID ({@code Integer}).
+ */
+ public static final int TAG_REMOTE_LOCK = SecurityLogTags.SECURITY_REMOTE_LOCK;
+
+ /**
+ * Indicates a failure to wipe device or user data. There is no extra payload in the log event.
+ */
+ public static final int TAG_WIPE_FAILURE = SecurityLogTags.SECURITY_WIPE_FAILED;
+
+ /**
+ * Indicates that an authentication key was generated. The log entry contains the following
+ * information about the event, encapsulated in an {@link Object} array and accessible via
+ * {@link SecurityEvent#getData()}:
+ * <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
+ * <li> [1] alias of the key ({@code String})
+ * <li> [2] requesting process uid ({@code Integer}).
+ */
+ public static final int TAG_KEY_GENERATED =
+ SecurityLogTags.SECURITY_KEY_GENERATED;
+
+ /**
+ * Indicates that a cryptographic key was imported. The log entry contains the following
+ * information about the event, encapsulated in an {@link Object} array and accessible via
+ * {@link SecurityEvent#getData()}:
+ * <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
+ * <li> [1] alias of the key ({@code String})
+ * <li> [2] requesting process uid ({@code Integer}).
+ */
+ public static final int TAG_KEY_IMPORT = SecurityLogTags.SECURITY_KEY_IMPORTED;
+
+ /**
+ * Indicates that a cryptographic key was destroyed. The log entry contains the following
+ * information about the event, encapsulated in an {@link Object} array and accessible via
+ * {@link SecurityEvent#getData()}:
+ * <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
+ * <li> [1] alias of the key ({@code String})
+ * <li> [2] requesting process uid ({@code Integer}).
+ */
+ public static final int TAG_KEY_DESTRUCTION = SecurityLogTags.SECURITY_KEY_DESTROYED;
+
+ /**
+ * Indicates that a new root certificate has been installed into system's trusted credential
+ * storage. The log entry contains the following information about the event, encapsulated in an
+ * {@link Object} array and accessible via {@link SecurityEvent#getData()}:
+ * <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
+ * <li> [1] subject of the certificate ({@code String}).
+ */
+ public static final int TAG_CERT_AUTHORITY_INSTALLED =
+ SecurityLogTags.SECURITY_CERT_AUTHORITY_INSTALLED;
+
+ /**
+ * Indicates that a new oot certificate has been removed from system's trusted credential
+ * storage. The log entry contains the following information about the event, encapsulated in an
+ * {@link Object} array and accessible via {@link SecurityEvent#getData()}:
+ * <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
+ * <li> [1] subject of the certificate ({@code String}).
+ */
+ public static final int TAG_CERT_AUTHORITY_REMOVED =
+ SecurityLogTags.SECURITY_CERT_AUTHORITY_REMOVED;
+
+ /**
+ * Indicates that an admin has set a user restriction. The log entry contains the following
+ * information about the event, encapsulated in an {@link Object} array and accessible via
+ * {@link SecurityEvent#getData()}:
+ * <li> [0] admin package name ({@code String})
+ * <li> [1] admin user ID ({@code Integer})
+ * <li> [2] user restriction ({@code String})
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ */
+ public static final int TAG_USER_RESTRICTION_ADDED =
+ SecurityLogTags.SECURITY_USER_RESTRICTION_ADDED;
+
+ /**
+ * Indicates that an admin has removed a user restriction. The log entry contains the following
+ * information about the event, encapsulated in an {@link Object} array and accessible via
+ * {@link SecurityEvent#getData()}:
+ * <li> [0] admin package name ({@code String})
+ * <li> [1] admin user ID ({@code Integer})
+ * <li> [2] user restriction ({@code String})
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ */
+ public static final int TAG_USER_RESTRICTION_REMOVED =
+ SecurityLogTags.SECURITY_USER_RESTRICTION_REMOVED;
+
+ /**
+ * Event severity level indicating that the event corresponds to normal workflow.
+ */
+ public static final int LEVEL_INFO = 1;
+
+ /**
+ * Event severity level indicating that the event may require admin attention.
+ */
+ public static final int LEVEL_WARNING = 2;
+
+ /**
+ * Event severity level indicating that the event requires urgent admin action.
+ */
+ public static final int LEVEL_ERROR = 3;
+
+ /**
* Returns if security logging is enabled. Log producers should only write new logs if this is
* true. Under the hood this is the logical AND of whether device owner exists and whether
* it enables logging by setting the system property {@link #PROPERTY_LOGGING_ENABLED}.
@@ -198,6 +502,60 @@
return mId;
}
+ /**
+ * Returns severity level for the event.
+ */
+ public @SecurityLogLevel int getLogLevel() {
+ switch (mEvent.getTag()) {
+ case TAG_ADB_SHELL_INTERACTIVE:
+ case TAG_ADB_SHELL_CMD:
+ case TAG_SYNC_RECV_FILE:
+ case TAG_SYNC_SEND_FILE:
+ case TAG_APP_PROCESS_START:
+ case TAG_KEYGUARD_DISMISSED:
+ case TAG_KEYGUARD_SECURED:
+ case TAG_OS_STARTUP:
+ case TAG_OS_SHUTDOWN:
+ case TAG_LOGGING_STARTED:
+ case TAG_LOGGING_STOPPED:
+ case TAG_MEDIA_MOUNT:
+ case TAG_MEDIA_UNMOUNT:
+ case TAG_PASSWORD_EXPIRATION_SET:
+ case TAG_PASSWORD_COMPLEXITY_SET:
+ case TAG_PASSWORD_HISTORY_LENGTH_SET:
+ case TAG_MAX_SCREEN_LOCK_TIMEOUT_SET:
+ case TAG_MAX_PASSWORD_ATTEMPTS_SET:
+ case TAG_USER_RESTRICTION_ADDED:
+ case TAG_USER_RESTRICTION_REMOVED:
+ return LEVEL_INFO;
+ case TAG_CERT_AUTHORITY_REMOVED:
+ return getSuccess() ? LEVEL_INFO : LEVEL_ERROR;
+ case TAG_CERT_AUTHORITY_INSTALLED:
+ case TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT:
+ case TAG_KEY_IMPORT:
+ case TAG_KEY_DESTRUCTION:
+ case TAG_KEY_GENERATED:
+ return getSuccess() ? LEVEL_INFO : LEVEL_WARNING;
+ case TAG_LOG_BUFFER_SIZE_CRITICAL:
+ case TAG_WIPE_FAILURE:
+ return LEVEL_ERROR;
+ default:
+ return LEVEL_INFO;
+ }
+ }
+
+ // Success/failure if present is encoded as an integer in the first (0th) element of data.
+ private boolean getSuccess() {
+ final Object data = getData();
+ if (data == null || !(data instanceof Object[])) {
+ return false;
+ }
+
+ final Object[] array = (Object[]) data;
+ return array.length >= 1 && array[0] instanceof Integer && (Integer) array[0] != 0;
+ }
+
+
@Override
public int describeContents() {
return 0;
@@ -263,8 +621,8 @@
throws IOException;
/**
- * Retrieve all security logs whose timestamp (in nanosceonds) is equal to or greater than the
- * given timestamp. This method will block until either the last log earlier than the given
+ * Retrieve all security logs whose timestamp is equal to or greater than the given timestamp in
+ * nanoseconds. This method will block until either the last log earlier than the given
* timestamp is about to be pruned, or after a 2-hour timeout has passed.
* @hide
*/
diff --git a/core/java/android/app/admin/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags
index 39371c7..be62678 100644
--- a/core/java/android/app/admin/SecurityLogTags.logtags
+++ b/core/java/android/app/admin/SecurityLogTags.logtags
@@ -10,3 +10,28 @@
210006 security_keyguard_dismissed
210007 security_keyguard_dismiss_auth_attempt (success|1),(method_strength|1)
210008 security_keyguard_secured
+
+# Additional event types for NIAP MDFPP 3.1 compliant audit logging.
+
+210009 security_os_startup (boot_state|3),(verity_mode|3)
+210010 security_os_shutdown
+210011 security_logging_started
+210012 security_logging_stopped
+210013 security_media_mounted (path|3),(label|3)
+210014 security_media_unmounted (path|3),(label|3)
+210015 security_log_buffer_size_critical
+210016 security_password_expiration_set (package|3),(admin_user|1),(target_user|1),(timeout|2|3)
+210017 security_password_complexity_set (package|3),(admin_user|1),(target_user|1),(length|1),(quality|1),(num_letters|1),(num_non_letters|1),(num_numeric|1),(num_uppercase|1),(num_lowercase|1),(num_symbols|1)
+210018 security_password_history_length_set (package|3),(admin_user|1),(target_user|1),(length|1)
+210019 security_max_screen_lock_timeout_set (package|3),(admin_user|1),(target_user|1),(timeout|2|3)
+210020 security_max_password_attempts_set (package|3),(admin_user|1),(target_user|1),(num_failures|1)
+210021 security_keyguard_disabled_features_set (package|3),(admin_user|1),(target_user|1),(features|1)
+210022 security_remote_lock (package|3),(admin_user|1),(target_user|1)
+210023 security_wipe_failed (package|3),(admin_user|1)
+210024 security_key_generated (success|1),(key_id|3),(uid|1)
+210025 security_key_imported (success|1),(key_id|3),(uid|1)
+210026 security_key_destroyed (success|1),(key_id|3),(uid|1)
+210027 security_user_restriction_added (package|3),(admin_user|1),(restriction|3)
+210028 security_user_restriction_removed (package|3),(admin_user|1),(restriction|3)
+210029 security_cert_authority_installed (success|1),(subject|3)
+210030 security_cert_authority_removed (success|1),(subject|3)
\ No newline at end of file
diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java
index 232a688..05d3fd9 100644
--- a/core/java/android/app/admin/SystemUpdatePolicy.java
+++ b/core/java/android/app/admin/SystemUpdatePolicy.java
@@ -16,16 +16,27 @@
package android.app.admin;
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.END_TAG;
+import static org.xmlpull.v1.XmlPullParser.TEXT;
+
import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.Log;
+import android.util.Pair;
import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
/**
* A class that represents a local system update policy set by the device owner.
@@ -34,6 +45,7 @@
* @see DevicePolicyManager#getSystemUpdatePolicy
*/
public class SystemUpdatePolicy implements Parcelable {
+ private static final String TAG = "SystemUpdatePolicy";
/** @hide */
@IntDef(prefix = { "TYPE_" }, value = {
@@ -94,20 +106,157 @@
private static final String KEY_POLICY_TYPE = "policy_type";
private static final String KEY_INSTALL_WINDOW_START = "install_window_start";
private static final String KEY_INSTALL_WINDOW_END = "install_window_end";
+ private static final String KEY_FREEZE_TAG = "freeze";
+ private static final String KEY_FREEZE_START = "start";
+ private static final String KEY_FREEZE_END = "end";
+
/**
* The upper boundary of the daily maintenance window: 24 * 60 minutes.
*/
private static final int WINDOW_BOUNDARY = 24 * 60;
+ /**
+ * The maximum length of a single freeze period: 90 days.
+ */
+ static final int FREEZE_PERIOD_MAX_LENGTH = 90;
+
+ /**
+ * The minimum allowed time between two adjacent freeze period (from the end of the first
+ * freeze period to the start of the second freeze period, both exclusive): 60 days.
+ */
+ static final int FREEZE_PERIOD_MIN_SEPARATION = 60;
+
+
+ /**
+ * An exception class that represents various validation errors thrown from
+ * {@link SystemUpdatePolicy#setFreezePeriods} and
+ * {@link DevicePolicyManager#setSystemUpdatePolicy}
+ */
+ public static final class ValidationFailedException extends IllegalArgumentException
+ implements Parcelable {
+
+ /** @hide */
+ @IntDef(prefix = { "ERROR_" }, value = {
+ ERROR_NONE,
+ ERROR_DUPLICATE_OR_OVERLAP,
+ ERROR_NEW_FREEZE_PERIOD_TOO_LONG,
+ ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE,
+ ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG,
+ ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ValidationFailureType {}
+
+ /** @hide */
+ public static final int ERROR_NONE = 0;
+
+ /**
+ * The freeze periods contains duplicates, periods that overlap with each
+ * other or periods whose start and end joins.
+ */
+ public static final int ERROR_DUPLICATE_OR_OVERLAP = 1;
+
+ /**
+ * There exists at least one freeze period whose length exceeds 90 days.
+ */
+ public static final int ERROR_NEW_FREEZE_PERIOD_TOO_LONG = 2;
+
+ /**
+ * There exists some freeze period which starts within 60 days of the preceding period's
+ * end time.
+ */
+ public static final int ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE = 3;
+
+ /**
+ * The device has been in a freeze period and when combining with the new freeze period
+ * to be set, it will result in the total freeze period being longer than 90 days.
+ */
+ public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG = 4;
+
+ /**
+ * The device has been in a freeze period and some new freeze period to be set is less
+ * than 60 days from the end of the last freeze period the device went through.
+ */
+ public static final int ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE = 5;
+
+ @ValidationFailureType
+ private final int mErrorCode;
+
+ private ValidationFailedException(int errorCode, String message) {
+ super(message);
+ mErrorCode = errorCode;
+ }
+
+ /**
+ * Returns the type of validation error associated with this exception.
+ */
+ public @ValidationFailureType int getErrorCode() {
+ return mErrorCode;
+ }
+
+ /** @hide */
+ public static ValidationFailedException duplicateOrOverlapPeriods() {
+ return new ValidationFailedException(ERROR_DUPLICATE_OR_OVERLAP,
+ "Found duplicate or overlapping periods");
+ }
+
+ /** @hide */
+ public static ValidationFailedException freezePeriodTooLong(String message) {
+ return new ValidationFailedException(ERROR_NEW_FREEZE_PERIOD_TOO_LONG, message);
+ }
+
+ /** @hide */
+ public static ValidationFailedException freezePeriodTooClose(String message) {
+ return new ValidationFailedException(ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE, message);
+ }
+
+ /** @hide */
+ public static ValidationFailedException combinedPeriodTooLong(String message) {
+ return new ValidationFailedException(ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG, message);
+ }
+
+ /** @hide */
+ public static ValidationFailedException combinedPeriodTooClose(String message) {
+ return new ValidationFailedException(ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE, message);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mErrorCode);
+ dest.writeString(getMessage());
+ }
+
+ public static final Parcelable.Creator<ValidationFailedException> CREATOR =
+ new Parcelable.Creator<ValidationFailedException>() {
+ @Override
+ public ValidationFailedException createFromParcel(Parcel source) {
+ return new ValidationFailedException(source.readInt(), source.readString());
+ }
+
+ @Override
+ public ValidationFailedException[] newArray(int size) {
+ return new ValidationFailedException[size];
+ }
+
+ };
+ }
+
@SystemUpdatePolicyType
private int mPolicyType;
private int mMaintenanceWindowStart;
private int mMaintenanceWindowEnd;
+ private final ArrayList<FreezeInterval> mFreezePeriods;
private SystemUpdatePolicy() {
mPolicyType = TYPE_UNKNOWN;
+ mFreezePeriods = new ArrayList<>();
}
/**
@@ -206,24 +355,129 @@
}
/**
- * Return if this object represents a valid policy.
+ * Return if this object represents a valid policy with:
+ * 1. Correct type
+ * 2. Valid maintenance window if applicable
+ * 3. Valid freeze periods
* @hide
*/
public boolean isValid() {
- if (mPolicyType == TYPE_INSTALL_AUTOMATIC || mPolicyType == TYPE_POSTPONE) {
+ try {
+ validateType();
+ validateFreezePeriods();
return true;
- } else if (mPolicyType == TYPE_INSTALL_WINDOWED) {
- return mMaintenanceWindowStart >= 0 && mMaintenanceWindowStart < WINDOW_BOUNDARY
- && mMaintenanceWindowEnd >= 0 && mMaintenanceWindowEnd < WINDOW_BOUNDARY;
- } else {
+ } catch (IllegalArgumentException e) {
return false;
}
}
+ /**
+ * Validate the type and maintenance window (if applicable) of this policy object,
+ * throws {@link IllegalArgumentException} if it's invalid.
+ * @hide
+ */
+ public void validateType() {
+ if (mPolicyType == TYPE_INSTALL_AUTOMATIC || mPolicyType == TYPE_POSTPONE) {
+ return;
+ } else if (mPolicyType == TYPE_INSTALL_WINDOWED) {
+ if (!(mMaintenanceWindowStart >= 0 && mMaintenanceWindowStart < WINDOW_BOUNDARY
+ && mMaintenanceWindowEnd >= 0 && mMaintenanceWindowEnd < WINDOW_BOUNDARY)) {
+ throw new IllegalArgumentException("Invalid maintenance window");
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid system update policy type.");
+ }
+ }
+
+ /**
+ * Configure a list of freeze periods on top of the current policy. When the device's clock is
+ * within any of the freeze periods, all incoming system updates including security patches will
+ * be blocked and cannot be installed. When the device is outside the freeze periods, the normal
+ * policy behavior will apply.
+ * <p>
+ * Each freeze period is defined by a starting and finishing date (both inclusive). Since the
+ * freeze period repeats annually, both of these dates are simply represented by integers
+ * counting the number of days since year start, similar to {@link LocalDate#getDayOfYear()}. We
+ * do not consider leap year when handling freeze period so the valid range of the integer is
+ * always [1,365] (see last section for more details on leap year). If the finishing date is
+ * smaller than the starting date, the freeze period is considered to be spanning across
+ * year-end.
+ * <p>
+ * Each individual freeze period is allowed to be at most 90 days long, and adjacent freeze
+ * periods need to be at least 60 days apart. Also, the list of freeze periods should not
+ * contain duplicates or overlap with each other. If any of these conditions is not met, a
+ * {@link ValidationFailedException} will be thrown.
+ * <p>
+ * Handling of leap year: we do not consider leap year when handling freeze period, in
+ * particular,
+ * <ul>
+ * <li>When a freeze period is defined by the day of year, February 29th does not count as one
+ * day, so day 59 is February 28th while day 60 is March 1st.</li>
+ * <li>When applying freeze period behavior to the device, a system clock of February 29th is
+ * treated as if it were February 28th</li>
+ * <li>When calculating the number of days of a freeze period or separation between two freeze
+ * periods, February 29th is also ignored and not counted as one day.</li>
+ * </ul>
+ *
+ * @param freezePeriods the list of freeze periods
+ * @throws ValidationFailedException if the supplied freeze periods do not meet the
+ * requirement set above
+ * @return this instance
+ */
+ public SystemUpdatePolicy setFreezePeriods(List<Pair<Integer, Integer>> freezePeriods) {
+ List<FreezeInterval> newPeriods = freezePeriods.stream().map(
+ p -> new FreezeInterval(p.first, p.second)).collect(Collectors.toList());
+ FreezeInterval.validatePeriods(newPeriods);
+ mFreezePeriods.clear();
+ mFreezePeriods.addAll(newPeriods);
+ return this;
+ }
+
+ /**
+ * Returns the list of freeze periods previously set on this system update policy object.
+ *
+ * @return the list of freeze periods, or an empty list if none was set.
+ */
+ public List<Pair<Integer, Integer>> getFreezePeriods() {
+ List<Pair<Integer, Integer>> result = new ArrayList<>(mFreezePeriods.size());
+ for (FreezeInterval interval : mFreezePeriods) {
+ result.add(new Pair<>(interval.mStartDay, interval.mEndDay));
+ }
+ return result;
+ }
+
+ /**
+ * Returns the real calendar dates of the current freeze period, or null if the device
+ * is not in a freeze period at the moment.
+ * @hide
+ */
+ public Pair<LocalDate, LocalDate> getCurrentFreezePeriod(LocalDate now) {
+ for (FreezeInterval interval : mFreezePeriods) {
+ if (interval.contains(now)) {
+ return interval.toCurrentOrFutureRealDates(now);
+ }
+ }
+ return null;
+ }
+
+ /** @hide */
+ public void validateFreezePeriods() {
+ FreezeInterval.validatePeriods(mFreezePeriods);
+ }
+
+ /** @hide */
+ public void validateAgainstPreviousFreezePeriod(LocalDate prevPeriodStart,
+ LocalDate prevPeriodEnd, LocalDate now) {
+ FreezeInterval.validateAgainstPreviousFreezePeriod(mFreezePeriods, prevPeriodStart,
+ prevPeriodEnd, now);
+ }
+
@Override
public String toString() {
- return String.format("SystemUpdatePolicy (type: %d, windowStart: %d, windowEnd: %d)",
- mPolicyType, mMaintenanceWindowStart, mMaintenanceWindowEnd);
+ return String.format("SystemUpdatePolicy (type: %d, windowStart: %d, windowEnd: %d, "
+ + "freezes: [%s])",
+ mPolicyType, mMaintenanceWindowStart, mMaintenanceWindowEnd,
+ mFreezePeriods.stream().map(n -> n.toString()).collect(Collectors.joining(",")));
}
@Override
@@ -236,6 +490,13 @@
dest.writeInt(mPolicyType);
dest.writeInt(mMaintenanceWindowStart);
dest.writeInt(mMaintenanceWindowEnd);
+ int freezeCount = mFreezePeriods.size();
+ dest.writeInt(freezeCount);
+ for (int i = 0; i < freezeCount; i++) {
+ FreezeInterval interval = mFreezePeriods.get(i);
+ dest.writeInt(interval.mStartDay);
+ dest.writeInt(interval.mEndDay);
+ }
}
public static final Parcelable.Creator<SystemUpdatePolicy> CREATOR =
@@ -247,6 +508,12 @@
policy.mPolicyType = source.readInt();
policy.mMaintenanceWindowStart = source.readInt();
policy.mMaintenanceWindowEnd = source.readInt();
+ int freezeCount = source.readInt();
+ policy.mFreezePeriods.ensureCapacity(freezeCount);
+ for (int i = 0; i < freezeCount; i++) {
+ policy.mFreezePeriods.add(
+ new FreezeInterval(source.readInt(), source.readInt()));
+ }
return policy;
}
@@ -256,8 +523,10 @@
}
};
-
/**
+ * Restore a previously saved SystemUpdatePolicy from XML. No need to validate
+ * the reconstructed policy since the XML is supposed to be created by the
+ * system server from a validated policy object previously.
* @hide
*/
public static SystemUpdatePolicy restoreFromXml(XmlPullParser parser) {
@@ -275,10 +544,26 @@
if (value != null) {
policy.mMaintenanceWindowEnd = Integer.parseInt(value);
}
+
+ int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != END_DOCUMENT
+ && (type != END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == END_TAG || type == TEXT) {
+ continue;
+ }
+ if (!parser.getName().equals(KEY_FREEZE_TAG)) {
+ continue;
+ }
+ policy.mFreezePeriods.add(new FreezeInterval(
+ Integer.parseInt(parser.getAttributeValue(null, KEY_FREEZE_START)),
+ Integer.parseInt(parser.getAttributeValue(null, KEY_FREEZE_END))));
+ }
return policy;
}
- } catch (NumberFormatException e) {
+ } catch (NumberFormatException | XmlPullParserException | IOException e) {
// Fail through
+ Log.w(TAG, "Load xml failed", e);
}
return null;
}
@@ -290,6 +575,13 @@
out.attribute(null, KEY_POLICY_TYPE, Integer.toString(mPolicyType));
out.attribute(null, KEY_INSTALL_WINDOW_START, Integer.toString(mMaintenanceWindowStart));
out.attribute(null, KEY_INSTALL_WINDOW_END, Integer.toString(mMaintenanceWindowEnd));
+ for (int i = 0; i < mFreezePeriods.size(); i++) {
+ FreezeInterval interval = mFreezePeriods.get(i);
+ out.startTag(null, KEY_FREEZE_TAG);
+ out.attribute(null, KEY_FREEZE_START, Integer.toString(interval.mStartDay));
+ out.attribute(null, KEY_FREEZE_END, Integer.toString(interval.mEndDay));
+ out.endTag(null, KEY_FREEZE_TAG);
+ }
}
}
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index cba9dcc..a1ad825c 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -256,6 +256,14 @@
public static final int FLAG_IS_PREFETCH = 1 << 2;
/**
+ * This job needs to be exempted from the app standby throttling. Only the system (UID 1000)
+ * can set it. Jobs with a time constrant must not have it.
+ *
+ * @hide
+ */
+ public static final int FLAG_EXEMPT_FROM_APP_STANDBY = 1 << 3;
+
+ /**
* @hide
*/
public static final int CONSTRAINT_FLAG_CHARGING = 1 << 0;
@@ -355,6 +363,13 @@
return flags;
}
+ /** @hide */
+ public boolean isExemptedFromAppStandby() {
+ return ((flags & FLAG_EXEMPT_FROM_APP_STANDBY) != 0)
+ && !hasEarlyConstraint()
+ && !hasLateConstraint();
+ }
+
/**
* Whether this job requires that the device be charging (or be a non-battery-powered
* device connected to permanent power, such as Android TV devices).
diff --git a/core/java/android/app/servertransaction/PendingTransactionActions.java b/core/java/android/app/servertransaction/PendingTransactionActions.java
index 8304c1c..073d28c 100644
--- a/core/java/android/app/servertransaction/PendingTransactionActions.java
+++ b/core/java/android/app/servertransaction/PendingTransactionActions.java
@@ -134,7 +134,7 @@
Bundle.dumpStats(pw, mPersistentState);
if (ex instanceof TransactionTooLargeException
- && mActivity.loadedApk.getTargetSdkVersion() < Build.VERSION_CODES.N) {
+ && mActivity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex);
return;
}
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index 5808f8b..126deef 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -146,11 +146,6 @@
*/
public static final String HINT_PARTIAL = "partial";
/**
- * A hint representing that this item is the max value possible for the slice containing this.
- * Used to indicate the maximum integer value for a {@link #SUBTYPE_SLIDER}.
- */
- public static final String HINT_MAX = "max";
- /**
* A hint representing that this item should be used to indicate that there's more
* content associated with this slice.
*/
@@ -168,6 +163,16 @@
*/
public static final String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE";
/**
+ * Key to retrieve an extra added to an intent when the value of a slider is changed.
+ * @deprecated remove once support lib is update to use EXTRA_RANGE_VALUE instead
+ */
+ @Deprecated
+ public static final String EXTRA_SLIDER_VALUE = "android.app.slice.extra.SLIDER_VALUE";
+ /**
+ * Key to retrieve an extra added to an intent when the value of an input range is changed.
+ */
+ public static final String EXTRA_RANGE_VALUE = "android.app.slice.extra.RANGE_VALUE";
+ /**
* Subtype to indicate that this is a message as part of a communication
* sequence in this slice.
*/
@@ -181,10 +186,24 @@
*/
public static final String SUBTYPE_COLOR = "color";
/**
- * Subtype to tag an item represents a slider.
+ * Subtype to tag an item as representing a slider.
+ * @deprecated remove once support lib is update to use SUBTYPE_RANGE instead
*/
+ @Deprecated
public static final String SUBTYPE_SLIDER = "slider";
/**
+ * Subtype to tag an item as representing a range.
+ */
+ public static final String SUBTYPE_RANGE = "range";
+ /**
+ * Subtype to tag an item as representing the max int value for a {@link #SUBTYPE_RANGE}.
+ */
+ public static final String SUBTYPE_MAX = "max";
+ /**
+ * Subtype to tag an item as representing the current int value for a {@link #SUBTYPE_RANGE}.
+ */
+ public static final String SUBTYPE_VALUE = "value";
+ /**
* Subtype to indicate that this content has a toggle action associated with it. To indicate
* that the toggle is on, use {@link #HINT_SELECTED}. When the toggle state changes, the
* intent associated with it will be sent along with an extra {@link #EXTRA_TOGGLE_STATE}
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 2fa9d8e..e5f3eae 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -314,6 +314,59 @@
}
/**
+ * Turns a slice intent into a slice uri. Expects an explicit intent. If there is no
+ * {@link android.content.ContentProvider} associated with the given intent this will throw
+ * {@link IllegalArgumentException}.
+ *
+ * @param intent The intent associated with a slice.
+ * @return The Slice Uri provided by the app or null if none is given.
+ * @see Slice
+ * @see SliceProvider#onMapIntentToUri(Intent)
+ * @see Intent
+ */
+ public @Nullable Uri mapIntentToUri(@NonNull Intent intent) {
+ Preconditions.checkNotNull(intent, "intent");
+ Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null,
+ "Slice intent must be explicit %s", intent);
+ ContentResolver resolver = mContext.getContentResolver();
+
+ // Check if the intent has data for the slice uri on it and use that
+ final Uri intentData = intent.getData();
+ if (intentData != null && SliceProvider.SLICE_TYPE.equals(resolver.getType(intentData))) {
+ return intentData;
+ }
+ // Otherwise ask the app
+ List<ResolveInfo> providers =
+ mContext.getPackageManager().queryIntentContentProviders(intent, 0);
+ if (providers == null || providers.isEmpty()) {
+ throw new IllegalArgumentException("Unable to resolve intent " + intent);
+ }
+ String authority = providers.get(0).providerInfo.authority;
+ Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(authority).build();
+ IContentProvider provider = resolver.acquireProvider(uri);
+ if (provider == null) {
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+ try {
+ Bundle extras = new Bundle();
+ extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
+ final Bundle res = provider.call(mContext.getPackageName(),
+ SliceProvider.METHOD_MAP_ONLY_INTENT, null, extras);
+ if (res == null) {
+ return null;
+ }
+ return res.getParcelable(SliceProvider.EXTRA_SLICE);
+ } catch (RemoteException e) {
+ // Arbitrary and not worth documenting, as Activity
+ // Manager will kill this process shortly anyway.
+ return null;
+ } finally {
+ resolver.releaseProvider(provider);
+ }
+ }
+
+ /**
* Turns a slice intent into slice content. Expects an explicit intent. If there is no
* {@link android.content.ContentProvider} associated with the given intent this will throw
* {@link IllegalArgumentException}.
@@ -329,7 +382,7 @@
@NonNull List<SliceSpec> supportedSpecs) {
Preconditions.checkNotNull(intent, "intent");
Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null,
- "Slice intent must be explicit " + intent);
+ "Slice intent must be explicit %s", intent);
ContentResolver resolver = mContext.getContentResolver();
// Check if the intent has data for the slice uri on it and use that
@@ -340,7 +393,7 @@
// Otherwise ask the app
List<ResolveInfo> providers =
mContext.getPackageManager().queryIntentContentProviders(intent, 0);
- if (providers == null) {
+ if (providers == null || providers.isEmpty()) {
throw new IllegalArgumentException("Unable to resolve intent " + intent);
}
String authority = providers.get(0).providerInfo.authority;
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index 00e8cca..af43032 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -114,6 +114,10 @@
/**
* @hide
*/
+ public static final String METHOD_MAP_ONLY_INTENT = "map_only";
+ /**
+ * @hide
+ */
public static final String METHOD_PIN = "pin";
/**
* @hide
@@ -147,6 +151,14 @@
* @hide
*/
public static final String EXTRA_OVERRIDE_PKG = "override_pkg";
+ /**
+ * @hide
+ */
+ public static final String EXTRA_OVERRIDE_UID = "override_uid";
+ /**
+ * @hide
+ */
+ public static final String EXTRA_OVERRIDE_PID = "override_pid";
private static final boolean DEBUG = false;
@@ -302,13 +314,20 @@
List<SliceSpec> supportedSpecs = extras.getParcelableArrayList(EXTRA_SUPPORTED_SPECS);
String callingPackage = getCallingPackage();
+ int callingUid = Binder.getCallingUid();
+ int callingPid = Binder.getCallingPid();
if (extras.containsKey(EXTRA_OVERRIDE_PKG)) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Only the system can override calling pkg");
}
+ // This is safe because we would grant SYSTEM_UID access to all slices
+ // and want to allow it to bind slices as if it were a less privileged app
+ // to check their permission levels.
callingPackage = extras.getString(EXTRA_OVERRIDE_PKG);
+ callingUid = extras.getInt(EXTRA_OVERRIDE_UID);
+ callingPid = extras.getInt(EXTRA_OVERRIDE_PID);
}
- Slice s = handleBindSlice(uri, supportedSpecs, callingPackage);
+ Slice s = handleBindSlice(uri, supportedSpecs, callingPackage, callingUid, callingPid);
Bundle b = new Bundle();
b.putParcelable(EXTRA_SLICE, s);
return b;
@@ -319,12 +338,20 @@
List<SliceSpec> supportedSpecs = extras.getParcelableArrayList(EXTRA_SUPPORTED_SPECS);
Bundle b = new Bundle();
if (uri != null) {
- Slice s = handleBindSlice(uri, supportedSpecs, getCallingPackage());
+ Slice s = handleBindSlice(uri, supportedSpecs, getCallingPackage(),
+ Binder.getCallingUid(), Binder.getCallingPid());
b.putParcelable(EXTRA_SLICE, s);
} else {
b.putParcelable(EXTRA_SLICE, null);
}
return b;
+ } else if (method.equals(METHOD_MAP_ONLY_INTENT)) {
+ Intent intent = extras.getParcelable(EXTRA_INTENT);
+ if (intent == null) return null;
+ Uri uri = onMapIntentToUri(intent);
+ Bundle b = new Bundle();
+ b.putParcelable(EXTRA_SLICE, uri);
+ return b;
} else if (method.equals(METHOD_PIN)) {
Uri uri = getUriWithoutUserId(extras.getParcelable(EXTRA_BIND_URI));
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
@@ -401,15 +428,15 @@
}
private Slice handleBindSlice(Uri sliceUri, List<SliceSpec> supportedSpecs,
- String callingPkg) {
+ String callingPkg, int callingUid, int callingPid) {
// This can be removed once Slice#bindSlice is removed and everyone is using
// SliceManager#bindSlice.
String pkg = callingPkg != null ? callingPkg
- : getContext().getPackageManager().getNameForUid(Binder.getCallingUid());
- if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.myUid())) {
+ : getContext().getPackageManager().getNameForUid(callingUid);
+ if (!UserHandle.isSameApp(callingUid, Process.myUid())) {
try {
mSliceManager.enforceSlicePermission(sliceUri, pkg,
- Binder.getCallingPid(), Binder.getCallingUid());
+ callingPid, callingUid);
} catch (SecurityException e) {
return createPermissionSlice(getContext(), sliceUri, pkg);
}
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index bd978e3..5d6a989 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -146,6 +146,14 @@
* allowed to do work even if they're idle or in a low bucket.
*/
public abstract void onParoleStateChanged(boolean isParoleOn);
+
+ /**
+ * Optional callback to inform the listener that the app has transitioned into
+ * an active state due to user interaction.
+ */
+ public void onUserInteractionStarted(String packageName, @UserIdInt int userId) {
+ // No-op by default
+ }
}
/** Backup/Restore API */
@@ -212,4 +220,17 @@
* indicated here before by a call to {@link #setLastJobRunTime(String, int, long)}.
*/
public abstract long getTimeSinceLastJobRun(String packageName, @UserIdInt int userId);
+
+ /**
+ * Report a few data points about an app's job state at the current time.
+ *
+ * @param packageName the app whose job state is being described
+ * @param userId which user the app is associated with
+ * @param numDeferredJobs the number of pending jobs that were deferred
+ * due to bucketing policy
+ * @param timeSinceLastJobRun number of milliseconds since the last time one of
+ * this app's jobs was executed
+ */
+ public abstract void reportAppJobState(String packageName, @UserIdInt int userId,
+ int numDeferredJobs, long timeSinceLastJobRun);
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 9f11d6e..bc7823b 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -438,7 +438,7 @@
* Intent used to broadcast the change in connection state of the local
* Bluetooth adapter to a profile of the remote device. When the adapter is
* not connected to any profiles of any remote devices and it attempts a
- * connection to a profile this intent will sent. Once connected, this intent
+ * connection to a profile this intent will be sent. Once connected, this intent
* will not be sent for any more connection attempts to any profiles of any
* remote device. When the adapter disconnects from the last profile its
* connected to of any remote device, this intent will be sent.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5177e10..f2eb4a0 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4170,6 +4170,16 @@
public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
/**
+ * Use with {@link #getSystemService} to retrieve a
+ * {@link android.se.omapi.ISecureElementService}
+ * for accessing the SecureElementService.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String SECURE_ELEMENT_SERVICE = "secure_element";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index acbdf14..9b62f19 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -50,6 +50,7 @@
import android.provider.DocumentsProvider;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
@@ -1553,16 +1554,6 @@
public static final String ACTION_INSTALL_FAILURE = "android.intent.action.INSTALL_FAILURE";
/**
- * @hide
- * @removed
- * @deprecated Do not use. This will go away.
- * Replace with {@link #ACTION_INSTALL_INSTANT_APP_PACKAGE}.
- */
- @SystemApi
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_INSTALL_EPHEMERAL_PACKAGE
- = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
- /**
* Activity Action: Launch instant application installer.
* <p class="note">
* This is a protected intent that can only be sent by the system.
@@ -1576,16 +1567,6 @@
= "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
/**
- * @hide
- * @removed
- * @deprecated Do not use. This will go away.
- * Replace with {@link #ACTION_RESOLVE_INSTANT_APP_PACKAGE}.
- */
- @SystemApi
- @SdkConstant(SdkConstantType.SERVICE_ACTION)
- public static final String ACTION_RESOLVE_EPHEMERAL_PACKAGE
- = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
- /**
* Service Action: Resolve instant application.
* <p>
* The system will have a persistent connection to this service.
@@ -1600,16 +1581,6 @@
= "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
/**
- * @hide
- * @removed
- * @deprecated Do not use. This will go away.
- * Replace with {@link #ACTION_INSTANT_APP_RESOLVER_SETTINGS}.
- */
- @SystemApi
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_EPHEMERAL_RESOLVER_SETTINGS
- = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
- /**
* Activity Action: Launch instant app settings.
*
* <p class="note">
@@ -4443,45 +4414,109 @@
/**
* A {@link IntentSender} to start after ephemeral installation success.
+ * @deprecated Use {@link #EXTRA_INSTANT_APP_SUCCESS).
+ * @removed
* @hide
*/
+ @Deprecated
public static final String EXTRA_EPHEMERAL_SUCCESS = "android.intent.extra.EPHEMERAL_SUCCESS";
/**
- * A {@link IntentSender} to start after ephemeral installation failure.
+ * A {@link IntentSender} to start after instant app installation success.
* @hide
*/
+ @SystemApi
+ public static final String EXTRA_INSTANT_APP_SUCCESS =
+ "android.intent.extra.INSTANT_APP_SUCCESS";
+
+ /**
+ * A {@link IntentSender} to start after ephemeral installation failure.
+ * @deprecated Use {@link #EXTRA_INSTANT_APP_FAILURE).
+ * @removed
+ * @hide
+ */
+ @Deprecated
public static final String EXTRA_EPHEMERAL_FAILURE = "android.intent.extra.EPHEMERAL_FAILURE";
/**
- * The host name that triggered an ephemeral resolution.
+ * A {@link IntentSender} to start after instant app installation failure.
* @hide
*/
+ @SystemApi
+ public static final String EXTRA_INSTANT_APP_FAILURE =
+ "android.intent.extra.INSTANT_APP_FAILURE";
+
+ /**
+ * The host name that triggered an ephemeral resolution.
+ * @deprecated Use {@link #EXTRA_INSTANT_APP_HOSTNAME).
+ * @removed
+ * @hide
+ */
+ @Deprecated
public static final String EXTRA_EPHEMERAL_HOSTNAME = "android.intent.extra.EPHEMERAL_HOSTNAME";
/**
- * An opaque token to track ephemeral resolution.
+ * The host name that triggered an instant app resolution.
* @hide
*/
+ @SystemApi
+ public static final String EXTRA_INSTANT_APP_HOSTNAME =
+ "android.intent.extra.INSTANT_APP_HOSTNAME";
+
+ /**
+ * An opaque token to track ephemeral resolution.
+ * @deprecated Use {@link #EXTRA_INSTANT_APP_TOKEN).
+ * @removed
+ * @hide
+ */
+ @Deprecated
public static final String EXTRA_EPHEMERAL_TOKEN = "android.intent.extra.EPHEMERAL_TOKEN";
/**
+ * An opaque token to track instant app resolution.
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_INSTANT_APP_TOKEN =
+ "android.intent.extra.INSTANT_APP_TOKEN";
+
+ /**
* The action that triggered an instant application resolution.
* @hide
*/
+ @SystemApi
public static final String EXTRA_INSTANT_APP_ACTION = "android.intent.extra.INSTANT_APP_ACTION";
/**
- * A {@link Bundle} of metadata that describes the instanta application that needs to be
+ * An array of {@link Bundle}s containing details about resolved instant apps..
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_INSTANT_APP_BUNDLES =
+ "android.intent.extra.INSTANT_APP_BUNDLES";
+
+ /**
+ * A {@link Bundle} of metadata that describes the instant application that needs to be
* installed. This data is populated from the response to
* {@link android.content.pm.InstantAppResolveInfo#getExtras()} as provided by the registered
* instant application resolver.
* @hide
*/
+ @SystemApi
public static final String EXTRA_INSTANT_APP_EXTRAS =
"android.intent.extra.INSTANT_APP_EXTRAS";
/**
+ * A boolean value indicating that the instant app resolver was unable to state with certainty
+ * that it did or did not have an app for the sanitized {@link Intent} defined at
+ * {@link #EXTRA_INTENT}.
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_UNKNOWN_INSTANT_APP =
+ "android.intent.extra.UNKNOWN_INSTANT_APP";
+
+ /**
* The version code of the app to install components from.
* @deprecated Use {@link #EXTRA_LONG_VERSION_CODE).
* @hide
@@ -4493,12 +4528,14 @@
* The version code of the app to install components from.
* @hide
*/
+ @SystemApi
public static final String EXTRA_LONG_VERSION_CODE = "android.intent.extra.LONG_VERSION_CODE";
/**
- * The app that triggered the ephemeral installation.
+ * The app that triggered the instant app installation.
* @hide
*/
+ @SystemApi
public static final String EXTRA_CALLING_PACKAGE
= "android.intent.extra.CALLING_PACKAGE";
@@ -4507,6 +4544,7 @@
* installer may use.
* @hide
*/
+ @SystemApi
public static final String EXTRA_VERIFICATION_BUNDLE
= "android.intent.extra.VERIFICATION_BUNDLE";
@@ -5029,6 +5067,7 @@
FLAG_GRANT_PREFIX_URI_PERMISSION,
FLAG_DEBUG_TRIAGED_MISSING,
FLAG_IGNORE_EPHEMERAL,
+ FLAG_ACTIVITY_MATCH_EXTERNAL,
FLAG_ACTIVITY_NO_HISTORY,
FLAG_ACTIVITY_SINGLE_TOP,
FLAG_ACTIVITY_NEW_TASK,
@@ -5072,6 +5111,7 @@
FLAG_INCLUDE_STOPPED_PACKAGES,
FLAG_DEBUG_TRIAGED_MISSING,
FLAG_IGNORE_EPHEMERAL,
+ FLAG_ACTIVITY_MATCH_EXTERNAL,
FLAG_ACTIVITY_NO_HISTORY,
FLAG_ACTIVITY_SINGLE_TOP,
FLAG_ACTIVITY_NEW_TASK,
@@ -5475,6 +5515,14 @@
*/
public static final int FLAG_ACTIVITY_LAUNCH_ADJACENT = 0x00001000;
+
+ /**
+ * If set, resolution of this intent may take place via an instant app not
+ * yet on the device if there does not yet exist an app on device to
+ * resolve it.
+ */
+ public static final int FLAG_ACTIVITY_MATCH_EXTERNAL = 0x00000800;
+
/**
* If set, when sending a broadcast only registered receivers will be
* called -- no BroadcastReceiver components will be launched.
@@ -7028,7 +7076,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if none was found.
*
* @deprecated
@@ -7046,7 +7094,7 @@
* @param defaultValue the value to be returned if no value of the desired
* type is stored with the given name.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or the default value if none was found.
*
* @see #putExtra(String, boolean)
@@ -7063,7 +7111,7 @@
* @param defaultValue the value to be returned if no value of the desired
* type is stored with the given name.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or the default value if none was found.
*
* @see #putExtra(String, byte)
@@ -7080,7 +7128,7 @@
* @param defaultValue the value to be returned if no value of the desired
* type is stored with the given name.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or the default value if none was found.
*
* @see #putExtra(String, short)
@@ -7097,7 +7145,7 @@
* @param defaultValue the value to be returned if no value of the desired
* type is stored with the given name.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or the default value if none was found.
*
* @see #putExtra(String, char)
@@ -7114,7 +7162,7 @@
* @param defaultValue the value to be returned if no value of the desired
* type is stored with the given name.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or the default value if none was found.
*
* @see #putExtra(String, int)
@@ -7131,7 +7179,7 @@
* @param defaultValue the value to be returned if no value of the desired
* type is stored with the given name.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or the default value if none was found.
*
* @see #putExtra(String, long)
@@ -7148,7 +7196,7 @@
* @param defaultValue the value to be returned if no value of the desired
* type is stored with the given name.
*
- * @return the value of an item that previously added with putExtra(),
+ * @return the value of an item previously added with putExtra(),
* or the default value if no such item is present
*
* @see #putExtra(String, float)
@@ -7165,7 +7213,7 @@
* @param defaultValue the value to be returned if no value of the desired
* type is stored with the given name.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or the default value if none was found.
*
* @see #putExtra(String, double)
@@ -7180,7 +7228,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no String value was found.
*
* @see #putExtra(String, String)
@@ -7194,7 +7242,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no CharSequence value was found.
*
* @see #putExtra(String, CharSequence)
@@ -7208,7 +7256,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no Parcelable value was found.
*
* @see #putExtra(String, Parcelable)
@@ -7222,7 +7270,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no Parcelable[] value was found.
*
* @see #putExtra(String, Parcelable[])
@@ -7236,8 +7284,9 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
- * or null if no ArrayList<Parcelable> value was found.
+ * @return the value of an item previously added with
+ * putParcelableArrayListExtra(), or null if no
+ * ArrayList<Parcelable> value was found.
*
* @see #putParcelableArrayListExtra(String, ArrayList)
*/
@@ -7250,7 +7299,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no Serializable value was found.
*
* @see #putExtra(String, Serializable)
@@ -7264,8 +7313,9 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
- * or null if no ArrayList<Integer> value was found.
+ * @return the value of an item previously added with
+ * putIntegerArrayListExtra(), or null if no
+ * ArrayList<Integer> value was found.
*
* @see #putIntegerArrayListExtra(String, ArrayList)
*/
@@ -7278,8 +7328,9 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
- * or null if no ArrayList<String> value was found.
+ * @return the value of an item previously added with
+ * putStringArrayListExtra(), or null if no
+ * ArrayList<String> value was found.
*
* @see #putStringArrayListExtra(String, ArrayList)
*/
@@ -7292,8 +7343,9 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
- * or null if no ArrayList<CharSequence> value was found.
+ * @return the value of an item previously added with
+ * putCharSequenceArrayListExtra, or null if no
+ * ArrayList<CharSequence> value was found.
*
* @see #putCharSequenceArrayListExtra(String, ArrayList)
*/
@@ -7306,7 +7358,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no boolean array value was found.
*
* @see #putExtra(String, boolean[])
@@ -7320,7 +7372,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no byte array value was found.
*
* @see #putExtra(String, byte[])
@@ -7334,7 +7386,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no short array value was found.
*
* @see #putExtra(String, short[])
@@ -7348,7 +7400,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no char array value was found.
*
* @see #putExtra(String, char[])
@@ -7362,7 +7414,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no int array value was found.
*
* @see #putExtra(String, int[])
@@ -7376,7 +7428,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no long array value was found.
*
* @see #putExtra(String, long[])
@@ -7390,7 +7442,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no float array value was found.
*
* @see #putExtra(String, float[])
@@ -7404,7 +7456,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no double array value was found.
*
* @see #putExtra(String, double[])
@@ -7418,7 +7470,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no String array value was found.
*
* @see #putExtra(String, String[])
@@ -7432,7 +7484,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no CharSequence array value was found.
*
* @see #putExtra(String, CharSequence[])
@@ -7446,7 +7498,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no Bundle value was found.
*
* @see #putExtra(String, Bundle)
@@ -7460,7 +7512,7 @@
*
* @param name The name of the desired item.
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or null if no IBinder value was found.
*
* @see #putExtra(String, IBinder)
@@ -7480,7 +7532,7 @@
* @param defaultValue The default value to return in case no item is
* associated with the key 'name'
*
- * @return the value of an item that previously added with putExtra()
+ * @return the value of an item previously added with putExtra(),
* or defaultValue if none was found.
*
* @see #putExtra
@@ -9451,7 +9503,7 @@
proto.write(IntentProto.PACKAGE, mPackage);
}
if (comp && mComponent != null) {
- proto.write(IntentProto.COMPONENT, mComponent.flattenToShortString());
+ mComponent.writeToProto(proto, IntentProto.COMPONENT);
}
if (mSourceBounds != null) {
proto.write(IntentProto.SOURCE_BOUNDS, mSourceBounds.toShortString());
@@ -10024,6 +10076,25 @@
}
}
+ /** @hide */
+ public boolean hasWebURI() {
+ if (getData() == null) {
+ return false;
+ }
+ final String scheme = getScheme();
+ if (TextUtils.isEmpty(scheme)) {
+ return false;
+ }
+ return scheme.equals(IntentFilter.SCHEME_HTTP) || scheme.equals(IntentFilter.SCHEME_HTTPS);
+ }
+
+ /** @hide */
+ public boolean isBrowsableWebIntent() {
+ return ACTION_VIEW.equals(mAction)
+ && hasCategory(CATEGORY_BROWSABLE)
+ && hasWebURI();
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/content/pm/AndroidTestBaseUpdater.java b/core/java/android/content/pm/AndroidTestBaseUpdater.java
new file mode 100644
index 0000000..2aaac02
--- /dev/null
+++ b/core/java/android/content/pm/AndroidTestBaseUpdater.java
@@ -0,0 +1,54 @@
+/*
+ * 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.content.pm;
+
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
+
+import android.content.pm.PackageParser.Package;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Updates a package to ensure that if it targets < P that the android.test.base library is
+ * included by default.
+ *
+ * <p>This is separated out so that it can be conditionally included at build time depending on
+ * whether android.test.base is on the bootclasspath or not. In order to include this at
+ * build time, and remove android.test.base from the bootclasspath pass
+ * REMOVE_ATB_FROM_BCP=true on the build command line, otherwise this class will not be included
+ * and the
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class AndroidTestBaseUpdater extends PackageSharedLibraryUpdater {
+
+ @Override
+ public void updatePackage(Package pkg) {
+ // Packages targeted at <= O_MR1 expect the classes in the android.test.base library
+ // to be accessible so this maintains backward compatibility by adding the
+ // android.test.base library to those packages.
+ if (apkTargetsApiLevelLessThanOrEqualToOMR1(pkg)) {
+ prefixRequiredLibrary(pkg, ANDROID_TEST_BASE);
+ } else {
+ // If a package already depends on android.test.runner then add a dependency on
+ // android.test.base because android.test.runner depends on classes from the
+ // android.test.base library.
+ prefixImplicitDependency(pkg, ANDROID_TEST_RUNNER, ANDROID_TEST_BASE);
+ }
+ }
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 746a090..db1630b 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -602,6 +602,13 @@
*/
public static final int PRIVATE_FLAG_VENDOR = 1 << 18;
+ /**
+ * Value for {@linl #privateFlags}: whether this app is pre-installed on the
+ * product partition of the system image.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_PRODUCT = 1 << 19;
+
/** @hide */
@IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -619,6 +626,7 @@
PRIVATE_FLAG_OEM,
PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE,
PRIVATE_FLAG_PRIVILEGED,
+ PRIVATE_FLAG_PRODUCT,
PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
PRIVATE_FLAG_STATIC_SHARED_LIBRARY,
PRIVATE_FLAG_VENDOR,
@@ -950,6 +958,7 @@
* Version of the sandbox the application wants to run in.
* @hide
*/
+ @SystemApi
public int targetSandboxVersion;
/**
@@ -1647,7 +1656,11 @@
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
}
- /** @hide */
+ /**
+ * True if the application is installed as an instant app.
+ * @hide
+ */
+ @SystemApi
public boolean isInstantApp() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
}
@@ -1699,6 +1712,11 @@
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
+ /** @hide */
+ public boolean isProduct() {
+ return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
+ }
+
/**
* Returns whether or not this application was installed as a virtual preload.
*/
diff --git a/core/java/android/content/pm/AuxiliaryResolveInfo.java b/core/java/android/content/pm/AuxiliaryResolveInfo.java
index 6bdcefb..202df50 100644
--- a/core/java/android/content/pm/AuxiliaryResolveInfo.java
+++ b/core/java/android/content/pm/AuxiliaryResolveInfo.java
@@ -21,6 +21,10 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Bundle;
+
+import java.util.Collections;
+import java.util.List;
/**
* Auxiliary application resolution response.
@@ -31,56 +35,95 @@
* hasn't been installed.
* @hide
*/
-public final class AuxiliaryResolveInfo extends IntentFilter {
- /** Resolved information returned from the external instant resolver */
- public final InstantAppResolveInfo resolveInfo;
- /** The resolved package. Copied from {@link #resolveInfo}. */
- public final String packageName;
+public final class AuxiliaryResolveInfo {
/** The activity to launch if there's an installation failure. */
public final ComponentName installFailureActivity;
- /** The resolve split. Copied from the matched filter in {@link #resolveInfo}. */
- public final String splitName;
/** Whether or not instant resolution needs the second phase */
public final boolean needsPhaseTwo;
/** Opaque token to track the instant application resolution */
public final String token;
- /** The version code of the package */
- public final long versionCode;
/** An intent to start upon failure to install */
public final Intent failureIntent;
+ /** The matching filters for this resolve info. */
+ public final List<AuxiliaryFilter> filters;
/** Create a response for installing an instant application. */
- public AuxiliaryResolveInfo(@NonNull InstantAppResolveInfo resolveInfo,
- @NonNull IntentFilter orig,
- @Nullable String splitName,
- @NonNull String token,
+ public AuxiliaryResolveInfo(@NonNull String token,
boolean needsPhase2,
- @Nullable Intent failureIntent) {
- super(orig);
- this.resolveInfo = resolveInfo;
- this.packageName = resolveInfo.getPackageName();
- this.splitName = splitName;
+ @Nullable Intent failureIntent,
+ @Nullable List<AuxiliaryFilter> filters) {
this.token = token;
this.needsPhaseTwo = needsPhase2;
- this.versionCode = resolveInfo.getVersionCode();
this.failureIntent = failureIntent;
+ this.filters = filters;
this.installFailureActivity = null;
}
/** Create a response for installing a split on demand. */
- public AuxiliaryResolveInfo(@NonNull String packageName,
- @Nullable String splitName,
- @Nullable ComponentName failureActivity,
- long versionCode,
- @Nullable Intent failureIntent) {
+ public AuxiliaryResolveInfo(@Nullable ComponentName failureActivity,
+ @Nullable Intent failureIntent,
+ @Nullable List<AuxiliaryFilter> filters) {
super();
- this.packageName = packageName;
this.installFailureActivity = failureActivity;
- this.splitName = splitName;
- this.versionCode = versionCode;
- this.resolveInfo = null;
+ this.filters = filters;
this.token = null;
this.needsPhaseTwo = false;
this.failureIntent = failureIntent;
}
+
+ /** Create a response for installing a split on demand. */
+ public AuxiliaryResolveInfo(@Nullable ComponentName failureActivity,
+ String packageName, long versionCode, String splitName) {
+ this(failureActivity, null, Collections.singletonList(
+ new AuxiliaryResolveInfo.AuxiliaryFilter(packageName, versionCode, splitName)));
+ }
+
+ /** @hide */
+ public static final class AuxiliaryFilter extends IntentFilter {
+ /** Resolved information returned from the external instant resolver */
+ public final InstantAppResolveInfo resolveInfo;
+ /** The resolved package. Copied from {@link #resolveInfo}. */
+ public final String packageName;
+ /** The version code of the package */
+ public final long versionCode;
+ /** The resolve split. Copied from the matched filter in {@link #resolveInfo}. */
+ public final String splitName;
+ /** The extras to pass on to the installer for this filter. */
+ public final Bundle extras;
+
+ public AuxiliaryFilter(IntentFilter orig, InstantAppResolveInfo resolveInfo,
+ String splitName, Bundle extras) {
+ super(orig);
+ this.resolveInfo = resolveInfo;
+ this.packageName = resolveInfo.getPackageName();
+ this.versionCode = resolveInfo.getLongVersionCode();
+ this.splitName = splitName;
+ this.extras = extras;
+ }
+
+ public AuxiliaryFilter(InstantAppResolveInfo resolveInfo,
+ String splitName, Bundle extras) {
+ this.resolveInfo = resolveInfo;
+ this.packageName = resolveInfo.getPackageName();
+ this.versionCode = resolveInfo.getLongVersionCode();
+ this.splitName = splitName;
+ this.extras = extras;
+ }
+
+ public AuxiliaryFilter(String packageName, long versionCode, String splitName) {
+ this.resolveInfo = null;
+ this.packageName = packageName;
+ this.versionCode = versionCode;
+ this.splitName = splitName;
+ this.extras = null;
+ }
+
+ @Override
+ public String toString() {
+ return "AuxiliaryFilter{"
+ + "packageName='" + packageName + '\''
+ + ", versionCode=" + versionCode
+ + ", splitName='" + splitName + '\'' + '}';
+ }
+ }
}
\ No newline at end of file
diff --git a/core/java/android/content/pm/EphemeralIntentFilter.java b/core/java/android/content/pm/EphemeralIntentFilter.java
deleted file mode 100644
index 1dbbf81..0000000
--- a/core/java/android/content/pm/EphemeralIntentFilter.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.content.IntentFilter;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Information about an ephemeral application intent filter.
- * @hide
- * @removed
- */
-@Deprecated
-@SystemApi
-public final class EphemeralIntentFilter implements Parcelable {
- private final InstantAppIntentFilter mInstantAppIntentFilter;
-
- public EphemeralIntentFilter(@Nullable String splitName, @NonNull List<IntentFilter> filters) {
- mInstantAppIntentFilter = new InstantAppIntentFilter(splitName, filters);
- }
-
- EphemeralIntentFilter(@NonNull InstantAppIntentFilter intentFilter) {
- mInstantAppIntentFilter = intentFilter;
- }
-
- EphemeralIntentFilter(Parcel in) {
- mInstantAppIntentFilter = in.readParcelable(null /*loader*/);
- }
-
- public String getSplitName() {
- return mInstantAppIntentFilter.getSplitName();
- }
-
- public List<IntentFilter> getFilters() {
- return mInstantAppIntentFilter.getFilters();
- }
-
- /** @hide */
- InstantAppIntentFilter getInstantAppIntentFilter() {
- return mInstantAppIntentFilter;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(mInstantAppIntentFilter, flags);
- }
-
- public static final Parcelable.Creator<EphemeralIntentFilter> CREATOR
- = new Parcelable.Creator<EphemeralIntentFilter>() {
- @Override
- public EphemeralIntentFilter createFromParcel(Parcel in) {
- return new EphemeralIntentFilter(in);
- }
- @Override
- public EphemeralIntentFilter[] newArray(int size) {
- return new EphemeralIntentFilter[size];
- }
- };
-}
diff --git a/core/java/android/content/pm/EphemeralResolveInfo.java b/core/java/android/content/pm/EphemeralResolveInfo.java
deleted file mode 100644
index 12131a3..0000000
--- a/core/java/android/content/pm/EphemeralResolveInfo.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.content.IntentFilter;
-import android.content.pm.InstantAppResolveInfo.InstantAppDigest;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Information about an ephemeral application.
- * @hide
- * @removed
- */
-@Deprecated
-@SystemApi
-public final class EphemeralResolveInfo implements Parcelable {
- /** Algorithm that will be used to generate the domain digest */
- public static final String SHA_ALGORITHM = "SHA-256";
-
- private final InstantAppResolveInfo mInstantAppResolveInfo;
- @Deprecated
- private final List<IntentFilter> mLegacyFilters;
-
- @Deprecated
- public EphemeralResolveInfo(@NonNull Uri uri, @NonNull String packageName,
- @NonNull List<IntentFilter> filters) {
- if (uri == null || packageName == null || filters == null || filters.isEmpty()) {
- throw new IllegalArgumentException();
- }
- final List<EphemeralIntentFilter> ephemeralFilters = new ArrayList<>(1);
- ephemeralFilters.add(new EphemeralIntentFilter(packageName, filters));
- mInstantAppResolveInfo = new InstantAppResolveInfo(uri.getHost(), packageName,
- createInstantAppIntentFilterList(ephemeralFilters));
- mLegacyFilters = new ArrayList<IntentFilter>(filters.size());
- mLegacyFilters.addAll(filters);
- }
-
- @Deprecated
- public EphemeralResolveInfo(@NonNull EphemeralDigest digest, @Nullable String packageName,
- @Nullable List<EphemeralIntentFilter> filters) {
- this(digest, packageName, filters, -1 /*versionCode*/);
- }
-
- public EphemeralResolveInfo(@NonNull EphemeralDigest digest, @Nullable String packageName,
- @Nullable List<EphemeralIntentFilter> filters, int versionCode) {
- mInstantAppResolveInfo = new InstantAppResolveInfo(
- digest.getInstantAppDigest(), packageName,
- createInstantAppIntentFilterList(filters), versionCode);
- mLegacyFilters = null;
- }
-
- public EphemeralResolveInfo(@NonNull String hostName, @Nullable String packageName,
- @Nullable List<EphemeralIntentFilter> filters) {
- this(new EphemeralDigest(hostName), packageName, filters);
- }
-
- EphemeralResolveInfo(Parcel in) {
- mInstantAppResolveInfo = in.readParcelable(null /*loader*/);
- mLegacyFilters = new ArrayList<IntentFilter>();
- in.readList(mLegacyFilters, null /*loader*/);
- }
-
- /** @hide */
- public InstantAppResolveInfo getInstantAppResolveInfo() {
- return mInstantAppResolveInfo;
- }
-
- private static List<InstantAppIntentFilter> createInstantAppIntentFilterList(
- List<EphemeralIntentFilter> filters) {
- if (filters == null) {
- return null;
- }
- final int filterCount = filters.size();
- final List<InstantAppIntentFilter> returnList = new ArrayList<>(filterCount);
- for (int i = 0; i < filterCount; i++) {
- returnList.add(filters.get(i).getInstantAppIntentFilter());
- }
- return returnList;
- }
-
- public byte[] getDigestBytes() {
- return mInstantAppResolveInfo.getDigestBytes();
- }
-
- public int getDigestPrefix() {
- return mInstantAppResolveInfo.getDigestPrefix();
- }
-
- public String getPackageName() {
- return mInstantAppResolveInfo.getPackageName();
- }
-
- public List<EphemeralIntentFilter> getIntentFilters() {
- final List<InstantAppIntentFilter> filters = mInstantAppResolveInfo.getIntentFilters();
- final int filterCount = filters.size();
- final List<EphemeralIntentFilter> returnList = new ArrayList<>(filterCount);
- for (int i = 0; i < filterCount; i++) {
- returnList.add(new EphemeralIntentFilter(filters.get(i)));
- }
- return returnList;
- }
-
- public int getVersionCode() {
- return mInstantAppResolveInfo.getVersionCode();
- }
-
- @Deprecated
- public List<IntentFilter> getFilters() {
- return mLegacyFilters;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(mInstantAppResolveInfo, flags);
- out.writeList(mLegacyFilters);
- }
-
- public static final Parcelable.Creator<EphemeralResolveInfo> CREATOR
- = new Parcelable.Creator<EphemeralResolveInfo>() {
- @Override
- public EphemeralResolveInfo createFromParcel(Parcel in) {
- return new EphemeralResolveInfo(in);
- }
- @Override
- public EphemeralResolveInfo[] newArray(int size) {
- return new EphemeralResolveInfo[size];
- }
- };
-
- /**
- * Helper class to generate and store each of the digests and prefixes
- * sent to the Ephemeral Resolver.
- * <p>
- * Since intent filters may want to handle multiple hosts within a
- * domain [eg “*.google.com”], the resolver is presented with multiple
- * hash prefixes. For example, "a.b.c.d.e" generates digests for
- * "d.e", "c.d.e", "b.c.d.e" and "a.b.c.d.e".
- *
- * @hide
- */
- @SystemApi
- public static final class EphemeralDigest implements Parcelable {
- private final InstantAppDigest mInstantAppDigest;
-
- public EphemeralDigest(@NonNull String hostName) {
- this(hostName, -1 /*maxDigests*/);
- }
-
- /** @hide */
- public EphemeralDigest(@NonNull String hostName, int maxDigests) {
- mInstantAppDigest = new InstantAppDigest(hostName, maxDigests);
- }
-
- EphemeralDigest(Parcel in) {
- mInstantAppDigest = in.readParcelable(null /*loader*/);
- }
-
- /** @hide */
- InstantAppDigest getInstantAppDigest() {
- return mInstantAppDigest;
- }
-
- public byte[][] getDigestBytes() {
- return mInstantAppDigest.getDigestBytes();
- }
-
- public int[] getDigestPrefix() {
- return mInstantAppDigest.getDigestPrefix();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(mInstantAppDigest, flags);
- }
-
- @SuppressWarnings("hiding")
- public static final Parcelable.Creator<EphemeralDigest> CREATOR =
- new Parcelable.Creator<EphemeralDigest>() {
- @Override
- public EphemeralDigest createFromParcel(Parcel in) {
- return new EphemeralDigest(in);
- }
- @Override
- public EphemeralDigest[] newArray(int size) {
- return new EphemeralDigest[size];
- }
- };
- }
-}
diff --git a/core/java/android/content/pm/InstantAppResolveInfo.java b/core/java/android/content/pm/InstantAppResolveInfo.java
index 19cb932..112c5da 100644
--- a/core/java/android/content/pm/InstantAppResolveInfo.java
+++ b/core/java/android/content/pm/InstantAppResolveInfo.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -26,11 +27,35 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
/**
- * Information about an instant application.
+ * Describes an externally resolvable instant application. There are three states that this class
+ * can represent: <p/>
+ * <ul>
+ * <li>
+ * The first, usable only for non http/s intents, implies that the resolver cannot
+ * immediately resolve this intent and would prefer that resolution be deferred to the
+ * instant app installer. Represent this state with {@link #InstantAppResolveInfo(Bundle)}.
+ * If the {@link android.content.Intent} has the scheme set to http/s and a set of digest
+ * prefixes were passed into one of the resolve methods in
+ * {@link android.app.InstantAppResolverService}, this state cannot be used.
+ * </li>
+ * <li>
+ * The second represents a partial match and is constructed with any of the other
+ * constructors. By setting one or more of the {@link Nullable}arguments to null, you
+ * communicate to the resolver in response to
+ * {@link android.app.InstantAppResolverService#onGetInstantAppResolveInfo(Intent, int[],
+ * String, InstantAppResolverService.InstantAppResolutionCallback)}
+ * that you need a 2nd round of resolution to complete the request.
+ * </li>
+ * <li>
+ * The third represents a complete match and is constructed with all @Nullable parameters
+ * populated.
+ * </li>
+ * </ul>
* @hide
*/
@SystemApi
@@ -38,6 +63,8 @@
/** Algorithm that will be used to generate the domain digest */
private static final String SHA_ALGORITHM = "SHA-256";
+ private static final byte[] EMPTY_DIGEST = new byte[0];
+
private final InstantAppDigest mDigest;
private final String mPackageName;
/** The filters used to match domain */
@@ -46,15 +73,30 @@
private final long mVersionCode;
/** Data about the app that should be passed along to the Instant App installer on resolve */
private final Bundle mExtras;
+ /**
+ * A flag that indicates that the resolver is aware that an app may match, but would prefer
+ * that the installer get the sanitized intent to decide. This should not be used for
+ * resolutions that include a host and will be ignored in such cases.
+ */
+ private final boolean mShouldLetInstallerDecide;
+ /** Constructor for intent-based InstantApp resolution results. */
public InstantAppResolveInfo(@NonNull InstantAppDigest digest, @Nullable String packageName,
@Nullable List<InstantAppIntentFilter> filters, int versionCode) {
this(digest, packageName, filters, (long) versionCode, null /* extras */);
}
+ /** Constructor for intent-based InstantApp resolution results with extras. */
public InstantAppResolveInfo(@NonNull InstantAppDigest digest, @Nullable String packageName,
@Nullable List<InstantAppIntentFilter> filters, long versionCode,
@Nullable Bundle extras) {
+ this(digest, packageName, filters, versionCode, extras, false);
+ }
+
+ /** Constructor for intent-based InstantApp resolution results with extras. */
+ private InstantAppResolveInfo(@NonNull InstantAppDigest digest, @Nullable String packageName,
+ @Nullable List<InstantAppIntentFilter> filters, long versionCode,
+ @Nullable Bundle extras, boolean shouldLetInstallerDecide) {
// validate arguments
if ((packageName == null && (filters != null && filters.size() != 0))
|| (packageName != null && (filters == null || filters.size() == 0))) {
@@ -62,7 +104,7 @@
}
mDigest = digest;
if (filters != null) {
- mFilters = new ArrayList<InstantAppIntentFilter>(filters.size());
+ mFilters = new ArrayList<>(filters.size());
mFilters.addAll(filters);
} else {
mFilters = null;
@@ -70,25 +112,48 @@
mPackageName = packageName;
mVersionCode = versionCode;
mExtras = extras;
+ mShouldLetInstallerDecide = shouldLetInstallerDecide;
}
+ /** Constructor for intent-based InstantApp resolution results by hostname. */
public InstantAppResolveInfo(@NonNull String hostName, @Nullable String packageName,
@Nullable List<InstantAppIntentFilter> filters) {
this(new InstantAppDigest(hostName), packageName, filters, -1 /*versionCode*/,
null /* extras */);
}
+ /**
+ * Constructor that creates a "let the installer decide" response with optional included
+ * extras.
+ */
+ public InstantAppResolveInfo(@Nullable Bundle extras) {
+ this(InstantAppDigest.UNDEFINED, null, null, -1, extras, true);
+ }
+
InstantAppResolveInfo(Parcel in) {
- mDigest = in.readParcelable(null /*loader*/);
- mPackageName = in.readString();
- mFilters = new ArrayList<InstantAppIntentFilter>();
- in.readList(mFilters, null /*loader*/);
- mVersionCode = in.readLong();
+ mShouldLetInstallerDecide = in.readBoolean();
mExtras = in.readBundle();
+ if (mShouldLetInstallerDecide) {
+ mDigest = InstantAppDigest.UNDEFINED;
+ mPackageName = null;
+ mFilters = Collections.emptyList();
+ mVersionCode = -1;
+ } else {
+ mDigest = in.readParcelable(null /*loader*/);
+ mPackageName = in.readString();
+ mFilters = new ArrayList<>();
+ in.readList(mFilters, null /*loader*/);
+ mVersionCode = in.readLong();
+ }
+ }
+
+ /** Returns true if the installer should be notified that it should query for packages. */
+ public boolean shouldLetInstallerDecide() {
+ return mShouldLetInstallerDecide;
}
public byte[] getDigestBytes() {
- return mDigest.getDigestBytes()[0];
+ return mDigest.mDigestBytes.length > 0 ? mDigest.getDigestBytes()[0] : EMPTY_DIGEST;
}
public int getDigestPrefix() {
@@ -127,11 +192,15 @@
@Override
public void writeToParcel(Parcel out, int flags) {
+ out.writeBoolean(mShouldLetInstallerDecide);
+ out.writeBundle(mExtras);
+ if (mShouldLetInstallerDecide) {
+ return;
+ }
out.writeParcelable(mDigest, flags);
out.writeString(mPackageName);
out.writeList(mFilters);
out.writeLong(mVersionCode);
- out.writeBundle(mExtras);
}
public static final Parcelable.Creator<InstantAppResolveInfo> CREATOR
@@ -159,7 +228,9 @@
@SystemApi
public static final class InstantAppDigest implements Parcelable {
private static final int DIGEST_MASK = 0xfffff000;
- private static final int DIGEST_PREFIX_COUNT = 5;
+
+ public static final InstantAppDigest UNDEFINED =
+ new InstantAppDigest(new byte[][]{}, new int[]{});
/** Full digest of the domain hashes */
private final byte[][] mDigestBytes;
/** The first 4 bytes of the domain hashes */
@@ -186,6 +257,11 @@
}
}
+ private InstantAppDigest(byte[][] digestBytes, int[] prefix) {
+ this.mDigestPrefix = prefix;
+ this.mDigestBytes = digestBytes;
+ }
+
private static byte[][] generateDigest(String hostName, int maxDigests) {
ArrayList<byte[]> digests = new ArrayList<>();
try {
diff --git a/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java b/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java
index 81041e9..81e4105 100644
--- a/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java
+++ b/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java
@@ -15,13 +15,12 @@
*/
package android.content.pm;
+import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+
import android.content.pm.PackageParser.Package;
-import android.os.Build;
import com.android.internal.annotations.VisibleForTesting;
-import java.util.ArrayList;
-
/**
* Updates a package to ensure that if it targets < P that the org.apache.http.legacy library is
* included by default.
@@ -37,30 +36,13 @@
@VisibleForTesting
public class OrgApacheHttpLegacyUpdater extends PackageSharedLibraryUpdater {
- private static final String APACHE_HTTP_LEGACY = "org.apache.http.legacy";
-
@Override
public void updatePackage(Package pkg) {
- ArrayList<String> usesLibraries = pkg.usesLibraries;
- ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;
-
// Packages targeted at <= O_MR1 expect the classes in the org.apache.http.legacy library
// to be accessible so this maintains backward compatibility by adding the
// org.apache.http.legacy library to those packages.
if (apkTargetsApiLevelLessThanOrEqualToOMR1(pkg)) {
- boolean apacheHttpLegacyPresent = isLibraryPresent(
- usesLibraries, usesOptionalLibraries, APACHE_HTTP_LEGACY);
- if (!apacheHttpLegacyPresent) {
- usesLibraries = prefix(usesLibraries, APACHE_HTTP_LEGACY);
- }
+ prefixRequiredLibrary(pkg, ORG_APACHE_HTTP_LEGACY);
}
-
- pkg.usesLibraries = usesLibraries;
- pkg.usesOptionalLibraries = usesOptionalLibraries;
- }
-
- private static boolean apkTargetsApiLevelLessThanOrEqualToOMR1(Package pkg) {
- int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
- return targetSdkVersion <= Build.VERSION_CODES.O_MR1;
}
}
diff --git a/core/java/android/content/pm/PackageBackwardCompatibility.java b/core/java/android/content/pm/PackageBackwardCompatibility.java
index 9bdb78b..a16f81b 100644
--- a/core/java/android/content/pm/PackageBackwardCompatibility.java
+++ b/core/java/android/content/pm/PackageBackwardCompatibility.java
@@ -16,14 +16,19 @@
package android.content.pm;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
+import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+
import android.content.pm.PackageParser.Package;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Supplier;
/**
* Modifies {@link Package} in order to maintain backwards compatibility.
@@ -35,54 +40,90 @@
private static final String TAG = PackageBackwardCompatibility.class.getSimpleName();
- private static final String ANDROID_TEST_MOCK = "android.test.mock";
-
- private static final String ANDROID_TEST_RUNNER = "android.test.runner";
-
private static final PackageBackwardCompatibility INSTANCE;
static {
- String className = "android.content.pm.OrgApacheHttpLegacyUpdater";
+ final List<PackageSharedLibraryUpdater> packageUpdaters = new ArrayList<>();
+
+ // Attempt to load and add the optional updater that will only be available when
+ // REMOVE_OAHL_FROM_BCP=true. If that could not be found then add the default updater that
+ // will remove any references to org.apache.http.library from the package so that it does
+ // not try and load the library when it is on the bootclasspath.
+ boolean bootClassPathContainsOAHL = !addOptionalUpdater(packageUpdaters,
+ "android.content.pm.OrgApacheHttpLegacyUpdater",
+ RemoveUnnecessaryOrgApacheHttpLegacyLibrary::new);
+
+ // Add this before adding AndroidTestBaseUpdater so that android.test.base comes before
+ // android.test.mock.
+ packageUpdaters.add(new AndroidTestRunnerSplitUpdater());
+
+ // Attempt to load and add the optional updater that will only be available when
+ // REMOVE_ATB_FROM_BCP=true. If that could not be found then add the default updater that
+ // will remove any references to org.apache.http.library from the package so that it does
+ // not try and load the library when it is on the bootclasspath.
+ boolean bootClassPathContainsATB = !addOptionalUpdater(packageUpdaters,
+ "android.content.pm.AndroidTestBaseUpdater",
+ RemoveUnnecessaryAndroidTestBaseLibrary::new);
+
+ PackageSharedLibraryUpdater[] updaterArray = packageUpdaters
+ .toArray(new PackageSharedLibraryUpdater[0]);
+ INSTANCE = new PackageBackwardCompatibility(
+ bootClassPathContainsOAHL, bootClassPathContainsATB, updaterArray);
+ }
+
+ /**
+ * Add an optional {@link PackageSharedLibraryUpdater} instance to the list, if it could not be
+ * found then add a default instance instead.
+ *
+ * @param packageUpdaters the list to update.
+ * @param className the name of the optional class.
+ * @param defaultUpdater the supplier of the default instance.
+ * @return true if the optional updater was added false otherwise.
+ */
+ private static boolean addOptionalUpdater(List<PackageSharedLibraryUpdater> packageUpdaters,
+ String className, Supplier<PackageSharedLibraryUpdater> defaultUpdater) {
Class<? extends PackageSharedLibraryUpdater> clazz;
try {
clazz = (PackageBackwardCompatibility.class.getClassLoader()
.loadClass(className)
.asSubclass(PackageSharedLibraryUpdater.class));
+ Log.i(TAG, "Loaded " + className);
} catch (ClassNotFoundException e) {
Log.i(TAG, "Could not find " + className + ", ignoring");
clazz = null;
}
- boolean hasOrgApacheHttpLegacy = false;
- final List<PackageSharedLibraryUpdater> packageUpdaters = new ArrayList<>();
+ boolean usedOptional = false;
+ PackageSharedLibraryUpdater updater;
if (clazz == null) {
- // Add an updater that will remove any references to org.apache.http.library from the
- // package so that it does not try and load the library when it is on the
- // bootclasspath.
- packageUpdaters.add(new RemoveUnnecessaryOrgApacheHttpLegacyLibrary());
+ updater = defaultUpdater.get();
} else {
try {
- packageUpdaters.add(clazz.getConstructor().newInstance());
- hasOrgApacheHttpLegacy = true;
+ updater = clazz.getConstructor().newInstance();
+ usedOptional = true;
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("Could not create instance of " + className, e);
}
}
-
- packageUpdaters.add(new AndroidTestRunnerSplitUpdater());
-
- PackageSharedLibraryUpdater[] updaterArray = packageUpdaters
- .toArray(new PackageSharedLibraryUpdater[0]);
- INSTANCE = new PackageBackwardCompatibility(hasOrgApacheHttpLegacy, updaterArray);
+ packageUpdaters.add(updater);
+ return usedOptional;
}
- private final boolean mRemovedOAHLFromBCP;
+ @VisibleForTesting
+ public static PackageSharedLibraryUpdater getInstance() {
+ return INSTANCE;
+ }
+
+ private final boolean mBootClassPathContainsOAHL;
+
+ private final boolean mBootClassPathContainsATB;
private final PackageSharedLibraryUpdater[] mPackageUpdaters;
- public PackageBackwardCompatibility(boolean removedOAHLFromBCP,
- PackageSharedLibraryUpdater[] packageUpdaters) {
- this.mRemovedOAHLFromBCP = removedOAHLFromBCP;
+ public PackageBackwardCompatibility(boolean bootClassPathContainsOAHL,
+ boolean bootClassPathContainsATB, PackageSharedLibraryUpdater[] packageUpdaters) {
+ this.mBootClassPathContainsOAHL = bootClassPathContainsOAHL;
+ this.mBootClassPathContainsATB = bootClassPathContainsATB;
this.mPackageUpdaters = packageUpdaters;
}
@@ -99,17 +140,25 @@
@Override
public void updatePackage(Package pkg) {
-
for (PackageSharedLibraryUpdater packageUpdater : mPackageUpdaters) {
packageUpdater.updatePackage(pkg);
}
}
/**
- * True if the org.apache.http.legacy has been removed the bootclasspath, false otherwise.
+ * True if the org.apache.http.legacy is on the bootclasspath, false otherwise.
*/
- public static boolean removeOAHLFromBCP() {
- return INSTANCE.mRemovedOAHLFromBCP;
+ @VisibleForTesting
+ public static boolean bootClassPathContainsOAHL() {
+ return INSTANCE.mBootClassPathContainsOAHL;
+ }
+
+ /**
+ * True if the android.test.base is on the bootclasspath, false otherwise.
+ */
+ @VisibleForTesting
+ public static boolean bootClassPathContainsATB() {
+ return INSTANCE.mBootClassPathContainsATB;
}
/**
@@ -126,24 +175,9 @@
@Override
public void updatePackage(Package pkg) {
- ArrayList<String> usesLibraries = pkg.usesLibraries;
- ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;
-
// android.test.runner has a dependency on android.test.mock so if android.test.runner
// is present but android.test.mock is not then add android.test.mock.
- boolean androidTestMockPresent = isLibraryPresent(
- usesLibraries, usesOptionalLibraries, ANDROID_TEST_MOCK);
- if (ArrayUtils.contains(usesLibraries, ANDROID_TEST_RUNNER)
- && !androidTestMockPresent) {
- usesLibraries.add(ANDROID_TEST_MOCK);
- }
- if (ArrayUtils.contains(usesOptionalLibraries, ANDROID_TEST_RUNNER)
- && !androidTestMockPresent) {
- usesOptionalLibraries.add(ANDROID_TEST_MOCK);
- }
-
- pkg.usesLibraries = usesLibraries;
- pkg.usesOptionalLibraries = usesOptionalLibraries;
+ prefixImplicitDependency(pkg, ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK);
}
}
@@ -155,13 +189,24 @@
public static class RemoveUnnecessaryOrgApacheHttpLegacyLibrary
extends PackageSharedLibraryUpdater {
- private static final String APACHE_HTTP_LEGACY = "org.apache.http.legacy";
+ @Override
+ public void updatePackage(Package pkg) {
+ removeLibrary(pkg, ORG_APACHE_HTTP_LEGACY);
+ }
+
+ }
+
+ /**
+ * Remove any usages of android.test.base from the shared library as the library is on the
+ * bootclasspath.
+ */
+ @VisibleForTesting
+ public static class RemoveUnnecessaryAndroidTestBaseLibrary
+ extends PackageSharedLibraryUpdater {
@Override
public void updatePackage(Package pkg) {
- pkg.usesLibraries = ArrayUtils.remove(pkg.usesLibraries, APACHE_HTTP_LEGACY);
- pkg.usesOptionalLibraries =
- ArrayUtils.remove(pkg.usesOptionalLibraries, APACHE_HTTP_LEGACY);
+ removeLibrary(pkg, ANDROID_TEST_BASE);
}
}
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5a894c7..0b4231f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1950,6 +1950,14 @@
* <li>Minor version number in bits 21-12</li>
* <li>Patch version number in bits 11-0</li>
* </ul>
+ * A version of 1.1.0 or higher also indicates:
+ * <ul>
+ * <li>The {@code VK_ANDROID_external_memory_android_hardware_buffer} extension is
+ * supported.</li>
+ * <li>{@code SYNC_FD} external semaphore and fence handles are supported.</li>
+ * <li>{@code VkPhysicalDeviceSamplerYcbcrConversionFeatures::samplerYcbcrConversion} is
+ * supported.</li>
+ * </ul>
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 3bb812b..2da8937 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -54,7 +54,6 @@
import android.content.pm.split.DefaultSplitAssetLoader;
import android.content.pm.split.SplitAssetDependencyLoader;
import android.content.pm.split.SplitAssetLoader;
-import android.content.res.ApkAssets;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -79,8 +78,10 @@
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Base64;
+import android.util.ByteStringUtils;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.PackageUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -1595,19 +1596,21 @@
int flags) throws PackageParserException {
final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
- ApkAssets apkAssets = null;
+ AssetManager assets = null;
XmlResourceParser parser = null;
try {
- try {
- apkAssets = fd != null
- ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
- : ApkAssets.loadFromPath(apkPath);
- } catch (IOException e) {
+ assets = newConfiguredAssetManager();
+ int cookie = fd != null
+ ? assets.addAssetFd(fd, debugPathName) : assets.addAssetPath(apkPath);
+ if (cookie == 0) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
"Failed to parse " + apkPath);
}
- parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
+ final DisplayMetrics metrics = new DisplayMetrics();
+ metrics.setToDefaults();
+
+ parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final SigningDetails signingDetails;
if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
@@ -1634,7 +1637,7 @@
"Failed to parse " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
- IoUtils.closeQuietly(apkAssets);
+ IoUtils.closeQuietly(assets);
}
}
@@ -5682,7 +5685,10 @@
return true;
}
- /** A container for signing-related data of an application package. */
+ /**
+ * A container for signing-related data of an application package.
+ * @hide
+ */
public static final class SigningDetails implements Parcelable {
@IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
@@ -5704,15 +5710,54 @@
public final ArraySet<PublicKey> publicKeys;
/**
- * Collection of {@code Signature} objects, each of which is formed from a former signing
- * certificate of this APK before it was changed by signing certificate rotation.
+ * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
+ * contains two pieces of information:
+ * 1) the past signing certificates
+ * 2) the flags that APK wants to assign to each of the past signing certificates.
+ *
+ * This collection of {@code Signature} objects, each of which is formed from a former
+ * signing certificate of this APK before it was changed by signing certificate rotation,
+ * represents the first piece of information. It is the APK saying to the rest of the
+ * world: "hey if you trust the old cert, you can trust me!" This is useful, if for
+ * instance, the platform would like to determine whether or not to allow this APK to do
+ * something it would've allowed it to do under the old cert (like upgrade).
*/
@Nullable
public final Signature[] pastSigningCertificates;
+ /** special value used to see if cert is in package - not exposed to callers */
+ private static final int PAST_CERT_EXISTS = 0;
+
+ @IntDef(
+ flag = true,
+ value = {CertCapabilities.INSTALLED_DATA,
+ CertCapabilities.SHARED_USER_ID,
+ CertCapabilities.PERMISSION })
+ public @interface CertCapabilities {
+
+ /** accept data from already installed pkg with this cert */
+ int INSTALLED_DATA = 1;
+
+ /** accept sharedUserId with pkg with this cert */
+ int SHARED_USER_ID = 2;
+
+ /** grant SIGNATURE permissions to pkgs with this cert */
+ int PERMISSION = 4;
+ }
+
/**
- * Flags for the {@code pastSigningCertificates} collection, which indicate the capabilities
- * the including APK wishes to grant to its past signing certificates.
+ * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
+ * contains two pieces of information:
+ * 1) the past signing certificates
+ * 2) the flags that APK wants to assign to each of the past signing certificates.
+ *
+ * These flags, which have a one-to-one relationship for the {@code pastSigningCertificates}
+ * collection, represent the second piece of information and are viewed as capabilities.
+ * They are an APK's way of telling the platform: "this is how I want to trust my old certs,
+ * please enforce that." This is useful for situation where this app itself is using its
+ * signing certificate as an authorization mechanism, like whether or not to allow another
+ * app to have its SIGNATURE permission. An app could specify whether to allow other apps
+ * signed by its old cert 'X' to still get a signature permission it defines, for example.
*/
@Nullable
public final int[] pastSigningCertificatesFlags;
@@ -5783,6 +5828,244 @@
return pastSigningCertificates != null && pastSigningCertificates.length > 0;
}
+ /**
+ * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one.
+ * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates,
+ * then that means it has authorized a signing certificate rotation, which eventually leads
+ * to our certificate, and thus can be trusted. If this method evaluates to true, this
+ * SigningDetails object should be trusted if the previous one is.
+ */
+ public boolean hasAncestorOrSelf(SigningDetails oldDetails) {
+ if (this == UNKNOWN || oldDetails == UNKNOWN) {
+ return false;
+ }
+ if (oldDetails.signatures.length > 1) {
+
+ // multiple-signer packages cannot rotate signing certs, so we just compare current
+ // signers for an exact match
+ return signaturesMatchExactly(oldDetails);
+ } else {
+
+ // we may have signing certificate rotation history, check to see if the oldDetails
+ // was one of our old signing certificates
+ return hasCertificate(oldDetails.signatures[0]);
+ }
+ }
+
+ /**
+ * Similar to {@code hasAncestorOrSelf}. Returns true only if this {@code SigningDetails}
+ * is a descendant of {@code oldDetails}, not if they're the same. This is used to
+ * determine if this object is newer than the provided one.
+ */
+ public boolean hasAncestor(SigningDetails oldDetails) {
+ if (this == UNKNOWN || oldDetails == UNKNOWN) {
+ return false;
+ }
+ if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
+
+ // the last entry in pastSigningCertificates is the current signer, ignore it
+ for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
+ if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or
+ * not this one grants it the provided capability, represented by the {@code flags}
+ * parameter. In the event of signing certificate rotation, a package may still interact
+ * with entities signed by its old signing certificate and not want to break previously
+ * functioning behavior. The {@code flags} value determines which capabilities the app
+ * signed by the newer signing certificate would like to continue to give to its previous
+ * signing certificate(s).
+ */
+ public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) {
+ if (this == UNKNOWN || oldDetails == UNKNOWN) {
+ return false;
+ }
+ if (oldDetails.signatures.length > 1) {
+
+ // multiple-signer packages cannot rotate signing certs, so we must have an exact
+ // match, which also means all capabilities are granted
+ return signaturesMatchExactly(oldDetails);
+ } else {
+
+ // we may have signing certificate rotation history, check to see if the oldDetails
+ // was one of our old signing certificates, and if we grant it the capability it's
+ // requesting
+ return hasCertificate(oldDetails.signatures[0], flags);
+ }
+ }
+
+ /**
+ * A special case of {@code checkCapability} which re-encodes both sets of signing
+ * certificates to counteract a previous re-encoding.
+ */
+ public boolean checkCapabilityRecover(SigningDetails oldDetails,
+ @CertCapabilities int flags) throws CertificateException {
+ if (oldDetails == UNKNOWN || this == UNKNOWN) {
+ return false;
+ }
+ if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
+
+ // signing certificates may have rotated, check entire history for effective match
+ for (int i = 0; i < pastSigningCertificates.length; i++) {
+ if (Signature.areEffectiveMatch(
+ oldDetails.signatures[0],
+ pastSigningCertificates[i])
+ && pastSigningCertificatesFlags[i] == flags) {
+ return true;
+ }
+ }
+ } else {
+ return Signature.areEffectiveMatch(oldDetails.signatures, signatures);
+ }
+ return false;
+ }
+
+ /**
+ * Determine if {@code signature} is in this SigningDetails' signing certificate history,
+ * including the current signer. Automatically returns false if this object has multiple
+ * signing certificates, since rotation is only supported for single-signers; this is
+ * enforced by {@code hasCertificateInternal}.
+ */
+ public boolean hasCertificate(Signature signature) {
+ return hasCertificateInternal(signature, PAST_CERT_EXISTS);
+ }
+
+ /**
+ * Determine if {@code signature} is in this SigningDetails' signing certificate history,
+ * including the current signer, and whether or not it has the given permission.
+ * Certificates which match our current signer automatically get all capabilities.
+ * Automatically returns false if this object has multiple signing certificates, since
+ * rotation is only supported for single-signers.
+ */
+ public boolean hasCertificate(Signature signature, @CertCapabilities int flags) {
+ return hasCertificateInternal(signature, flags);
+ }
+
+ /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */
+ public boolean hasCertificate(byte[] certificate) {
+ Signature signature = new Signature(certificate);
+ return hasCertificate(signature);
+ }
+
+ private boolean hasCertificateInternal(Signature signature, int flags) {
+ if (this == UNKNOWN) {
+ return false;
+ }
+
+ // only single-signed apps can have pastSigningCertificates
+ if (hasPastSigningCertificates()) {
+
+ // check all past certs, except for the current one, which automatically gets all
+ // capabilities, since it is the same as the current signature
+ for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
+ if (pastSigningCertificates[i].equals(signature)) {
+ if (flags == PAST_CERT_EXISTS
+ || (flags & pastSigningCertificatesFlags[i]) == flags) {
+ return true;
+ }
+ }
+ }
+ }
+
+ // not in previous certs signing history, just check the current signer and make sure
+ // we are singly-signed
+ return signatures.length == 1 && signatures[0].equals(signature);
+ }
+
+ /**
+ * Determines if the provided {@code sha256String} is an ancestor of this one, and whether
+ * or not this one grants it the provided capability, represented by the {@code flags}
+ * parameter. In the event of signing certificate rotation, a package may still interact
+ * with entities signed by its old signing certificate and not want to break previously
+ * functioning behavior. The {@code flags} value determines which capabilities the app
+ * signed by the newer signing certificate would like to continue to give to its previous
+ * signing certificate(s).
+ *
+ * @param sha256String A hex-encoded representation of a sha256 digest. In the case of an
+ * app with multiple signers, this represents the hex-encoded sha256
+ * digest of the combined hex-encoded sha256 digests of each individual
+ * signing certificate according to {@link
+ * PackageUtils#computeSignaturesSha256Digest(Signature[])}
+ */
+ public boolean checkCapability(String sha256String, @CertCapabilities int flags) {
+ if (this == UNKNOWN) {
+ return false;
+ }
+
+ // first see if the hash represents a single-signer in our signing history
+ byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String);
+ if (hasSha256Certificate(sha256Bytes, flags)) {
+ return true;
+ }
+
+ // Not in signing history, either represents multiple signatures or not a match.
+ // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match.
+ // We already check the single-signer case above as part of hasSha256Certificate, so no
+ // need to verify we have multiple signers, just run the old check
+ // just consider current signing certs
+ final String[] mSignaturesSha256Digests =
+ PackageUtils.computeSignaturesSha256Digests(signatures);
+ final String mSignaturesSha256Digest =
+ PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests);
+ return mSignaturesSha256Digest.equals(sha256String);
+ }
+
+ /**
+ * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate
+ * history, including the current signer. Automatically returns false if this object has
+ * multiple signing certificates, since rotation is only supported for single-signers.
+ */
+ public boolean hasSha256Certificate(byte[] sha256Certificate) {
+ return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS);
+ }
+
+ /**
+ * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing
+ * certificate in this SigningDetails' signing certificate history, including the current
+ * signer, and whether or not it has the given permission. Certificates which match our
+ * current signer automatically get all capabilities. Automatically returns false if this
+ * object has multiple signing certificates, since rotation is only supported for
+ * single-signers.
+ */
+ public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) {
+ return hasSha256CertificateInternal(sha256Certificate, flags);
+ }
+
+ private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) {
+ if (this == UNKNOWN) {
+ return false;
+ }
+ if (hasPastSigningCertificates()) {
+
+ // check all past certs, except for the last one, which automatically gets all
+ // capabilities, since it is the same as the current signature, and is checked below
+ for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
+ byte[] digest = PackageUtils.computeSha256DigestBytes(
+ pastSigningCertificates[i].toByteArray());
+ if (Arrays.equals(sha256Certificate, digest)) {
+ if (flags == PAST_CERT_EXISTS
+ || (flags & pastSigningCertificatesFlags[i]) == flags) {
+ return true;
+ }
+ }
+ }
+ }
+
+ // not in previous certs signing history, just check the current signer
+ if (signatures.length == 1) {
+ byte[] digest =
+ PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
+ return Arrays.equals(sha256Certificate, digest);
+ }
+ return false;
+ }
+
/** Returns true if the signatures in this and other match exactly. */
public boolean signaturesMatchExactly(SigningDetails other) {
return Signature.areExactMatch(this.signatures, other.signatures);
@@ -6393,6 +6676,11 @@
}
/** @hide */
+ public boolean isProduct() {
+ return applicationInfo.isProduct();
+ }
+
+ /** @hide */
public boolean isPrivileged() {
return applicationInfo.isPrivilegedApp();
}
diff --git a/core/java/android/content/pm/PackageSharedLibraryUpdater.java b/core/java/android/content/pm/PackageSharedLibraryUpdater.java
index 49d884c..fa89432 100644
--- a/core/java/android/content/pm/PackageSharedLibraryUpdater.java
+++ b/core/java/android/content/pm/PackageSharedLibraryUpdater.java
@@ -17,6 +17,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Build;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
@@ -38,6 +39,12 @@
*/
public abstract void updatePackage(PackageParser.Package pkg);
+ static void removeLibrary(PackageParser.Package pkg, String libraryName) {
+ pkg.usesLibraries = ArrayUtils.remove(pkg.usesLibraries, libraryName);
+ pkg.usesOptionalLibraries =
+ ArrayUtils.remove(pkg.usesOptionalLibraries, libraryName);
+ }
+
static @NonNull
<T> ArrayList<T> prefix(@Nullable ArrayList<T> cur, T val) {
if (cur == null) {
@@ -47,9 +54,54 @@
return cur;
}
- static boolean isLibraryPresent(ArrayList<String> usesLibraries,
+ private static boolean isLibraryPresent(ArrayList<String> usesLibraries,
ArrayList<String> usesOptionalLibraries, String apacheHttpLegacy) {
return ArrayUtils.contains(usesLibraries, apacheHttpLegacy)
|| ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
}
+
+ static boolean apkTargetsApiLevelLessThanOrEqualToOMR1(PackageParser.Package pkg) {
+ int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
+ return targetSdkVersion <= Build.VERSION_CODES.O_MR1;
+ }
+
+ /**
+ * Add an implicit dependency.
+ *
+ * <p>If the package has an existing dependency on {@code existingLibrary} then prefix it with
+ * the {@code implicitDependency} if it is not already in the list of libraries.
+ *
+ * @param pkg the {@link PackageParser.Package} to update.
+ * @param existingLibrary the existing library.
+ * @param implicitDependency the implicit dependency to add
+ */
+ void prefixImplicitDependency(PackageParser.Package pkg, String existingLibrary,
+ String implicitDependency) {
+ ArrayList<String> usesLibraries = pkg.usesLibraries;
+ ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;
+
+ if (!isLibraryPresent(usesLibraries, usesOptionalLibraries, implicitDependency)) {
+ if (ArrayUtils.contains(usesLibraries, existingLibrary)) {
+ prefix(usesLibraries, implicitDependency);
+ } else if (ArrayUtils.contains(usesOptionalLibraries, existingLibrary)) {
+ prefix(usesOptionalLibraries, implicitDependency);
+ }
+
+ pkg.usesLibraries = usesLibraries;
+ pkg.usesOptionalLibraries = usesOptionalLibraries;
+ }
+ }
+
+ void prefixRequiredLibrary(PackageParser.Package pkg, String libraryName) {
+ ArrayList<String> usesLibraries = pkg.usesLibraries;
+ ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;
+
+ boolean alreadyPresent = isLibraryPresent(
+ usesLibraries, usesOptionalLibraries, libraryName);
+ if (!alreadyPresent) {
+ usesLibraries = prefix(usesLibraries, libraryName);
+
+ pkg.usesLibraries = usesLibraries;
+ }
+ }
}
diff --git a/core/java/android/content/pm/SharedLibraryNames.java b/core/java/android/content/pm/SharedLibraryNames.java
new file mode 100644
index 0000000..83e8663
--- /dev/null
+++ b/core/java/android/content/pm/SharedLibraryNames.java
@@ -0,0 +1,32 @@
+/*
+ * 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.content.pm;
+
+/**
+ * A set of shared library names
+ *
+ * @hide
+ */
+public class SharedLibraryNames {
+
+ static final String ANDROID_TEST_BASE = "android.test.base";
+
+ static final String ANDROID_TEST_MOCK = "android.test.mock";
+
+ static final String ANDROID_TEST_RUNNER = "android.test.runner";
+
+ static final String ORG_APACHE_HTTP_LEGACY = "org.apache.http.legacy";
+}
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index fdc54ae..a2a14ed 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -285,6 +285,29 @@
}
/**
+ * Test if given {@link Signature} objects are effectively equal. In rare
+ * cases, certificates can have slightly malformed encoding which causes
+ * exact-byte checks to fail.
+ * <p>
+ * To identify effective equality, we bounce the certificates through an
+ * decode/encode pass before doing the exact-byte check. To reduce attack
+ * surface area, we only allow a byte size delta of a few bytes.
+ *
+ * @throws CertificateException if the before/after length differs
+ * substantially, usually a signal of something fishy going on.
+ * @hide
+ */
+ public static boolean areEffectiveMatch(Signature a, Signature b)
+ throws CertificateException {
+ final CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+ final Signature aPrime = bounce(cf, a);
+ final Signature bPrime = bounce(cf, b);
+
+ return aPrime.equals(bPrime);
+ }
+
+ /**
* Bounce the given {@link Signature} through a decode/encode cycle.
*
* @throws CertificateException if the before/after length differs
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
deleted file mode 100644
index b087c48..0000000
--- a/core/java/android/content/res/ApkAssets.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.content.res;
-
-import android.annotation.NonNull;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * The loaded, immutable, in-memory representation of an APK.
- *
- * The main implementation is native C++ and there is very little API surface exposed here. The APK
- * is mainly accessed via {@link AssetManager}.
- *
- * Since the ApkAssets instance is immutable, it can be reused and shared across AssetManagers,
- * making the creation of AssetManagers very cheap.
- * @hide
- */
-public final class ApkAssets implements AutoCloseable {
- @GuardedBy("this") private long mNativePtr;
- @GuardedBy("this") private StringBlock mStringBlock;
-
- /**
- * Creates a new ApkAssets instance from the given path on disk.
- *
- * @param path The path to an APK on disk.
- * @return a new instance of ApkAssets.
- * @throws IOException if a disk I/O error or parsing error occurred.
- */
- public static @NonNull ApkAssets loadFromPath(@NonNull String path) throws IOException {
- return new ApkAssets(path, false /*system*/, false /*forceSharedLib*/, false /*overlay*/);
- }
-
- /**
- * Creates a new ApkAssets instance from the given path on disk.
- *
- * @param path The path to an APK on disk.
- * @param system When true, the APK is loaded as a system APK (framework).
- * @return a new instance of ApkAssets.
- * @throws IOException if a disk I/O error or parsing error occurred.
- */
- public static @NonNull ApkAssets loadFromPath(@NonNull String path, boolean system)
- throws IOException {
- return new ApkAssets(path, system, false /*forceSharedLib*/, false /*overlay*/);
- }
-
- /**
- * Creates a new ApkAssets instance from the given path on disk.
- *
- * @param path The path to an APK on disk.
- * @param system When true, the APK is loaded as a system APK (framework).
- * @param forceSharedLibrary When true, any packages within the APK with package ID 0x7f are
- * loaded as a shared library.
- * @return a new instance of ApkAssets.
- * @throws IOException if a disk I/O error or parsing error occurred.
- */
- public static @NonNull ApkAssets loadFromPath(@NonNull String path, boolean system,
- boolean forceSharedLibrary) throws IOException {
- return new ApkAssets(path, system, forceSharedLibrary, false /*overlay*/);
- }
-
- /**
- * Creates a new ApkAssets instance from the given file descriptor. Not for use by applications.
- *
- * Performs a dup of the underlying fd, so you must take care of still closing
- * the FileDescriptor yourself (and can do that whenever you want).
- *
- * @param fd The FileDescriptor of an open, readable APK.
- * @param friendlyName The friendly name used to identify this ApkAssets when logging.
- * @param system When true, the APK is loaded as a system APK (framework).
- * @param forceSharedLibrary When true, any packages within the APK with package ID 0x7f are
- * loaded as a shared library.
- * @return a new instance of ApkAssets.
- * @throws IOException if a disk I/O error or parsing error occurred.
- */
- public static @NonNull ApkAssets loadFromFd(@NonNull FileDescriptor fd,
- @NonNull String friendlyName, boolean system, boolean forceSharedLibrary)
- throws IOException {
- return new ApkAssets(fd, friendlyName, system, forceSharedLibrary);
- }
-
- /**
- * Creates a new ApkAssets instance from the IDMAP at idmapPath. The overlay APK path
- * is encoded within the IDMAP.
- *
- * @param idmapPath Path to the IDMAP of an overlay APK.
- * @param system When true, the APK is loaded as a system APK (framework).
- * @return a new instance of ApkAssets.
- * @throws IOException if a disk I/O error or parsing error occurred.
- */
- public static @NonNull ApkAssets loadOverlayFromPath(@NonNull String idmapPath, boolean system)
- throws IOException {
- return new ApkAssets(idmapPath, system, false /*forceSharedLibrary*/, true /*overlay*/);
- }
-
- private ApkAssets(@NonNull String path, boolean system, boolean forceSharedLib, boolean overlay)
- throws IOException {
- Preconditions.checkNotNull(path, "path");
- mNativePtr = nativeLoad(path, system, forceSharedLib, overlay);
- mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
- }
-
- private ApkAssets(@NonNull FileDescriptor fd, @NonNull String friendlyName, boolean system,
- boolean forceSharedLib) throws IOException {
- Preconditions.checkNotNull(fd, "fd");
- Preconditions.checkNotNull(friendlyName, "friendlyName");
- mNativePtr = nativeLoadFromFd(fd, friendlyName, system, forceSharedLib);
- mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
- }
-
- @NonNull String getAssetPath() {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetAssetPath(mNativePtr);
- }
- }
-
- CharSequence getStringFromPool(int idx) {
- synchronized (this) {
- ensureValidLocked();
- return mStringBlock.get(idx);
- }
- }
-
- /**
- * Retrieve a parser for a compiled XML file. This is associated with a single APK and
- * <em>NOT</em> a full AssetManager. This means that shared-library references will not be
- * dynamically assigned runtime package IDs.
- *
- * @param fileName The path to the file within the APK.
- * @return An XmlResourceParser.
- * @throws IOException if the file was not found or an error occurred retrieving it.
- */
- public @NonNull XmlResourceParser openXml(@NonNull String fileName) throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
- synchronized (this) {
- ensureValidLocked();
- long nativeXmlPtr = nativeOpenXml(mNativePtr, fileName);
- try (XmlBlock block = new XmlBlock(null, nativeXmlPtr)) {
- XmlResourceParser parser = block.newParser();
- // If nativeOpenXml doesn't throw, it will always return a valid native pointer,
- // which makes newParser always return non-null. But let's be paranoid.
- if (parser == null) {
- throw new AssertionError("block.newParser() returned a null parser");
- }
- return parser;
- }
- }
- }
-
- /**
- * Returns false if the underlying APK was changed since this ApkAssets was loaded.
- */
- public boolean isUpToDate() {
- synchronized (this) {
- ensureValidLocked();
- return nativeIsUpToDate(mNativePtr);
- }
- }
-
- /**
- * Closes the ApkAssets and destroys the underlying native implementation. Further use of the
- * ApkAssets object will cause exceptions to be thrown.
- *
- * Calling close on an already closed ApkAssets does nothing.
- */
- @Override
- public void close() {
- synchronized (this) {
- if (mNativePtr == 0) {
- return;
- }
-
- mStringBlock = null;
- nativeDestroy(mNativePtr);
- mNativePtr = 0;
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- if (mNativePtr != 0) {
- nativeDestroy(mNativePtr);
- }
- }
-
- private void ensureValidLocked() {
- if (mNativePtr == 0) {
- throw new RuntimeException("ApkAssets is closed");
- }
- }
-
- private static native long nativeLoad(
- @NonNull String path, boolean system, boolean forceSharedLib, boolean overlay)
- throws IOException;
- private static native long nativeLoadFromFd(@NonNull FileDescriptor fd,
- @NonNull String friendlyName, boolean system, boolean forceSharedLib)
- throws IOException;
- private static native void nativeDestroy(long ptr);
- private static native @NonNull String nativeGetAssetPath(long ptr);
- private static native long nativeGetStringBlock(long ptr);
- private static native boolean nativeIsUpToDate(long ptr);
- private static native long nativeOpenXml(long ptr, @NonNull String fileName) throws IOException;
-}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 78370f4..7866560 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -18,11 +18,9 @@
import android.annotation.AnyRes;
import android.annotation.ArrayRes;
-import android.annotation.AttrRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.StyleRes;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration.NativeConfig;
import android.os.ParcelFileDescriptor;
@@ -30,18 +28,10 @@
import android.util.SparseArray;
import android.util.TypedValue;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
+import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.channels.FileLock;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
/**
@@ -52,17 +42,7 @@
* bytes.
*/
public final class AssetManager implements AutoCloseable {
- private static final String TAG = "AssetManager";
- private static final boolean DEBUG_REFS = false;
-
- private static final String FRAMEWORK_APK_PATH = "/system/framework/framework-res.apk";
-
- private static final Object sSync = new Object();
-
- // Not private for LayoutLib's BridgeAssetManager.
- @GuardedBy("sSync") static AssetManager sSystem = null;
-
- @GuardedBy("sSync") private static ApkAssets[] sSystemApkAssets = new ApkAssets[0];
+ /* modes used when opening an asset */
/**
* Mode for {@link #open(String, int)}: no specific information about how
@@ -85,279 +65,87 @@
*/
public static final int ACCESS_BUFFER = 3;
- @GuardedBy("this") private final TypedValue mValue = new TypedValue();
- @GuardedBy("this") private final long[] mOffsets = new long[2];
+ private static final String TAG = "AssetManager";
+ private static final boolean localLOGV = false || false;
+
+ private static final boolean DEBUG_REFS = false;
+
+ private static final Object sSync = new Object();
+ /*package*/ static AssetManager sSystem = null;
- // Pointer to native implementation, stuffed inside a long.
- @GuardedBy("this") private long mObject;
+ private final TypedValue mValue = new TypedValue();
+ private final long[] mOffsets = new long[2];
+
+ // For communication with native code.
+ private long mObject;
- // The loaded asset paths.
- @GuardedBy("this") private ApkAssets[] mApkAssets;
-
- // Debug/reference counting implementation.
- @GuardedBy("this") private boolean mOpen = true;
- @GuardedBy("this") private int mNumRefs = 1;
- @GuardedBy("this") private HashMap<Long, RuntimeException> mRefStacks;
-
+ private StringBlock mStringBlocks[] = null;
+
+ private int mNumRefs = 1;
+ private boolean mOpen = true;
+ private HashMap<Long, RuntimeException> mRefStacks;
+
/**
* Create a new AssetManager containing only the basic system assets.
* Applications will not generally use this method, instead retrieving the
* appropriate asset manager with {@link Resources#getAssets}. Not for
* use by applications.
- * @hide
+ * {@hide}
*/
public AssetManager() {
- final ApkAssets[] assets;
- synchronized (sSync) {
- createSystemAssetsInZygoteLocked();
- assets = sSystemApkAssets;
- }
-
- mObject = nativeCreate();
- if (DEBUG_REFS) {
- mNumRefs = 0;
- incRefsLocked(hashCode());
- }
-
- // Always set the framework resources.
- setApkAssets(assets, false /*invalidateCaches*/);
- }
-
- /**
- * Private constructor that doesn't call ensureSystemAssets.
- * Used for the creation of system assets.
- */
- @SuppressWarnings("unused")
- private AssetManager(boolean sentinel) {
- mObject = nativeCreate();
- if (DEBUG_REFS) {
- mNumRefs = 0;
- incRefsLocked(hashCode());
- }
- }
-
- /**
- * This must be called from Zygote so that system assets are shared by all applications.
- * @hide
- */
- private static void createSystemAssetsInZygoteLocked() {
- if (sSystem != null) {
- return;
- }
-
- // Make sure that all IDMAPs are up to date.
- nativeVerifySystemIdmaps();
-
- try {
- ArrayList<ApkAssets> apkAssets = new ArrayList<>();
- apkAssets.add(ApkAssets.loadFromPath(FRAMEWORK_APK_PATH, true /*system*/));
-
- // Load all static RROs.
- try (FileInputStream fis = new FileInputStream(
- "/data/resource-cache/overlays.list");
- BufferedReader br = new BufferedReader(new InputStreamReader(fis))) {
- // Acquire a lock so that any idmap scanning doesn't impact the current set.
- try (FileLock flock = fis.getChannel().lock(0, Long.MAX_VALUE,
- true /*shared*/)) {
- for (String line; (line = br.readLine()) != null; ) {
- String idmapPath = line.split(" ")[1];
- apkAssets.add(
- ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
- }
- }
+ synchronized (this) {
+ if (DEBUG_REFS) {
+ mNumRefs = 0;
+ incRefsLocked(this.hashCode());
}
-
- sSystemApkAssets = apkAssets.toArray(new ApkAssets[apkAssets.size()]);
- sSystem = new AssetManager(true /*sentinel*/);
- sSystem.setApkAssets(sSystemApkAssets, false /*invalidateCaches*/);
- } catch (IOException e) {
- throw new IllegalStateException("Failed to create system AssetManager", e);
+ init(false);
+ if (localLOGV) Log.v(TAG, "New asset manager: " + this);
+ ensureSystemAssets();
}
}
+ private static void ensureSystemAssets() {
+ synchronized (sSync) {
+ if (sSystem == null) {
+ AssetManager system = new AssetManager(true);
+ system.makeStringBlocks(null);
+ sSystem = system;
+ }
+ }
+ }
+
+ private AssetManager(boolean isSystem) {
+ if (DEBUG_REFS) {
+ synchronized (this) {
+ mNumRefs = 0;
+ incRefsLocked(this.hashCode());
+ }
+ }
+ init(true);
+ if (localLOGV) Log.v(TAG, "New asset manager: " + this);
+ }
+
/**
* Return a global shared asset manager that provides access to only
* system assets (no application assets).
- * @hide
+ * {@hide}
*/
public static AssetManager getSystem() {
- synchronized (sSync) {
- createSystemAssetsInZygoteLocked();
- return sSystem;
- }
+ ensureSystemAssets();
+ return sSystem;
}
/**
* Close this asset manager.
*/
- @Override
public void close() {
- synchronized (this) {
- if (!mOpen) {
- return;
+ synchronized(this) {
+ //System.out.println("Release: num=" + mNumRefs
+ // + ", released=" + mReleased);
+ if (mOpen) {
+ mOpen = false;
+ decRefsLocked(this.hashCode());
}
-
- mOpen = false;
- decRefsLocked(hashCode());
- }
- }
-
- /**
- * Changes the asset paths in this AssetManager. This replaces the {@link #addAssetPath(String)}
- * family of methods.
- *
- * @param apkAssets The new set of paths.
- * @param invalidateCaches Whether to invalidate any caches. This should almost always be true.
- * Set this to false if you are appending new resources
- * (not new configurations).
- * @hide
- */
- public void setApkAssets(@NonNull ApkAssets[] apkAssets, boolean invalidateCaches) {
- Preconditions.checkNotNull(apkAssets, "apkAssets");
- synchronized (this) {
- ensureValidLocked();
- mApkAssets = apkAssets;
- nativeSetApkAssets(mObject, apkAssets, invalidateCaches);
- if (invalidateCaches) {
- // Invalidate all caches.
- invalidateCachesLocked(-1);
- }
- }
- }
-
- /**
- * Invalidates the caches in this AssetManager according to the bitmask `diff`.
- *
- * @param diff The bitmask of changes generated by {@link Configuration#diff(Configuration)}.
- * @see ActivityInfo.Config
- */
- private void invalidateCachesLocked(int diff) {
- // TODO(adamlesinski): Currently there are no caches to invalidate in Java code.
- }
-
- /**
- * @hide
- */
- public @NonNull ApkAssets[] getApkAssets() {
- synchronized (this) {
- ensureValidLocked();
- return mApkAssets;
- }
- }
-
- /**
- * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
- * @hide
- */
- @Deprecated
- public int addAssetPath(String path) {
- return addAssetPathInternal(path, false /*overlay*/, false /*appAsLib*/);
- }
-
- /**
- * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
- * @hide
- */
- @Deprecated
- public int addAssetPathAsSharedLibrary(String path) {
- return addAssetPathInternal(path, false /*overlay*/, true /*appAsLib*/);
- }
-
- /**
- * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}
- * @hide
- */
- @Deprecated
- public int addOverlayPath(String path) {
- return addAssetPathInternal(path, true /*overlay*/, false /*appAsLib*/);
- }
-
- private int addAssetPathInternal(String path, boolean overlay, boolean appAsLib) {
- Preconditions.checkNotNull(path, "path");
- synchronized (this) {
- ensureOpenLocked();
- final int count = mApkAssets.length;
- for (int i = 0; i < count; i++) {
- if (mApkAssets[i].getAssetPath().equals(path)) {
- return i + 1;
- }
- }
-
- final ApkAssets assets;
- try {
- if (overlay) {
- // TODO(b/70343104): This hardcoded path will be removed once
- // addAssetPathInternal is deleted.
- final String idmapPath = "/data/resource-cache/"
- + path.substring(1).replace('/', '@')
- + "@idmap";
- assets = ApkAssets.loadOverlayFromPath(idmapPath, false /*system*/);
- } else {
- assets = ApkAssets.loadFromPath(path, false /*system*/, appAsLib);
- }
- } catch (IOException e) {
- return 0;
- }
-
- final ApkAssets[] newApkAssets = Arrays.copyOf(mApkAssets, count + 1);
- newApkAssets[count] = assets;
- setApkAssets(newApkAssets, true);
- return count + 1;
- }
- }
-
- /**
- * Ensures that the native implementation has not been destroyed.
- * The AssetManager may have been closed, but references to it still exist
- * and therefore the native implementation is not destroyed.
- */
- private void ensureValidLocked() {
- if (mObject == 0) {
- throw new RuntimeException("AssetManager has been destroyed");
- }
- }
-
- /**
- * Ensures that the AssetManager has not been explicitly closed. If this method passes,
- * then this implies that ensureValidLocked() also passes.
- */
- private void ensureOpenLocked() {
- if (!mOpen) {
- throw new RuntimeException("AssetManager has been closed");
- }
- }
-
- /**
- * Populates {@code outValue} with the data associated a particular
- * resource identifier for the current configuration.
- *
- * @param resId the resource identifier to load
- * @param densityDpi the density bucket for which to load the resource
- * @param outValue the typed value in which to put the data
- * @param resolveRefs {@code true} to resolve references, {@code false}
- * to leave them unresolved
- * @return {@code true} if the data was loaded into {@code outValue},
- * {@code false} otherwise
- */
- boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
- boolean resolveRefs) {
- Preconditions.checkNotNull(outValue, "outValue");
- synchronized (this) {
- ensureValidLocked();
- final int cookie = nativeGetResourceValue(
- mObject, resId, (short) densityDpi, outValue, resolveRefs);
- if (cookie <= 0) {
- return false;
- }
-
- // Convert the changing configurations flags populated by native code.
- outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
- outValue.changingConfigurations);
-
- if (outValue.type == TypedValue.TYPE_STRING) {
- outValue.string = mApkAssets[cookie - 1].getStringFromPool(outValue.data);
- }
- return true;
}
}
@@ -368,7 +156,8 @@
* @param resId the resource identifier to load
* @return the string value, or {@code null}
*/
- @Nullable CharSequence getResourceText(@StringRes int resId) {
+ @Nullable
+ final CharSequence getResourceText(@StringRes int resId) {
synchronized (this) {
final TypedValue outValue = mValue;
if (getResourceValue(resId, 0, outValue, true)) {
@@ -383,15 +172,15 @@
* identifier for the current configuration.
*
* @param resId the resource identifier to load
- * @param bagEntryId the index into the bag to load
+ * @param bagEntryId
* @return the string value, or {@code null}
*/
- @Nullable CharSequence getResourceBagText(@StringRes int resId, int bagEntryId) {
+ @Nullable
+ final CharSequence getResourceBagText(@StringRes int resId, int bagEntryId) {
synchronized (this) {
- ensureValidLocked();
final TypedValue outValue = mValue;
- final int cookie = nativeGetResourceBagValue(mObject, resId, bagEntryId, outValue);
- if (cookie <= 0) {
+ final int block = loadResourceBagValue(resId, bagEntryId, outValue, true);
+ if (block < 0) {
return null;
}
@@ -400,49 +189,12 @@
outValue.changingConfigurations);
if (outValue.type == TypedValue.TYPE_STRING) {
- return mApkAssets[cookie - 1].getStringFromPool(outValue.data);
+ return mStringBlocks[block].get(outValue.data);
}
return outValue.coerceToString();
}
}
- int getResourceArraySize(@ArrayRes int resId) {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetResourceArraySize(mObject, resId);
- }
- }
-
- /**
- * Populates `outData` with array elements of `resId`. `outData` is normally
- * used with
- * {@link TypedArray}.
- *
- * Each logical element in `outData` is {@link TypedArray#STYLE_NUM_ENTRIES}
- * long,
- * with the indices of the data representing the type, value, asset cookie,
- * resource ID,
- * configuration change mask, and density of the element.
- *
- * @param resId The resource ID of an array resource.
- * @param outData The array to populate with data.
- * @return The length of the array.
- *
- * @see TypedArray#STYLE_TYPE
- * @see TypedArray#STYLE_DATA
- * @see TypedArray#STYLE_ASSET_COOKIE
- * @see TypedArray#STYLE_RESOURCE_ID
- * @see TypedArray#STYLE_CHANGING_CONFIGURATIONS
- * @see TypedArray#STYLE_DENSITY
- */
- int getResourceArray(@ArrayRes int resId, @NonNull int[] outData) {
- Preconditions.checkNotNull(outData, "outData");
- synchronized (this) {
- ensureValidLocked();
- return nativeGetResourceArray(mObject, resId, outData);
- }
- }
-
/**
* Retrieves the string array associated with a particular resource
* identifier for the current configuration.
@@ -450,10 +202,39 @@
* @param resId the resource identifier of the string array
* @return the string array, or {@code null}
*/
- @Nullable String[] getResourceStringArray(@ArrayRes int resId) {
+ @Nullable
+ final String[] getResourceStringArray(@ArrayRes int resId) {
+ return getArrayStringResource(resId);
+ }
+
+ /**
+ * Populates {@code outValue} with the data associated a particular
+ * resource identifier for the current configuration.
+ *
+ * @param resId the resource identifier to load
+ * @param densityDpi the density bucket for which to load the resource
+ * @param outValue the typed value in which to put the data
+ * @param resolveRefs {@code true} to resolve references, {@code false}
+ * to leave them unresolved
+ * @return {@code true} if the data was loaded into {@code outValue},
+ * {@code false} otherwise
+ */
+ final boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
+ boolean resolveRefs) {
synchronized (this) {
- ensureValidLocked();
- return nativeGetResourceStringArray(mObject, resId);
+ final int block = loadResourceValue(resId, (short) densityDpi, outValue, resolveRefs);
+ if (block < 0) {
+ return false;
+ }
+
+ // Convert the changing configurations flags populated by native code.
+ outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+ outValue.changingConfigurations);
+
+ if (outValue.type == TypedValue.TYPE_STRING) {
+ outValue.string = mStringBlocks[block].get(outValue.data);
+ }
+ return true;
}
}
@@ -463,48 +244,26 @@
*
* @param resId the resource id of the string array
*/
- @Nullable CharSequence[] getResourceTextArray(@ArrayRes int resId) {
+ final @Nullable CharSequence[] getResourceTextArray(@ArrayRes int resId) {
synchronized (this) {
- ensureValidLocked();
- final int[] rawInfoArray = nativeGetResourceStringArrayInfo(mObject, resId);
+ final int[] rawInfoArray = getArrayStringInfo(resId);
if (rawInfoArray == null) {
return null;
}
-
final int rawInfoArrayLen = rawInfoArray.length;
final int infoArrayLen = rawInfoArrayLen / 2;
+ int block;
+ int index;
final CharSequence[] retArray = new CharSequence[infoArrayLen];
for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) {
- int cookie = rawInfoArray[i];
- int index = rawInfoArray[i + 1];
- retArray[j] = (index >= 0 && cookie > 0)
- ? mApkAssets[cookie - 1].getStringFromPool(index) : null;
+ block = rawInfoArray[i];
+ index = rawInfoArray[i + 1];
+ retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null;
}
return retArray;
}
}
- @Nullable int[] getResourceIntArray(@ArrayRes int resId) {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetResourceIntArray(mObject, resId);
- }
- }
-
- /**
- * Get the attributes for a style resource. These are the <item>
- * elements in
- * a <style> resource.
- * @param resId The resource ID of the style
- * @return An array of attribute IDs.
- */
- @AttrRes int[] getStyleAttributes(@StyleRes int resId) {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetStyleAttributes(mObject, resId);
- }
- }
-
/**
* Populates {@code outValue} with the data associated with a particular
* resource identifier for the current configuration. Resolves theme
@@ -518,88 +277,73 @@
* @return {@code true} if the data was loaded into {@code outValue},
* {@code false} otherwise
*/
- boolean getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue,
+ final boolean getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue,
boolean resolveRefs) {
- Preconditions.checkNotNull(outValue, "outValue");
+ final int block = loadThemeAttributeValue(theme, resId, outValue, resolveRefs);
+ if (block < 0) {
+ return false;
+ }
+
+ // Convert the changing configurations flags populated by native code.
+ outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+ outValue.changingConfigurations);
+
+ if (outValue.type == TypedValue.TYPE_STRING) {
+ final StringBlock[] blocks = ensureStringBlocks();
+ outValue.string = blocks[block].get(outValue.data);
+ }
+ return true;
+ }
+
+ /**
+ * Ensures the string blocks are loaded.
+ *
+ * @return the string blocks
+ */
+ @NonNull
+ final StringBlock[] ensureStringBlocks() {
synchronized (this) {
- ensureValidLocked();
- final int cookie = nativeThemeGetAttributeValue(mObject, theme, resId, outValue,
- resolveRefs);
- if (cookie <= 0) {
- return false;
+ if (mStringBlocks == null) {
+ makeStringBlocks(sSystem.mStringBlocks);
}
+ return mStringBlocks;
+ }
+ }
- // Convert the changing configurations flags populated by native code.
- outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
- outValue.changingConfigurations);
-
- if (outValue.type == TypedValue.TYPE_STRING) {
- outValue.string = mApkAssets[cookie - 1].getStringFromPool(outValue.data);
+ /*package*/ final void makeStringBlocks(StringBlock[] seed) {
+ final int seedNum = (seed != null) ? seed.length : 0;
+ final int num = getStringBlockCount();
+ mStringBlocks = new StringBlock[num];
+ if (localLOGV) Log.v(TAG, "Making string blocks for " + this
+ + ": " + num);
+ for (int i=0; i<num; i++) {
+ if (i < seedNum) {
+ mStringBlocks[i] = seed[i];
+ } else {
+ mStringBlocks[i] = new StringBlock(getNativeStringBlock(i), true);
}
- return true;
}
}
- void dumpTheme(long theme, int priority, String tag, String prefix) {
+ /*package*/ final CharSequence getPooledStringForCookie(int cookie, int id) {
synchronized (this) {
- ensureValidLocked();
- nativeThemeDump(mObject, theme, priority, tag, prefix);
+ // Cookies map to string blocks starting at 1.
+ return mStringBlocks[cookie - 1].get(id);
}
}
- @Nullable String getResourceName(@AnyRes int resId) {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetResourceName(mObject, resId);
- }
- }
-
- @Nullable String getResourcePackageName(@AnyRes int resId) {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetResourcePackageName(mObject, resId);
- }
- }
-
- @Nullable String getResourceTypeName(@AnyRes int resId) {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetResourceTypeName(mObject, resId);
- }
- }
-
- @Nullable String getResourceEntryName(@AnyRes int resId) {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetResourceEntryName(mObject, resId);
- }
- }
-
- @AnyRes int getResourceIdentifier(@NonNull String name, @Nullable String defType,
- @Nullable String defPackage) {
- synchronized (this) {
- ensureValidLocked();
- // name is checked in JNI.
- return nativeGetResourceIdentifier(mObject, name, defType, defPackage);
- }
- }
-
- CharSequence getPooledStringForCookie(int cookie, int id) {
- // Cookies map to ApkAssets starting at 1.
- return getApkAssets()[cookie - 1].getStringFromPool(id);
- }
-
/**
* Open an asset using ACCESS_STREAMING mode. This provides access to
* files that have been bundled with an application as assets -- that is,
* files placed in to the "assets" directory.
*
- * @param fileName The name of the asset to open. This name can be hierarchical.
+ * @param fileName The name of the asset to open. This name can be
+ * hierarchical.
*
* @see #open(String, int)
* @see #list
*/
- public @NonNull InputStream open(@NonNull String fileName) throws IOException {
+ public final InputStream open(String fileName) throws IOException {
return open(fileName, ACCESS_STREAMING);
}
@@ -609,7 +353,8 @@
* with an application as assets -- that is, files placed in to the
* "assets" directory.
*
- * @param fileName The name of the asset to open. This name can be hierarchical.
+ * @param fileName The name of the asset to open. This name can be
+ * hierarchical.
* @param accessMode Desired access mode for retrieving the data.
*
* @see #ACCESS_UNKNOWN
@@ -619,40 +364,34 @@
* @see #open(String)
* @see #list
*/
- public @NonNull InputStream open(@NonNull String fileName, int accessMode) throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+ public final InputStream open(String fileName, int accessMode)
+ throws IOException {
synchronized (this) {
- ensureOpenLocked();
- final long asset = nativeOpenAsset(mObject, fileName, accessMode);
- if (asset == 0) {
- throw new FileNotFoundException("Asset file: " + fileName);
+ if (!mOpen) {
+ throw new RuntimeException("Assetmanager has been closed");
}
- final AssetInputStream assetInputStream = new AssetInputStream(asset);
- incRefsLocked(assetInputStream.hashCode());
- return assetInputStream;
+ long asset = openAsset(fileName, accessMode);
+ if (asset != 0) {
+ AssetInputStream res = new AssetInputStream(asset);
+ incRefsLocked(res.hashCode());
+ return res;
+ }
}
+ throw new FileNotFoundException("Asset file: " + fileName);
}
- /**
- * Open an uncompressed asset by mmapping it and returning an {@link AssetFileDescriptor}.
- * This provides access to files that have been bundled with an application as assets -- that
- * is, files placed in to the "assets" directory.
- *
- * The asset must be uncompressed, or an exception will be thrown.
- *
- * @param fileName The name of the asset to open. This name can be hierarchical.
- * @return An open AssetFileDescriptor.
- */
- public @NonNull AssetFileDescriptor openFd(@NonNull String fileName) throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+ public final AssetFileDescriptor openFd(String fileName)
+ throws IOException {
synchronized (this) {
- ensureOpenLocked();
- final ParcelFileDescriptor pfd = nativeOpenAssetFd(mObject, fileName, mOffsets);
- if (pfd == null) {
- throw new FileNotFoundException("Asset file: " + fileName);
+ if (!mOpen) {
+ throw new RuntimeException("Assetmanager has been closed");
}
- return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
+ ParcelFileDescriptor pfd = openAssetFd(fileName, mOffsets);
+ if (pfd != null) {
+ return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
+ }
}
+ throw new FileNotFoundException("Asset file: " + fileName);
}
/**
@@ -667,121 +406,90 @@
*
* @see #open
*/
- public @Nullable String[] list(@NonNull String path) throws IOException {
- Preconditions.checkNotNull(path, "path");
- synchronized (this) {
- ensureValidLocked();
- return nativeList(mObject, path);
- }
- }
+ public native final String[] list(String path)
+ throws IOException;
/**
+ * {@hide}
* Open a non-asset file as an asset using ACCESS_STREAMING mode. This
* provides direct access to all of the files included in an application
* package (not only its assets). Applications should not normally use
* this.
- *
- * @param fileName Name of the asset to retrieve.
- *
+ *
* @see #open(String)
- * @hide
*/
- public @NonNull InputStream openNonAsset(@NonNull String fileName) throws IOException {
+ public final InputStream openNonAsset(String fileName) throws IOException {
return openNonAsset(0, fileName, ACCESS_STREAMING);
}
/**
+ * {@hide}
* Open a non-asset file as an asset using a specific access mode. This
* provides direct access to all of the files included in an application
* package (not only its assets). Applications should not normally use
* this.
- *
- * @param fileName Name of the asset to retrieve.
- * @param accessMode Desired access mode for retrieving the data.
- *
- * @see #ACCESS_UNKNOWN
- * @see #ACCESS_STREAMING
- * @see #ACCESS_RANDOM
- * @see #ACCESS_BUFFER
+ *
* @see #open(String, int)
- * @hide
*/
- public @NonNull InputStream openNonAsset(@NonNull String fileName, int accessMode)
- throws IOException {
+ public final InputStream openNonAsset(String fileName, int accessMode)
+ throws IOException {
return openNonAsset(0, fileName, accessMode);
}
/**
+ * {@hide}
* Open a non-asset in a specified package. Not for use by applications.
- *
+ *
* @param cookie Identifier of the package to be opened.
* @param fileName Name of the asset to retrieve.
- * @hide
*/
- public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName)
- throws IOException {
+ public final InputStream openNonAsset(int cookie, String fileName)
+ throws IOException {
return openNonAsset(cookie, fileName, ACCESS_STREAMING);
}
/**
+ * {@hide}
* Open a non-asset in a specified package. Not for use by applications.
- *
+ *
* @param cookie Identifier of the package to be opened.
* @param fileName Name of the asset to retrieve.
* @param accessMode Desired access mode for retrieving the data.
- * @hide
*/
- public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName, int accessMode)
- throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+ public final InputStream openNonAsset(int cookie, String fileName, int accessMode)
+ throws IOException {
synchronized (this) {
- ensureOpenLocked();
- final long asset = nativeOpenNonAsset(mObject, cookie, fileName, accessMode);
- if (asset == 0) {
- throw new FileNotFoundException("Asset absolute file: " + fileName);
+ if (!mOpen) {
+ throw new RuntimeException("Assetmanager has been closed");
}
- final AssetInputStream assetInputStream = new AssetInputStream(asset);
- incRefsLocked(assetInputStream.hashCode());
- return assetInputStream;
+ long asset = openNonAssetNative(cookie, fileName, accessMode);
+ if (asset != 0) {
+ AssetInputStream res = new AssetInputStream(asset);
+ incRefsLocked(res.hashCode());
+ return res;
+ }
}
+ throw new FileNotFoundException("Asset absolute file: " + fileName);
}
- /**
- * Open a non-asset as an asset by mmapping it and returning an {@link AssetFileDescriptor}.
- * This provides direct access to all of the files included in an application
- * package (not only its assets). Applications should not normally use this.
- *
- * The asset must not be compressed, or an exception will be thrown.
- *
- * @param fileName Name of the asset to retrieve.
- */
- public @NonNull AssetFileDescriptor openNonAssetFd(@NonNull String fileName)
+ public final AssetFileDescriptor openNonAssetFd(String fileName)
throws IOException {
return openNonAssetFd(0, fileName);
}
-
- /**
- * Open a non-asset as an asset by mmapping it and returning an {@link AssetFileDescriptor}.
- * This provides direct access to all of the files included in an application
- * package (not only its assets). Applications should not normally use this.
- *
- * The asset must not be compressed, or an exception will be thrown.
- *
- * @param cookie Identifier of the package to be opened.
- * @param fileName Name of the asset to retrieve.
- */
- public @NonNull AssetFileDescriptor openNonAssetFd(int cookie, @NonNull String fileName)
- throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+
+ public final AssetFileDescriptor openNonAssetFd(int cookie,
+ String fileName) throws IOException {
synchronized (this) {
- ensureOpenLocked();
- final ParcelFileDescriptor pfd =
- nativeOpenNonAssetFd(mObject, cookie, fileName, mOffsets);
- if (pfd == null) {
- throw new FileNotFoundException("Asset absolute file: " + fileName);
+ if (!mOpen) {
+ throw new RuntimeException("Assetmanager has been closed");
}
- return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
+ ParcelFileDescriptor pfd = openNonAssetFdNative(cookie,
+ fileName, mOffsets);
+ if (pfd != null) {
+ return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
+ }
}
+ throw new FileNotFoundException("Asset absolute file: " + fileName);
}
/**
@@ -789,7 +497,7 @@
*
* @param fileName The name of the file to retrieve.
*/
- public @NonNull XmlResourceParser openXmlResourceParser(@NonNull String fileName)
+ public final XmlResourceParser openXmlResourceParser(String fileName)
throws IOException {
return openXmlResourceParser(0, fileName);
}
@@ -800,265 +508,270 @@
* @param cookie Identifier of the package to be opened.
* @param fileName The name of the file to retrieve.
*/
- public @NonNull XmlResourceParser openXmlResourceParser(int cookie, @NonNull String fileName)
- throws IOException {
- try (XmlBlock block = openXmlBlockAsset(cookie, fileName)) {
- XmlResourceParser parser = block.newParser();
- // If openXmlBlockAsset doesn't throw, it will always return an XmlBlock object with
- // a valid native pointer, which makes newParser always return non-null. But let's
- // be paranoid.
- if (parser == null) {
- throw new AssertionError("block.newParser() returned a null parser");
- }
- return parser;
- }
+ public final XmlResourceParser openXmlResourceParser(int cookie,
+ String fileName) throws IOException {
+ XmlBlock block = openXmlBlockAsset(cookie, fileName);
+ XmlResourceParser rp = block.newParser();
+ block.close();
+ return rp;
}
/**
- * Retrieve a non-asset as a compiled XML file. Not for use by applications.
+ * {@hide}
+ * Retrieve a non-asset as a compiled XML file. Not for use by
+ * applications.
*
* @param fileName The name of the file to retrieve.
- * @hide
*/
- @NonNull XmlBlock openXmlBlockAsset(@NonNull String fileName) throws IOException {
+ /*package*/ final XmlBlock openXmlBlockAsset(String fileName)
+ throws IOException {
return openXmlBlockAsset(0, fileName);
}
/**
+ * {@hide}
* Retrieve a non-asset as a compiled XML file. Not for use by
* applications.
*
* @param cookie Identifier of the package to be opened.
* @param fileName Name of the asset to retrieve.
- * @hide
*/
- @NonNull XmlBlock openXmlBlockAsset(int cookie, @NonNull String fileName) throws IOException {
- Preconditions.checkNotNull(fileName, "fileName");
+ /*package*/ final XmlBlock openXmlBlockAsset(int cookie, String fileName)
+ throws IOException {
synchronized (this) {
- ensureOpenLocked();
- final long xmlBlock = nativeOpenXmlAsset(mObject, cookie, fileName);
- if (xmlBlock == 0) {
- throw new FileNotFoundException("Asset XML file: " + fileName);
+ if (!mOpen) {
+ throw new RuntimeException("Assetmanager has been closed");
}
- final XmlBlock block = new XmlBlock(this, xmlBlock);
- incRefsLocked(block.hashCode());
- return block;
+ long xmlBlock = openXmlAssetNative(cookie, fileName);
+ if (xmlBlock != 0) {
+ XmlBlock res = new XmlBlock(this, xmlBlock);
+ incRefsLocked(res.hashCode());
+ return res;
+ }
}
+ throw new FileNotFoundException("Asset XML file: " + fileName);
}
- void xmlBlockGone(int id) {
+ /*package*/ void xmlBlockGone(int id) {
synchronized (this) {
decRefsLocked(id);
}
}
- void applyStyle(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
- @Nullable XmlBlock.Parser parser, @NonNull int[] inAttrs, long outValuesAddress,
- long outIndicesAddress) {
- Preconditions.checkNotNull(inAttrs, "inAttrs");
+ /*package*/ final long createTheme() {
synchronized (this) {
- // Need to synchronize on AssetManager because we will be accessing
- // the native implementation of AssetManager.
- ensureValidLocked();
- nativeApplyStyle(mObject, themePtr, defStyleAttr, defStyleRes,
- parser != null ? parser.mParseState : 0, inAttrs, outValuesAddress,
- outIndicesAddress);
+ if (!mOpen) {
+ throw new RuntimeException("Assetmanager has been closed");
+ }
+ long res = newTheme();
+ incRefsLocked(res);
+ return res;
}
}
- boolean resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
- @Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues,
- @NonNull int[] outIndices) {
- Preconditions.checkNotNull(inAttrs, "inAttrs");
- Preconditions.checkNotNull(outValues, "outValues");
- Preconditions.checkNotNull(outIndices, "outIndices");
+ /*package*/ final void releaseTheme(long theme) {
synchronized (this) {
- // Need to synchronize on AssetManager because we will be accessing
- // the native implementation of AssetManager.
- ensureValidLocked();
- return nativeResolveAttrs(mObject,
- themePtr, defStyleAttr, defStyleRes, inValues, inAttrs, outValues, outIndices);
+ deleteTheme(theme);
+ decRefsLocked(theme);
}
}
- boolean retrieveAttributes(@NonNull XmlBlock.Parser parser, @NonNull int[] inAttrs,
- @NonNull int[] outValues, @NonNull int[] outIndices) {
- Preconditions.checkNotNull(parser, "parser");
- Preconditions.checkNotNull(inAttrs, "inAttrs");
- Preconditions.checkNotNull(outValues, "outValues");
- Preconditions.checkNotNull(outIndices, "outIndices");
- synchronized (this) {
- // Need to synchronize on AssetManager because we will be accessing
- // the native implementation of AssetManager.
- ensureValidLocked();
- return nativeRetrieveAttributes(
- mObject, parser.mParseState, inAttrs, outValues, outIndices);
- }
- }
-
- long createTheme() {
- synchronized (this) {
- ensureValidLocked();
- long themePtr = nativeThemeCreate(mObject);
- incRefsLocked(themePtr);
- return themePtr;
- }
- }
-
- void releaseTheme(long themePtr) {
- synchronized (this) {
- nativeThemeDestroy(themePtr);
- decRefsLocked(themePtr);
- }
- }
-
- void applyStyleToTheme(long themePtr, @StyleRes int resId, boolean force) {
- synchronized (this) {
- // Need to synchronize on AssetManager because we will be accessing
- // the native implementation of AssetManager.
- ensureValidLocked();
- nativeThemeApplyStyle(mObject, themePtr, resId, force);
- }
- }
-
- @Override
protected void finalize() throws Throwable {
- if (DEBUG_REFS && mNumRefs != 0) {
- Log.w(TAG, "AssetManager " + this + " finalized with non-zero refs: " + mNumRefs);
- if (mRefStacks != null) {
- for (RuntimeException e : mRefStacks.values()) {
- Log.w(TAG, "Reference from here", e);
+ try {
+ if (DEBUG_REFS && mNumRefs != 0) {
+ Log.w(TAG, "AssetManager " + this
+ + " finalized with non-zero refs: " + mNumRefs);
+ if (mRefStacks != null) {
+ for (RuntimeException e : mRefStacks.values()) {
+ Log.w(TAG, "Reference from here", e);
+ }
}
}
- }
-
- if (mObject != 0) {
- nativeDestroy(mObject);
+ destroy();
+ } finally {
+ super.finalize();
}
}
-
- /* No Locking is needed for AssetInputStream because an AssetInputStream is not-thread
- safe and it does not rely on AssetManager once it has been created. It completely owns the
- underlying Asset. */
+
public final class AssetInputStream extends InputStream {
- private long mAssetNativePtr;
- private long mLength;
- private long mMarkPos;
-
/**
* @hide
*/
public final int getAssetInt() {
throw new UnsupportedOperationException();
}
-
/**
* @hide
*/
public final long getNativeAsset() {
- return mAssetNativePtr;
+ return mAsset;
}
-
- private AssetInputStream(long assetNativePtr) {
- mAssetNativePtr = assetNativePtr;
- mLength = nativeAssetGetLength(assetNativePtr);
+ private AssetInputStream(long asset)
+ {
+ mAsset = asset;
+ mLength = getAssetLength(asset);
}
-
- @Override
public final int read() throws IOException {
- ensureOpen();
- return nativeAssetReadChar(mAssetNativePtr);
+ return readAssetChar(mAsset);
}
-
- @Override
- public final int read(@NonNull byte[] b) throws IOException {
- ensureOpen();
- Preconditions.checkNotNull(b, "b");
- return nativeAssetRead(mAssetNativePtr, b, 0, b.length);
- }
-
- @Override
- public final int read(@NonNull byte[] b, int off, int len) throws IOException {
- ensureOpen();
- Preconditions.checkNotNull(b, "b");
- return nativeAssetRead(mAssetNativePtr, b, off, len);
- }
-
- @Override
- public final long skip(long n) throws IOException {
- ensureOpen();
- long pos = nativeAssetSeek(mAssetNativePtr, 0, 0);
- if ((pos + n) > mLength) {
- n = mLength - pos;
- }
- if (n > 0) {
- nativeAssetSeek(mAssetNativePtr, n, 0);
- }
- return n;
- }
-
- @Override
- public final int available() throws IOException {
- ensureOpen();
- final long len = nativeAssetGetRemainingLength(mAssetNativePtr);
- return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) len;
- }
-
- @Override
public final boolean markSupported() {
return true;
}
-
- @Override
- public final void mark(int readlimit) {
- ensureOpen();
- mMarkPos = nativeAssetSeek(mAssetNativePtr, 0, 0);
+ public final int available() throws IOException {
+ long len = getAssetRemainingLength(mAsset);
+ return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)len;
}
-
- @Override
- public final void reset() throws IOException {
- ensureOpen();
- nativeAssetSeek(mAssetNativePtr, mMarkPos, -1);
- }
-
- @Override
public final void close() throws IOException {
- if (mAssetNativePtr != 0) {
- nativeAssetDestroy(mAssetNativePtr);
- mAssetNativePtr = 0;
-
- synchronized (AssetManager.this) {
+ synchronized (AssetManager.this) {
+ if (mAsset != 0) {
+ destroyAsset(mAsset);
+ mAsset = 0;
decRefsLocked(hashCode());
}
}
}
+ public final void mark(int readlimit) {
+ mMarkPos = seekAsset(mAsset, 0, 0);
+ }
+ public final void reset() throws IOException {
+ seekAsset(mAsset, mMarkPos, -1);
+ }
+ public final int read(byte[] b) throws IOException {
+ return readAsset(mAsset, b, 0, b.length);
+ }
+ public final int read(byte[] b, int off, int len) throws IOException {
+ return readAsset(mAsset, b, off, len);
+ }
+ public final long skip(long n) throws IOException {
+ long pos = seekAsset(mAsset, 0, 0);
+ if ((pos+n) > mLength) {
+ n = mLength-pos;
+ }
+ if (n > 0) {
+ seekAsset(mAsset, n, 0);
+ }
+ return n;
+ }
- @Override
- protected void finalize() throws Throwable {
+ protected void finalize() throws Throwable
+ {
close();
}
- private void ensureOpen() {
- if (mAssetNativePtr == 0) {
- throw new IllegalStateException("AssetInputStream is closed");
- }
+ private long mAsset;
+ private long mLength;
+ private long mMarkPos;
+ }
+
+ /**
+ * Add an additional set of assets to the asset manager. This can be
+ * either a directory or ZIP file. Not for use by applications. Returns
+ * the cookie of the added asset, or 0 on failure.
+ * {@hide}
+ */
+ public final int addAssetPath(String path) {
+ return addAssetPathInternal(path, false);
+ }
+
+ /**
+ * Add an application assets to the asset manager and loading it as shared library.
+ * This can be either a directory or ZIP file. Not for use by applications. Returns
+ * the cookie of the added asset, or 0 on failure.
+ * {@hide}
+ */
+ public final int addAssetPathAsSharedLibrary(String path) {
+ return addAssetPathInternal(path, true);
+ }
+
+ private final int addAssetPathInternal(String path, boolean appAsLib) {
+ synchronized (this) {
+ int res = addAssetPathNative(path, appAsLib);
+ makeStringBlocks(mStringBlocks);
+ return res;
}
}
+ private native final int addAssetPathNative(String path, boolean appAsLib);
+
+ /**
+ * Add an additional set of assets to the asset manager from an already open
+ * FileDescriptor. Not for use by applications.
+ * This does not give full AssetManager functionality for these assets,
+ * since the origin of the file is not known for purposes of sharing,
+ * overlay resolution, and other features. However it does allow you
+ * to do simple access to the contents of the given fd as an apk file.
+ * Performs a dup of the underlying fd, so you must take care of still closing
+ * the FileDescriptor yourself (and can do that whenever you want).
+ * Returns the cookie of the added asset, or 0 on failure.
+ * {@hide}
+ */
+ public int addAssetFd(FileDescriptor fd, String debugPathName) {
+ return addAssetFdInternal(fd, debugPathName, false);
+ }
+
+ private int addAssetFdInternal(FileDescriptor fd, String debugPathName,
+ boolean appAsLib) {
+ synchronized (this) {
+ int res = addAssetFdNative(fd, debugPathName, appAsLib);
+ makeStringBlocks(mStringBlocks);
+ return res;
+ }
+ }
+
+ private native int addAssetFdNative(FileDescriptor fd, String debugPathName,
+ boolean appAsLib);
+
+ /**
+ * Add a set of assets to overlay an already added set of assets.
+ *
+ * This is only intended for application resources. System wide resources
+ * are handled before any Java code is executed.
+ *
+ * {@hide}
+ */
+
+ public final int addOverlayPath(String idmapPath) {
+ synchronized (this) {
+ int res = addOverlayPathNative(idmapPath);
+ makeStringBlocks(mStringBlocks);
+ return res;
+ }
+ }
+
+ /**
+ * See addOverlayPath.
+ *
+ * {@hide}
+ */
+ public native final int addOverlayPathNative(String idmapPath);
+
+ /**
+ * Add multiple sets of assets to the asset manager at once. See
+ * {@link #addAssetPath(String)} for more information. Returns array of
+ * cookies for each added asset with 0 indicating failure, or null if
+ * the input array of paths is null.
+ * {@hide}
+ */
+ public final int[] addAssetPaths(String[] paths) {
+ if (paths == null) {
+ return null;
+ }
+
+ int[] cookies = new int[paths.length];
+ for (int i = 0; i < paths.length; i++) {
+ cookies[i] = addAssetPath(paths[i]);
+ }
+
+ return cookies;
+ }
+
/**
* Determine whether the state in this asset manager is up-to-date with
* the files on the filesystem. If false is returned, you need to
* instantiate a new AssetManager class to see the new data.
- * @hide
+ * {@hide}
*/
- public boolean isUpToDate() {
- for (ApkAssets apkAssets : getApkAssets()) {
- if (!apkAssets.isUpToDate()) {
- return false;
- }
- }
- return true;
- }
+ public native final boolean isUpToDate();
/**
* Get the locales that this asset manager contains data for.
@@ -1071,12 +784,7 @@
* are of the form {@code ll_CC} where {@code ll} is a two letter language code,
* and {@code CC} is a two letter country code.
*/
- public String[] getLocales() {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetLocales(mObject, false /*excludeSystem*/);
- }
- }
+ public native final String[] getLocales();
/**
* Same as getLocales(), except that locales that are only provided by the system (i.e. those
@@ -1086,57 +794,131 @@
* assets support Cherokee and French, getLocales() would return
* [Cherokee, English, French, German], while getNonSystemLocales() would return
* [Cherokee, French].
- * @hide
+ * {@hide}
*/
- public String[] getNonSystemLocales() {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetLocales(mObject, true /*excludeSystem*/);
- }
- }
+ public native final String[] getNonSystemLocales();
+
+ /** {@hide} */
+ public native final Configuration[] getSizeConfigurations();
/**
- * @hide
- */
- Configuration[] getSizeConfigurations() {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetSizeConfigurations(mObject);
- }
- }
-
- /**
- * Change the configuration used when retrieving resources. Not for use by
+ * Change the configuation used when retrieving resources. Not for use by
* applications.
- * @hide
+ * {@hide}
*/
- public void setConfiguration(int mcc, int mnc, @Nullable String locale, int orientation,
- int touchscreen, int density, int keyboard, int keyboardHidden, int navigation,
- int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp,
- int screenHeightDp, int screenLayout, int uiMode, int colorMode, int majorVersion) {
- synchronized (this) {
- ensureValidLocked();
- nativeSetConfiguration(mObject, mcc, mnc, locale, orientation, touchscreen, density,
- keyboard, keyboardHidden, navigation, screenWidth, screenHeight,
- smallestScreenWidthDp, screenWidthDp, screenHeightDp, screenLayout, uiMode,
- colorMode, majorVersion);
- }
- }
+ public native final void setConfiguration(int mcc, int mnc, String locale,
+ int orientation, int touchscreen, int density, int keyboard,
+ int keyboardHidden, int navigation, int screenWidth, int screenHeight,
+ int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp,
+ int screenLayout, int uiMode, int colorMode, int majorVersion);
/**
- * @hide
+ * Retrieve the resource identifier for the given resource name.
*/
- public SparseArray<String> getAssignedPackageIdentifiers() {
- synchronized (this) {
- ensureValidLocked();
- return nativeGetAssignedPackageIdentifiers(mObject);
- }
- }
+ /*package*/ native final int getResourceIdentifier(String name,
+ String defType,
+ String defPackage);
- private void incRefsLocked(long id) {
+ /*package*/ native final String getResourceName(int resid);
+ /*package*/ native final String getResourcePackageName(int resid);
+ /*package*/ native final String getResourceTypeName(int resid);
+ /*package*/ native final String getResourceEntryName(int resid);
+
+ private native final long openAsset(String fileName, int accessMode);
+ private final native ParcelFileDescriptor openAssetFd(String fileName,
+ long[] outOffsets) throws IOException;
+ private native final long openNonAssetNative(int cookie, String fileName,
+ int accessMode);
+ private native ParcelFileDescriptor openNonAssetFdNative(int cookie,
+ String fileName, long[] outOffsets) throws IOException;
+ private native final void destroyAsset(long asset);
+ private native final int readAssetChar(long asset);
+ private native final int readAsset(long asset, byte[] b, int off, int len);
+ private native final long seekAsset(long asset, long offset, int whence);
+ private native final long getAssetLength(long asset);
+ private native final long getAssetRemainingLength(long asset);
+
+ /** Returns true if the resource was found, filling in mRetStringBlock and
+ * mRetData. */
+ private native final int loadResourceValue(int ident, short density, TypedValue outValue,
+ boolean resolve);
+ /** Returns true if the resource was found, filling in mRetStringBlock and
+ * mRetData. */
+ private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
+ boolean resolve);
+ /*package*/ static final int STYLE_NUM_ENTRIES = 6;
+ /*package*/ static final int STYLE_TYPE = 0;
+ /*package*/ static final int STYLE_DATA = 1;
+ /*package*/ static final int STYLE_ASSET_COOKIE = 2;
+ /*package*/ static final int STYLE_RESOURCE_ID = 3;
+
+ /* Offset within typed data array for native changingConfigurations. */
+ static final int STYLE_CHANGING_CONFIGURATIONS = 4;
+
+ /*package*/ static final int STYLE_DENSITY = 5;
+ /*package*/ native static final void applyStyle(long theme,
+ int defStyleAttr, int defStyleRes, long xmlParser,
+ int[] inAttrs, int length, long outValuesAddress, long outIndicesAddress);
+ /*package*/ native static final boolean resolveAttrs(long theme,
+ int defStyleAttr, int defStyleRes, int[] inValues,
+ int[] inAttrs, int[] outValues, int[] outIndices);
+ /*package*/ native final boolean retrieveAttributes(
+ long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices);
+ /*package*/ native final int getArraySize(int resource);
+ /*package*/ native final int retrieveArray(int resource, int[] outValues);
+ private native final int getStringBlockCount();
+ private native final long getNativeStringBlock(int block);
+
+ /**
+ * {@hide}
+ */
+ public native final String getCookieName(int cookie);
+
+ /**
+ * {@hide}
+ */
+ public native final SparseArray<String> getAssignedPackageIdentifiers();
+
+ /**
+ * {@hide}
+ */
+ public native static final int getGlobalAssetCount();
+
+ /**
+ * {@hide}
+ */
+ public native static final String getAssetAllocations();
+
+ /**
+ * {@hide}
+ */
+ public native static final int getGlobalAssetManagerCount();
+
+ private native final long newTheme();
+ private native final void deleteTheme(long theme);
+ /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force);
+ /*package*/ native static final void copyTheme(long dest, long source);
+ /*package*/ native static final void clearTheme(long theme);
+ /*package*/ native static final int loadThemeAttributeValue(long theme, int ident,
+ TypedValue outValue,
+ boolean resolve);
+ /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix);
+ /*package*/ native static final @NativeConfig int getThemeChangingConfigurations(long theme);
+
+ private native final long openXmlAssetNative(int cookie, String fileName);
+
+ private native final String[] getArrayStringResource(int arrayRes);
+ private native final int[] getArrayStringInfo(int arrayRes);
+ /*package*/ native final int[] getArrayIntResource(int arrayRes);
+ /*package*/ native final int[] getStyleAttributes(int themeRes);
+
+ private native final void init(boolean isSystem);
+ private native final void destroy();
+
+ private final void incRefsLocked(long id) {
if (DEBUG_REFS) {
if (mRefStacks == null) {
- mRefStacks = new HashMap<>();
+ mRefStacks = new HashMap<Long, RuntimeException>();
}
RuntimeException ex = new RuntimeException();
ex.fillInStackTrace();
@@ -1144,117 +926,16 @@
}
mNumRefs++;
}
-
- private void decRefsLocked(long id) {
+
+ private final void decRefsLocked(long id) {
if (DEBUG_REFS && mRefStacks != null) {
mRefStacks.remove(id);
}
mNumRefs--;
- if (mNumRefs == 0 && mObject != 0) {
- nativeDestroy(mObject);
- mObject = 0;
+ //System.out.println("Dec streams: mNumRefs=" + mNumRefs
+ // + " mReleased=" + mReleased);
+ if (mNumRefs == 0) {
+ destroy();
}
}
-
- // AssetManager setup native methods.
- private static native long nativeCreate();
- private static native void nativeDestroy(long ptr);
- private static native void nativeSetApkAssets(long ptr, @NonNull ApkAssets[] apkAssets,
- boolean invalidateCaches);
- private static native void nativeSetConfiguration(long ptr, int mcc, int mnc,
- @Nullable String locale, int orientation, int touchscreen, int density, int keyboard,
- int keyboardHidden, int navigation, int screenWidth, int screenHeight,
- int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout,
- int uiMode, int colorMode, int majorVersion);
- private static native @NonNull SparseArray<String> nativeGetAssignedPackageIdentifiers(
- long ptr);
-
- // File native methods.
- private static native @Nullable String[] nativeList(long ptr, @NonNull String path)
- throws IOException;
- private static native long nativeOpenAsset(long ptr, @NonNull String fileName, int accessMode);
- private static native @Nullable ParcelFileDescriptor nativeOpenAssetFd(long ptr,
- @NonNull String fileName, long[] outOffsets) throws IOException;
- private static native long nativeOpenNonAsset(long ptr, int cookie, @NonNull String fileName,
- int accessMode);
- private static native @Nullable ParcelFileDescriptor nativeOpenNonAssetFd(long ptr, int cookie,
- @NonNull String fileName, @NonNull long[] outOffsets) throws IOException;
- private static native long nativeOpenXmlAsset(long ptr, int cookie, @NonNull String fileName);
-
- // Primitive resource native methods.
- private static native int nativeGetResourceValue(long ptr, @AnyRes int resId, short density,
- @NonNull TypedValue outValue, boolean resolveReferences);
- private static native int nativeGetResourceBagValue(long ptr, @AnyRes int resId, int bagEntryId,
- @NonNull TypedValue outValue);
-
- private static native @Nullable @AttrRes int[] nativeGetStyleAttributes(long ptr,
- @StyleRes int resId);
- private static native @Nullable String[] nativeGetResourceStringArray(long ptr,
- @ArrayRes int resId);
- private static native @Nullable int[] nativeGetResourceStringArrayInfo(long ptr,
- @ArrayRes int resId);
- private static native @Nullable int[] nativeGetResourceIntArray(long ptr, @ArrayRes int resId);
- private static native int nativeGetResourceArraySize(long ptr, @ArrayRes int resId);
- private static native int nativeGetResourceArray(long ptr, @ArrayRes int resId,
- @NonNull int[] outValues);
-
- // Resource name/ID native methods.
- private static native @AnyRes int nativeGetResourceIdentifier(long ptr, @NonNull String name,
- @Nullable String defType, @Nullable String defPackage);
- private static native @Nullable String nativeGetResourceName(long ptr, @AnyRes int resid);
- private static native @Nullable String nativeGetResourcePackageName(long ptr,
- @AnyRes int resid);
- private static native @Nullable String nativeGetResourceTypeName(long ptr, @AnyRes int resid);
- private static native @Nullable String nativeGetResourceEntryName(long ptr, @AnyRes int resid);
- private static native @Nullable String[] nativeGetLocales(long ptr, boolean excludeSystem);
- private static native @Nullable Configuration[] nativeGetSizeConfigurations(long ptr);
-
- // Style attribute retrieval native methods.
- private static native void nativeApplyStyle(long ptr, long themePtr, @AttrRes int defStyleAttr,
- @StyleRes int defStyleRes, long xmlParserPtr, @NonNull int[] inAttrs,
- long outValuesAddress, long outIndicesAddress);
- private static native boolean nativeResolveAttrs(long ptr, long themePtr,
- @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @Nullable int[] inValues,
- @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices);
- private static native boolean nativeRetrieveAttributes(long ptr, long xmlParserPtr,
- @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices);
-
- // Theme related native methods
- private static native long nativeThemeCreate(long ptr);
- private static native void nativeThemeDestroy(long themePtr);
- private static native void nativeThemeApplyStyle(long ptr, long themePtr, @StyleRes int resId,
- boolean force);
- static native void nativeThemeCopy(long destThemePtr, long sourceThemePtr);
- static native void nativeThemeClear(long themePtr);
- private static native int nativeThemeGetAttributeValue(long ptr, long themePtr,
- @AttrRes int resId, @NonNull TypedValue outValue, boolean resolve);
- private static native void nativeThemeDump(long ptr, long themePtr, int priority, String tag,
- String prefix);
- static native @NativeConfig int nativeThemeGetChangingConfigurations(long themePtr);
-
- // AssetInputStream related native methods.
- private static native void nativeAssetDestroy(long assetPtr);
- private static native int nativeAssetReadChar(long assetPtr);
- private static native int nativeAssetRead(long assetPtr, byte[] b, int off, int len);
- private static native long nativeAssetSeek(long assetPtr, long offset, int whence);
- private static native long nativeAssetGetLength(long assetPtr);
- private static native long nativeAssetGetRemainingLength(long assetPtr);
-
- private static native void nativeVerifySystemIdmaps();
-
- // Global debug native methods.
- /**
- * @hide
- */
- public static native int getGlobalAssetCount();
-
- /**
- * @hide
- */
- public static native String getAssetAllocations();
-
- /**
- * @hide
- */
- public static native int getGlobalAssetManagerCount();
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 8f58891..e173653c 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -590,7 +590,7 @@
*/
@NonNull
public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
- int[] res = mResourcesImpl.getAssets().getResourceIntArray(id);
+ int[] res = mResourcesImpl.getAssets().getArrayIntResource(id);
if (res != null) {
return res;
}
@@ -613,13 +613,13 @@
@NonNull
public TypedArray obtainTypedArray(@ArrayRes int id) throws NotFoundException {
final ResourcesImpl impl = mResourcesImpl;
- int len = impl.getAssets().getResourceArraySize(id);
+ int len = impl.getAssets().getArraySize(id);
if (len < 0) {
throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id));
}
TypedArray array = TypedArray.obtain(this, len);
- array.mLength = impl.getAssets().getResourceArray(id, array.mData);
+ array.mLength = impl.getAssets().retrieveArray(id, array.mData);
array.mIndices[0] = 0;
return array;
@@ -1789,7 +1789,8 @@
// out the attributes from the XML file (applying type information
// contained in the resources and such).
XmlBlock.Parser parser = (XmlBlock.Parser)set;
- mResourcesImpl.getAssets().retrieveAttributes(parser, attrs, array.mData, array.mIndices);
+ mResourcesImpl.getAssets().retrieveAttributes(parser.mParseState, attrs,
+ array.mData, array.mIndices);
array.mXml = parser;
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 2a4b278..97cb78b 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -168,6 +168,7 @@
mDisplayAdjustments = displayAdjustments;
mConfiguration.setToDefaults();
updateConfiguration(config, metrics, displayAdjustments.getCompatibilityInfo());
+ mAssets.ensureStringBlocks();
}
public DisplayAdjustments getDisplayAdjustments() {
@@ -1273,7 +1274,8 @@
void applyStyle(int resId, boolean force) {
synchronized (mKey) {
- mAssets.applyStyleToTheme(mTheme, resId, force);
+ AssetManager.applyThemeStyle(mTheme, resId, force);
+
mThemeResId = resId;
mKey.append(resId, force);
}
@@ -1282,7 +1284,7 @@
void setTo(ThemeImpl other) {
synchronized (mKey) {
synchronized (other.mKey) {
- AssetManager.nativeThemeCopy(mTheme, other.mTheme);
+ AssetManager.copyTheme(mTheme, other.mTheme);
mThemeResId = other.mThemeResId;
mKey.setTo(other.getKey());
@@ -1305,10 +1307,12 @@
// out the attributes from the XML file (applying type information
// contained in the resources and such).
final XmlBlock.Parser parser = (XmlBlock.Parser) set;
- mAssets.applyStyle(mTheme, defStyleAttr, defStyleRes, parser, attrs,
- array.mDataAddress, array.mIndicesAddress);
+ AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
+ parser != null ? parser.mParseState : 0,
+ attrs, attrs.length, array.mDataAddress, array.mIndicesAddress);
array.mTheme = wrapper;
array.mXml = parser;
+
return array;
}
}
@@ -1325,7 +1329,7 @@
}
final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
- mAssets.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
+ AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
array.mTheme = wrapper;
array.mXml = null;
return array;
@@ -1345,14 +1349,14 @@
@Config int getChangingConfigurations() {
synchronized (mKey) {
final @NativeConfig int nativeChangingConfig =
- AssetManager.nativeThemeGetChangingConfigurations(mTheme);
+ AssetManager.getThemeChangingConfigurations(mTheme);
return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
}
}
public void dump(int priority, String tag, String prefix) {
synchronized (mKey) {
- mAssets.dumpTheme(mTheme, priority, tag, prefix);
+ AssetManager.dumpTheme(mTheme, priority, tag, prefix);
}
}
@@ -1381,13 +1385,13 @@
*/
void rebase() {
synchronized (mKey) {
- AssetManager.nativeThemeClear(mTheme);
+ AssetManager.clearTheme(mTheme);
// Reapply the same styles in the same order.
for (int i = 0; i < mKey.mCount; i++) {
final int resId = mKey.mResId[i];
final boolean force = mKey.mForce[i];
- mAssets.applyStyleToTheme(mTheme, resId, force);
+ AssetManager.applyThemeStyle(mTheme, resId, force);
}
}
}
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index cbb3c6d..f33c751 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -61,15 +61,6 @@
return attrs;
}
- // STYLE_ prefixed constants are offsets within the typed data array.
- static final int STYLE_NUM_ENTRIES = 6;
- static final int STYLE_TYPE = 0;
- static final int STYLE_DATA = 1;
- static final int STYLE_ASSET_COOKIE = 2;
- static final int STYLE_RESOURCE_ID = 3;
- static final int STYLE_CHANGING_CONFIGURATIONS = 4;
- static final int STYLE_DENSITY = 5;
-
private final Resources mResources;
private DisplayMetrics mMetrics;
private AssetManager mAssets;
@@ -87,7 +78,7 @@
private void resize(int len) {
mLength = len;
- final int dataLen = len * STYLE_NUM_ENTRIES;
+ final int dataLen = len * AssetManager.STYLE_NUM_ENTRIES;
final int indicesLen = len + 1;
final VMRuntime runtime = VMRuntime.getRuntime();
if (mDataAddress == 0 || mData.length < dataLen) {
@@ -175,9 +166,9 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return null;
} else if (type == TypedValue.TYPE_STRING) {
@@ -212,9 +203,9 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return null;
} else if (type == TypedValue.TYPE_STRING) {
@@ -251,13 +242,14 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_STRING) {
- final int cookie = data[index + STYLE_ASSET_COOKIE];
+ final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
if (cookie < 0) {
- return mXml.getPooledString(data[index + STYLE_DATA]).toString();
+ return mXml.getPooledString(
+ data[index+AssetManager.STYLE_DATA]).toString();
}
}
return null;
@@ -282,11 +274,11 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
final @Config int changingConfigs = ActivityInfo.activityInfoConfigNativeToJava(
- data[index + STYLE_CHANGING_CONFIGURATIONS]);
+ data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
if ((changingConfigs & ~allowedChangingConfigs) != 0) {
return null;
}
@@ -328,14 +320,14 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return defValue;
} else if (type >= TypedValue.TYPE_FIRST_INT
&& type <= TypedValue.TYPE_LAST_INT) {
- return data[index + STYLE_DATA] != 0;
+ return data[index+AssetManager.STYLE_DATA] != 0;
}
final TypedValue v = mValue;
@@ -367,14 +359,14 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return defValue;
} else if (type >= TypedValue.TYPE_FIRST_INT
&& type <= TypedValue.TYPE_LAST_INT) {
- return data[index + STYLE_DATA];
+ return data[index+AssetManager.STYLE_DATA];
}
final TypedValue v = mValue;
@@ -404,16 +396,16 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return defValue;
} else if (type == TypedValue.TYPE_FLOAT) {
- return Float.intBitsToFloat(data[index + STYLE_DATA]);
+ return Float.intBitsToFloat(data[index+AssetManager.STYLE_DATA]);
} else if (type >= TypedValue.TYPE_FIRST_INT
&& type <= TypedValue.TYPE_LAST_INT) {
- return data[index + STYLE_DATA];
+ return data[index+AssetManager.STYLE_DATA];
}
final TypedValue v = mValue;
@@ -454,15 +446,15 @@
}
final int attrIndex = index;
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return defValue;
} else if (type >= TypedValue.TYPE_FIRST_INT
&& type <= TypedValue.TYPE_LAST_INT) {
- return data[index + STYLE_DATA];
+ return data[index+AssetManager.STYLE_DATA];
} else if (type == TypedValue.TYPE_STRING) {
final TypedValue value = mValue;
if (getValueAt(index, value)) {
@@ -506,7 +498,7 @@
}
final TypedValue value = mValue;
- if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+ if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
if (value.type == TypedValue.TYPE_ATTRIBUTE) {
throw new UnsupportedOperationException(
"Failed to resolve attribute at index " + index + ": " + value);
@@ -541,7 +533,7 @@
}
final TypedValue value = mValue;
- if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+ if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
if (value.type == TypedValue.TYPE_ATTRIBUTE) {
throw new UnsupportedOperationException(
"Failed to resolve attribute at index " + index + ": " + value);
@@ -572,15 +564,15 @@
}
final int attrIndex = index;
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return defValue;
} else if (type >= TypedValue.TYPE_FIRST_INT
&& type <= TypedValue.TYPE_LAST_INT) {
- return data[index + STYLE_DATA];
+ return data[index+AssetManager.STYLE_DATA];
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
getValueAt(index, value);
@@ -620,14 +612,15 @@
}
final int attrIndex = index;
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return defValue;
} else if (type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimension(data[index + STYLE_DATA], mMetrics);
+ return TypedValue.complexToDimension(
+ data[index + AssetManager.STYLE_DATA], mMetrics);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
getValueAt(index, value);
@@ -668,14 +661,15 @@
}
final int attrIndex = index;
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return defValue;
} else if (type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelOffset(data[index + STYLE_DATA], mMetrics);
+ return TypedValue.complexToDimensionPixelOffset(
+ data[index + AssetManager.STYLE_DATA], mMetrics);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
getValueAt(index, value);
@@ -717,14 +711,15 @@
}
final int attrIndex = index;
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return defValue;
} else if (type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
+ return TypedValue.complexToDimensionPixelSize(
+ data[index+AssetManager.STYLE_DATA], mMetrics);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
getValueAt(index, value);
@@ -760,15 +755,16 @@
}
final int attrIndex = index;
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type >= TypedValue.TYPE_FIRST_INT
&& type <= TypedValue.TYPE_LAST_INT) {
- return data[index + STYLE_DATA];
+ return data[index+AssetManager.STYLE_DATA];
} else if (type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
+ return TypedValue.complexToDimensionPixelSize(
+ data[index+AssetManager.STYLE_DATA], mMetrics);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
getValueAt(index, value);
@@ -799,14 +795,15 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type >= TypedValue.TYPE_FIRST_INT
&& type <= TypedValue.TYPE_LAST_INT) {
- return data[index + STYLE_DATA];
+ return data[index+AssetManager.STYLE_DATA];
} else if (type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
+ return TypedValue.complexToDimensionPixelSize(
+ data[index + AssetManager.STYLE_DATA], mMetrics);
}
return defValue;
@@ -836,14 +833,15 @@
}
final int attrIndex = index;
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return defValue;
} else if (type == TypedValue.TYPE_FRACTION) {
- return TypedValue.complexToFraction(data[index + STYLE_DATA], base, pbase);
+ return TypedValue.complexToFraction(
+ data[index+AssetManager.STYLE_DATA], base, pbase);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
getValueAt(index, value);
@@ -876,10 +874,10 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- if (data[index + STYLE_TYPE] != TypedValue.TYPE_NULL) {
- final int resid = data[index + STYLE_RESOURCE_ID];
+ if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) {
+ final int resid = data[index+AssetManager.STYLE_RESOURCE_ID];
if (resid != 0) {
return resid;
}
@@ -904,10 +902,10 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- if (data[index + STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
- return data[index + STYLE_DATA];
+ if (data[index + AssetManager.STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
+ return data[index + AssetManager.STYLE_DATA];
}
return defValue;
}
@@ -941,7 +939,7 @@
}
final TypedValue value = mValue;
- if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+ if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
if (value.type == TypedValue.TYPE_ATTRIBUTE) {
throw new UnsupportedOperationException(
"Failed to resolve attribute at index " + index + ": " + value);
@@ -977,7 +975,7 @@
}
final TypedValue value = mValue;
- if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+ if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
if (value.type == TypedValue.TYPE_ATTRIBUTE) {
throw new UnsupportedOperationException(
"Failed to resolve attribute at index " + index + ": " + value);
@@ -1008,7 +1006,7 @@
}
final TypedValue value = mValue;
- if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+ if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
return mResources.getTextArray(value.resourceId);
}
return null;
@@ -1029,7 +1027,7 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- return getValueAt(index * STYLE_NUM_ENTRIES, outValue);
+ return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
}
/**
@@ -1045,8 +1043,8 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
- return mData[index + STYLE_TYPE];
+ index *= AssetManager.STYLE_NUM_ENTRIES;
+ return mData[index + AssetManager.STYLE_TYPE];
}
/**
@@ -1065,9 +1063,9 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
return type != TypedValue.TYPE_NULL;
}
@@ -1086,11 +1084,11 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- index *= STYLE_NUM_ENTRIES;
+ index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
return type != TypedValue.TYPE_NULL
- || data[index + STYLE_DATA] == TypedValue.DATA_NULL_EMPTY;
+ || data[index+AssetManager.STYLE_DATA] == TypedValue.DATA_NULL_EMPTY;
}
/**
@@ -1111,7 +1109,7 @@
}
final TypedValue value = mValue;
- if (getValueAt(index * STYLE_NUM_ENTRIES, value)) {
+ if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
return value;
}
return null;
@@ -1183,16 +1181,16 @@
final int[] data = mData;
final int N = length();
for (int i = 0; i < N; i++) {
- final int index = i * STYLE_NUM_ENTRIES;
- if (data[index + STYLE_TYPE] != TypedValue.TYPE_ATTRIBUTE) {
+ final int index = i * AssetManager.STYLE_NUM_ENTRIES;
+ if (data[index + AssetManager.STYLE_TYPE] != TypedValue.TYPE_ATTRIBUTE) {
// Not an attribute, ignore.
continue;
}
// Null the entry so that we can safely call getZzz().
- data[index + STYLE_TYPE] = TypedValue.TYPE_NULL;
+ data[index + AssetManager.STYLE_TYPE] = TypedValue.TYPE_NULL;
- final int attr = data[index + STYLE_DATA];
+ final int attr = data[index + AssetManager.STYLE_DATA];
if (attr == 0) {
// Useless data, ignore.
continue;
@@ -1233,44 +1231,45 @@
final int[] data = mData;
final int N = length();
for (int i = 0; i < N; i++) {
- final int index = i * STYLE_NUM_ENTRIES;
- final int type = data[index + STYLE_TYPE];
+ final int index = i * AssetManager.STYLE_NUM_ENTRIES;
+ final int type = data[index + AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
continue;
}
changingConfig |= ActivityInfo.activityInfoConfigNativeToJava(
- data[index + STYLE_CHANGING_CONFIGURATIONS]);
+ data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
}
return changingConfig;
}
private boolean getValueAt(int index, TypedValue outValue) {
final int[] data = mData;
- final int type = data[index + STYLE_TYPE];
+ final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return false;
}
outValue.type = type;
- outValue.data = data[index + STYLE_DATA];
- outValue.assetCookie = data[index + STYLE_ASSET_COOKIE];
- outValue.resourceId = data[index + STYLE_RESOURCE_ID];
+ outValue.data = data[index+AssetManager.STYLE_DATA];
+ outValue.assetCookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
+ outValue.resourceId = data[index+AssetManager.STYLE_RESOURCE_ID];
outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
- data[index + STYLE_CHANGING_CONFIGURATIONS]);
- outValue.density = data[index + STYLE_DENSITY];
+ data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
+ outValue.density = data[index+AssetManager.STYLE_DENSITY];
outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null;
return true;
}
private CharSequence loadStringValueAt(int index) {
final int[] data = mData;
- final int cookie = data[index + STYLE_ASSET_COOKIE];
+ final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
if (cookie < 0) {
if (mXml != null) {
- return mXml.getPooledString(data[index + STYLE_DATA]);
+ return mXml.getPooledString(
+ data[index+AssetManager.STYLE_DATA]);
}
return null;
}
- return mAssets.getPooledStringForCookie(cookie, data[index + STYLE_DATA]);
+ return mAssets.getPooledStringForCookie(cookie, data[index+AssetManager.STYLE_DATA]);
}
/** @hide */
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index d4ccffb..e6b95741 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -16,7 +16,6 @@
package android.content.res;
-import android.annotation.Nullable;
import android.util.TypedValue;
import com.android.internal.util.XmlUtils;
@@ -34,7 +33,7 @@
*
* {@hide}
*/
-final class XmlBlock implements AutoCloseable {
+final class XmlBlock {
private static final boolean DEBUG=false;
public XmlBlock(byte[] data) {
@@ -49,7 +48,6 @@
mStrings = new StringBlock(nativeGetStringBlock(mNative), false);
}
- @Override
public void close() {
synchronized (this) {
if (mOpen) {
@@ -480,13 +478,13 @@
* are doing! The given native object must exist for the entire lifetime
* of this newly creating XmlBlock.
*/
- XmlBlock(@Nullable AssetManager assets, long xmlBlock) {
+ XmlBlock(AssetManager assets, long xmlBlock) {
mAssets = assets;
mNative = xmlBlock;
mStrings = new StringBlock(nativeGetStringBlock(xmlBlock), false);
}
- private @Nullable final AssetManager mAssets;
+ private final AssetManager mAssets;
private final long mNative;
/*package*/ final StringBlock mStrings;
private boolean mOpen = true;
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index f84ec65..a748f4d 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -28,6 +28,7 @@
import android.util.LongSparseArray;
import android.util.SparseIntArray;
+import dalvik.annotation.optimization.FastNative;
import dalvik.system.CloseGuard;
/**
@@ -62,28 +63,43 @@
private static native void nativeDispose(long windowPtr);
private static native void nativeWriteToParcel(long windowPtr, Parcel parcel);
- private static native void nativeClear(long windowPtr);
-
- private static native int nativeGetNumRows(long windowPtr);
- private static native boolean nativeSetNumColumns(long windowPtr, int columnNum);
- private static native boolean nativeAllocRow(long windowPtr);
- private static native void nativeFreeLastRow(long windowPtr);
-
- private static native int nativeGetType(long windowPtr, int row, int column);
+ private static native String nativeGetName(long windowPtr);
private static native byte[] nativeGetBlob(long windowPtr, int row, int column);
private static native String nativeGetString(long windowPtr, int row, int column);
- private static native long nativeGetLong(long windowPtr, int row, int column);
- private static native double nativeGetDouble(long windowPtr, int row, int column);
private static native void nativeCopyStringToBuffer(long windowPtr, int row, int column,
CharArrayBuffer buffer);
-
private static native boolean nativePutBlob(long windowPtr, byte[] value, int row, int column);
- private static native boolean nativePutString(long windowPtr, String value, int row, int column);
+ private static native boolean nativePutString(long windowPtr, String value,
+ int row, int column);
+
+ // Below native methods don't do unconstrained work, so are FastNative for performance
+
+ @FastNative
+ private static native void nativeClear(long windowPtr);
+
+ @FastNative
+ private static native int nativeGetNumRows(long windowPtr);
+ @FastNative
+ private static native boolean nativeSetNumColumns(long windowPtr, int columnNum);
+ @FastNative
+ private static native boolean nativeAllocRow(long windowPtr);
+ @FastNative
+ private static native void nativeFreeLastRow(long windowPtr);
+
+ @FastNative
+ private static native int nativeGetType(long windowPtr, int row, int column);
+ @FastNative
+ private static native long nativeGetLong(long windowPtr, int row, int column);
+ @FastNative
+ private static native double nativeGetDouble(long windowPtr, int row, int column);
+
+ @FastNative
private static native boolean nativePutLong(long windowPtr, long value, int row, int column);
+ @FastNative
private static native boolean nativePutDouble(long windowPtr, double value, int row, int column);
+ @FastNative
private static native boolean nativePutNull(long windowPtr, int row, int column);
- private static native String nativeGetName(long windowPtr);
/**
* Creates a new empty cursor window and gives it a name.
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 7fb0c89..7297426 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -22,7 +22,9 @@
/**
* Class representing a sensor. Use {@link SensorManager#getSensorList} to get
- * the list of available Sensors.
+ * the list of available sensors. For more information about Android sensors,
+ * read the
+ * <a href="/guide/topics/sensors/sensors_motion.html">Motion Sensors guide</a>.</p>
*
* @see SensorManager
* @see SensorEventListener
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index f47cd66..eb4bced 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -576,7 +576,7 @@
*
* @see #enableSurfaceSharing
*/
- public static int getMaxSharedSurfaceCount() {
+ public int getMaxSharedSurfaceCount() {
return MAX_SURFACES_COUNT;
}
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 398dda1..91bbdc7 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -88,18 +88,22 @@
/* Returns true if the specified USB function is enabled. */
boolean isFunctionEnabled(String function);
- /* Sets the current USB function as well as whether USB data
- * (for example, MTP exposed pictures) should be made available
- * on the USB connection. Unlocking data should only be done with
- * user involvement, since exposing pictures or other data could
- * leak sensitive user information.
- */
+ /* Sets the current USB function. */
+ void setCurrentFunctions(long functions);
+
+ /* Compatibility version of setCurrentFunctions(long). */
void setCurrentFunction(String function, boolean usbDataUnlocked);
+ /* Gets the current USB functions. */
+ long getCurrentFunctions();
+
/* Sets the screen unlocked USB function(s), which will be set automatically
* when the screen is unlocked.
*/
- void setScreenUnlockedFunctions(String function);
+ void setScreenUnlockedFunctions(long functions);
+
+ /* Gets the current screen unlocked functions. */
+ long getScreenUnlockedFunctions();
/* Allow USB debugging from the attached host. If alwaysAllow is true, add the
* the public key to list of host keys that the user has approved.
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 7617c2b..8daecac 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -28,6 +28,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.hardware.usb.gadget.V1_0.GadgetFunction;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.Process;
@@ -37,6 +38,8 @@
import com.android.internal.util.Preconditions;
import java.util.HashMap;
+import java.util.Map;
+import java.util.StringJoiner;
/**
* This class allows you to access the state of USB and communicate with USB devices.
@@ -70,7 +73,7 @@
* MTP function is enabled
* <li> {@link #USB_FUNCTION_PTP} boolean extra indicating whether the
* PTP function is enabled
- * <li> {@link #USB_FUNCTION_PTP} boolean extra indicating whether the
+ * <li> {@link #USB_FUNCTION_ACCESSORY} boolean extra indicating whether the
* accessory function is enabled
* <li> {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the
* audio source function is enabled
@@ -196,8 +199,7 @@
/**
* A placeholder indicating that no USB function is being specified.
- * Used to distinguish between selecting no function vs. the default function in
- * {@link #setCurrentFunction(String)}.
+ * Used for compatibility with old init scripts to indicate no functions vs. charging function.
*
* {@hide}
*/
@@ -298,6 +300,69 @@
*/
public static final String EXTRA_PERMISSION_GRANTED = "permission";
+ /**
+ * Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
+ * {@hide}
+ */
+ public static final long FUNCTION_NONE = 0;
+
+ /**
+ * Code for the mtp usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * {@hide}
+ */
+ public static final long FUNCTION_MTP = GadgetFunction.MTP;
+
+ /**
+ * Code for the ptp usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * {@hide}
+ */
+ public static final long FUNCTION_PTP = GadgetFunction.PTP;
+
+ /**
+ * Code for the rndis usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * {@hide}
+ */
+ public static final long FUNCTION_RNDIS = GadgetFunction.RNDIS;
+
+ /**
+ * Code for the midi usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * {@hide}
+ */
+ public static final long FUNCTION_MIDI = GadgetFunction.MIDI;
+
+ /**
+ * Code for the accessory usb function.
+ * {@hide}
+ */
+ public static final long FUNCTION_ACCESSORY = GadgetFunction.ACCESSORY;
+
+ /**
+ * Code for the audio source usb function.
+ * {@hide}
+ */
+ public static final long FUNCTION_AUDIO_SOURCE = GadgetFunction.AUDIO_SOURCE;
+
+ /**
+ * Code for the adb usb function.
+ * {@hide}
+ */
+ public static final long FUNCTION_ADB = GadgetFunction.ADB;
+
+ private static final long SETTABLE_FUNCTIONS = FUNCTION_MTP | FUNCTION_PTP | FUNCTION_RNDIS
+ | FUNCTION_MIDI;
+
+ private static final Map<String, Long> FUNCTION_NAME_TO_CODE = new HashMap<>();
+
+ static {
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MTP, FUNCTION_MTP);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_PTP, FUNCTION_PTP);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_RNDIS, FUNCTION_RNDIS);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MIDI, FUNCTION_MIDI);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ACCESSORY, FUNCTION_ACCESSORY);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB);
+ }
+
private final Context mContext;
private final IUsbManager mService;
@@ -548,15 +613,14 @@
* services offered by the device.
* </p>
*
+ * @deprecated use getCurrentFunctions() instead.
* @param function name of the USB function
* @return true if the USB function is enabled
*
* {@hide}
*/
+ @Deprecated
public boolean isFunctionEnabled(String function) {
- if (mService == null) {
- return false;
- }
try {
return mService.isFunctionEnabled(function);
} catch (RemoteException e) {
@@ -565,7 +629,7 @@
}
/**
- * Sets the current USB function when in device mode.
+ * Sets the current USB functions when in device mode.
* <p>
* USB functions represent interfaces which are published to the host to access
* services offered by the device.
@@ -574,27 +638,59 @@
* automatically activate additional functions such as {@link #USB_FUNCTION_ADB}
* or {@link #USB_FUNCTION_ACCESSORY} based on other settings and states.
* </p><p>
- * The allowed values are: {@link #USB_FUNCTION_NONE}, {@link #USB_FUNCTION_AUDIO_SOURCE},
- * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
- * or {@link #USB_FUNCTION_RNDIS}.
- * </p><p>
- * Also sets whether USB data (for example, MTP exposed pictures) should be made available
- * on the USB connection when in device mode. Unlocking usb data should only be done with
- * user involvement, since exposing pictures or other data could leak sensitive
- * user information.
+ * An argument of 0 indicates that the device is charging, and can pick any
+ * appropriate function for that purpose.
* </p><p>
* Note: This function is asynchronous and may fail silently without applying
* the requested changes.
* </p>
*
- * @param function name of the USB function, or null to restore the default function
- * @param usbDataUnlocked whether user data is accessible
+ * @param functions the USB function(s) to set, as a bitwise mask.
+ * Must satisfy {@link UsbManager#areSettableFunctions}
*
* {@hide}
*/
- public void setCurrentFunction(String function, boolean usbDataUnlocked) {
+ public void setCurrentFunctions(long functions) {
try {
- mService.setCurrentFunction(function, usbDataUnlocked);
+ mService.setCurrentFunctions(functions);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Sets the current USB functions when in device mode.
+ *
+ * @deprecated use setCurrentFunctions(long) instead.
+ * @param functions the USB function(s) to set.
+ * @param usbDataUnlocked unused
+
+ * {@hide}
+ */
+ @Deprecated
+ public void setCurrentFunction(String functions, boolean usbDataUnlocked) {
+ try {
+ mService.setCurrentFunction(functions, usbDataUnlocked);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the current USB functions in device mode.
+ * <p>
+ * This function returns the state of primary USB functions and can return a
+ * mask containing any usb function(s) except for ADB.
+ * </p>
+ *
+ * @return The currently enabled functions, in a bitwise mask.
+ * A zero mask indicates that the current function is the charging function.
+ *
+ * {@hide}
+ */
+ public long getCurrentFunctions() {
+ try {
+ return mService.getCurrentFunctions();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -604,23 +700,37 @@
* Sets the screen unlocked functions, which are persisted and set as the current functions
* whenever the screen is unlocked.
* <p>
- * The allowed values are: {@link #USB_FUNCTION_NONE},
- * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
- * or {@link #USB_FUNCTION_RNDIS}.
- * {@link #USB_FUNCTION_NONE} has the effect of switching off this feature, so functions
+ * A zero mask has the effect of switching off this feature, so functions
* no longer change on screen unlock.
* </p><p>
* Note: When the screen is on, this method will apply given functions as current functions,
* which is asynchronous and may fail silently without applying the requested changes.
* </p>
*
- * @param function function to set as default
+ * @param functions functions to set, in a bitwise mask.
+ * Must satisfy {@link UsbManager#areSettableFunctions}
*
* {@hide}
*/
- public void setScreenUnlockedFunctions(String function) {
+ public void setScreenUnlockedFunctions(long functions) {
try {
- mService.setScreenUnlockedFunctions(function);
+ mService.setScreenUnlockedFunctions(functions);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Gets the current screen unlocked functions.
+ *
+ * @return The currently set screen enabled functions.
+ * A zero mask indicates that the screen unlocked functions feature is not enabled.
+ *
+ * {@hide}
+ */
+ public long getScreenUnlockedFunctions() {
+ try {
+ return mService.getScreenUnlockedFunctions();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -719,51 +829,71 @@
}
}
- /** @hide */
- public static String addFunction(String functions, String function) {
- if (USB_FUNCTION_NONE.equals(functions)) {
- return function;
- }
- if (!containsFunction(functions, function)) {
- if (functions.length() > 0) {
- functions += ",";
- }
- functions += function;
- }
- return functions;
+ /**
+ * Returns whether the given functions are valid inputs to UsbManager.
+ * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI are accepted.
+ *
+ * @return Whether the mask is settable.
+ *
+ * {@hide}
+ */
+ public static boolean areSettableFunctions(long functions) {
+ return functions == FUNCTION_NONE
+ || ((~SETTABLE_FUNCTIONS & functions) == 0 && Long.bitCount(functions) == 1);
}
- /** @hide */
- public static String removeFunction(String functions, String function) {
- String[] split = functions.split(",");
- for (int i = 0; i < split.length; i++) {
- if (function.equals(split[i])) {
- split[i] = null;
- }
+ /**
+ * Converts the given function mask to string. Maintains ordering with respect to init scripts.
+ *
+ * @return String representation of given mask
+ *
+ * {@hide}
+ */
+ public static String usbFunctionsToString(long functions) {
+ StringJoiner joiner = new StringJoiner(",");
+ if ((functions & FUNCTION_MTP) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_MTP);
}
- if (split.length == 1 && split[0] == null) {
- return USB_FUNCTION_NONE;
+ if ((functions & FUNCTION_PTP) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_PTP);
}
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < split.length; i++) {
- String s = split[i];
- if (s != null) {
- if (builder.length() > 0) {
- builder.append(",");
- }
- builder.append(s);
- }
+ if ((functions & FUNCTION_RNDIS) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_RNDIS);
}
- return builder.toString();
+ if ((functions & FUNCTION_MIDI) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_MIDI);
+ }
+ if ((functions & FUNCTION_ACCESSORY) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_ACCESSORY);
+ }
+ if ((functions & FUNCTION_AUDIO_SOURCE) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_AUDIO_SOURCE);
+ }
+ if ((functions & FUNCTION_ADB) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_ADB);
+ }
+ return joiner.toString();
}
- /** @hide */
- public static boolean containsFunction(String functions, String function) {
- int index = functions.indexOf(function);
- if (index < 0) return false;
- if (index > 0 && functions.charAt(index - 1) != ',') return false;
- int charAfter = index + function.length();
- if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
- return true;
+ /**
+ * Parses a string of usb functions that are comma separated.
+ *
+ * @return A mask of all valid functions in the string
+ *
+ * {@hide}
+ */
+ public static long usbFunctionsFromString(String functions) {
+ if (functions == null || functions.equals(USB_FUNCTION_NONE)) {
+ return FUNCTION_NONE;
+ }
+ long ret = 0;
+ for (String function : functions.split(",")) {
+ if (FUNCTION_NAME_TO_CODE.containsKey(function)) {
+ ret |= FUNCTION_NAME_TO_CODE.get(function);
+ } else if (function.length() > 0) {
+ throw new IllegalArgumentException("Invalid usb function " + functions);
+ }
+ }
+ return ret;
}
}
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 13b9206..2306e5f 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -61,6 +61,7 @@
* @attr ref android.R.styleable#KeyboardView_keyBackground
* @attr ref android.R.styleable#KeyboardView_keyPreviewLayout
* @attr ref android.R.styleable#KeyboardView_keyPreviewOffset
+ * @attr ref android.R.styleable#KeyboardView_keyPreviewHeight
* @attr ref android.R.styleable#KeyboardView_labelTextSize
* @attr ref android.R.styleable#KeyboardView_keyTextSize
* @attr ref android.R.styleable#KeyboardView_keyTextColor
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 9ccdbe2..0829b4a 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -462,7 +462,7 @@
mConfig.setMode(MODE_TUNNEL);
mConfig.setSourceAddress(sourceAddress.getHostAddress());
mConfig.setSpiResourceId(spi.getResourceId());
- return new IpSecTransform(mContext, mConfig);
+ return new IpSecTransform(mContext, mConfig).activate();
}
/**
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 843bdb5..a734719 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -157,11 +157,11 @@
// values of the "plugged" field in the ACTION_BATTERY_CHANGED intent.
// These must be powers of 2.
/** Power source is an AC charger. */
- public static final int BATTERY_PLUGGED_AC = 1;
+ public static final int BATTERY_PLUGGED_AC = OsProtoEnums.BATTERY_PLUGGED_AC; // = 1
/** Power source is a USB port. */
- public static final int BATTERY_PLUGGED_USB = 2;
+ public static final int BATTERY_PLUGGED_USB = OsProtoEnums.BATTERY_PLUGGED_USB; // = 2
/** Power source is wireless. */
- public static final int BATTERY_PLUGGED_WIRELESS = 4;
+ public static final int BATTERY_PLUGGED_WIRELESS = OsProtoEnums.BATTERY_PLUGGED_WIRELESS; // = 4
/** @hide */
public static final int BATTERY_PLUGGED_ANY =
diff --git a/core/java/android/os/BatteryManagerInternal.java b/core/java/android/os/BatteryManagerInternal.java
index f3a95b9..a86237d 100644
--- a/core/java/android/os/BatteryManagerInternal.java
+++ b/core/java/android/os/BatteryManagerInternal.java
@@ -24,26 +24,63 @@
public abstract class BatteryManagerInternal {
/**
* Returns true if the device is plugged into any of the specified plug types.
+ *
+ * This is a simple accessor that's safe to be called from any locks, but internally it may
+ * wait on the battery service lock.
*/
public abstract boolean isPowered(int plugTypeSet);
/**
* Returns the current plug type.
+ *
+ * This is a simple accessor that's safe to be called from any locks, but internally it may
+ * wait on the battery service lock.
*/
public abstract int getPlugType();
/**
* Returns battery level as a percentage.
+ *
+ * This is a simple accessor that's safe to be called from any locks, but internally it may
+ * wait on the battery service lock.
*/
public abstract int getBatteryLevel();
/**
+ * Instantaneous battery capacity in uA-h, as defined in the HealthInfo HAL struct.
+ * Please note apparently it could be bigger than {@link #getBatteryFullCharge}.
+ *
+ * This is a simple accessor that's safe to be called from any locks, but internally it may
+ * wait on the battery service lock.
+ *
+ * @see android.hardware.health.V1_0.HealthInfo#batteryChargeCounter
+ */
+ public abstract int getBatteryChargeCounter();
+
+ /**
+ * Battery charge value when it is considered to be "full" in uA-h , as defined in the
+ * HealthInfo HAL struct.
+ *
+ * This is a simple accessor that's safe to be called from any locks, but internally it may
+ * wait on the battery service lock.
+ *
+ * @see android.hardware.health.V1_0.HealthInfo#batteryFullCharge
+ */
+ public abstract int getBatteryFullCharge();
+
+ /**
* Returns whether we currently consider the battery level to be low.
+ *
+ * This is a simple accessor that's safe to be called from any locks, but internally it may
+ * wait on the battery service lock.
*/
public abstract boolean getBatteryLevelLow();
/**
* Returns a non-zero value if an unsupported charger is attached.
+ *
+ * This is a simple accessor that's safe to be called from any locks, but internally it may
+ * wait on the battery service lock.
*/
public abstract int getInvalidCharger();
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 03a8dba..fd0e5ae 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -20,6 +20,7 @@
import android.app.job.JobParameters;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.server.ServerProtoEnums;
import android.service.batterystats.BatteryStatsServiceDumpProto;
import android.telephony.SignalStrength;
import android.text.format.DateFormat;
@@ -2054,17 +2055,17 @@
/**
* Constant for device idle mode: not active.
*/
- public static final int DEVICE_IDLE_MODE_OFF = 0;
+ public static final int DEVICE_IDLE_MODE_OFF = ServerProtoEnums.DEVICE_IDLE_MODE_OFF; // 0
/**
* Constant for device idle mode: active in lightweight mode.
*/
- public static final int DEVICE_IDLE_MODE_LIGHT = 1;
+ public static final int DEVICE_IDLE_MODE_LIGHT = ServerProtoEnums.DEVICE_IDLE_MODE_LIGHT; // 1
/**
* Constant for device idle mode: active in full mode.
*/
- public static final int DEVICE_IDLE_MODE_DEEP = 2;
+ public static final int DEVICE_IDLE_MODE_DEEP = ServerProtoEnums.DEVICE_IDLE_MODE_DEEP; // 2
/**
* Returns the time in microseconds that device has been in idle mode while
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index eb264d6d..4aadc5b 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -21,7 +21,9 @@
import android.util.ExceptionUtils;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseIntArray;
+import com.android.internal.os.BinderInternal;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
@@ -934,6 +936,7 @@
final int totalUnclearedSize = unclearedSize();
if (totalUnclearedSize >= CRASH_AT_SIZE) {
dumpProxyInterfaceCounts();
+ dumpPerUidProxyCounts();
Runtime.getRuntime().gc();
throw new AssertionError("Binder ProxyMap has too many entries: "
+ totalSize + " (total), " + totalUnclearedSize + " (uncleared), "
@@ -987,6 +990,20 @@
}
}
+ /**
+ * Dump per uid binder proxy counts to the logcat.
+ */
+ private void dumpPerUidProxyCounts() {
+ SparseIntArray counts = BinderInternal.nGetBinderProxyPerUidCounts();
+ if (counts.size() == 0) return;
+ Log.d(Binder.TAG, "Per Uid Binder Proxy Counts:");
+ for (int i = 0; i < counts.size(); i++) {
+ final int uid = counts.keyAt(i);
+ final int binderCount = counts.valueAt(i);
+ Log.d(Binder.TAG, "UID : " + uid + " count = " + binderCount);
+ }
+ }
+
// Corresponding ArrayLists in the following two arrays always have the same size.
// They contain no empty entries. However WeakReferences in the values ArrayLists
// may have been cleared.
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index fc78861..48f5684 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -894,14 +894,6 @@
/**
* P.
- *
- * <p>Applications targeting this or a later release will get these
- * new changes in behavior:</p>
- * <ul>
- * <li>{@link android.app.Service#startForeground Service.startForeground} requires
- * that apps hold the permission
- * {@link android.Manifest.permission#FOREGROUND_SERVICE}.</li>
- * </ul>
*/
public static final int P = CUR_DEVELOPMENT; // STOPSHIP Replace with the real version.
}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 33e8c3e..e606964 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -56,10 +56,10 @@
* <p><strong>Logging Trace Files</strong></p>
* <p>Debug can create log files that give details about an application, such as
* a call stack and start/stop times for any running methods. See <a
-href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files. To start logging trace files, call one
- * of the startMethodTracing() methods. To stop tracing, call
- * {@link #stopMethodTracing()}.
+ * href="{@docRoot}studio/profile/traceview.html">Inspect Trace Logs with
+ * Traceview</a> for information about reading trace files. To start logging
+ * trace files, call one of the startMethodTracing() methods. To stop tracing,
+ * call {@link #stopMethodTracing()}.
*/
public final class Debug
{
@@ -116,6 +116,8 @@
/** The proportional set size that is swappable for dalvik heap. */
/** @hide We may want to expose this, eventually. */
public int dalvikSwappablePss;
+ /** @hide The resident set size for dalvik heap. (Without other Dalvik overhead.) */
+ public int dalvikRss;
/** The private dirty pages used by dalvik heap. */
public int dalvikPrivateDirty;
/** The shared dirty pages used by dalvik heap. */
@@ -138,6 +140,8 @@
/** The proportional set size that is swappable for the native heap. */
/** @hide We may want to expose this, eventually. */
public int nativeSwappablePss;
+ /** @hide The resident set size for the native heap. */
+ public int nativeRss;
/** The private dirty pages used by the native heap. */
public int nativePrivateDirty;
/** The shared dirty pages used by the native heap. */
@@ -160,6 +164,8 @@
/** The proportional set size that is swappable for everything else. */
/** @hide We may want to expose this, eventually. */
public int otherSwappablePss;
+ /** @hide The resident set size for everything else. */
+ public int otherRss;
/** The private dirty pages used by everything else. */
public int otherPrivateDirty;
/** The shared dirty pages used by everything else. */
@@ -288,24 +294,26 @@
public static final int NUM_DVK_STATS = 14;
/** @hide */
- public static final int NUM_CATEGORIES = 8;
+ public static final int NUM_CATEGORIES = 9;
/** @hide */
- public static final int offsetPss = 0;
+ public static final int OFFSET_PSS = 0;
/** @hide */
- public static final int offsetSwappablePss = 1;
+ public static final int OFFSET_SWAPPABLE_PSS = 1;
/** @hide */
- public static final int offsetPrivateDirty = 2;
+ public static final int OFFSET_RSS = 2;
/** @hide */
- public static final int offsetSharedDirty = 3;
+ public static final int OFFSET_PRIVATE_DIRTY = 3;
/** @hide */
- public static final int offsetPrivateClean = 4;
+ public static final int OFFSET_SHARED_DIRTY = 4;
/** @hide */
- public static final int offsetSharedClean = 5;
+ public static final int OFFSET_PRIVATE_CLEAN = 5;
/** @hide */
- public static final int offsetSwappedOut = 6;
+ public static final int OFFSET_SHARED_CLEAN = 6;
/** @hide */
- public static final int offsetSwappedOutPss = 7;
+ public static final int OFFSET_SWAPPED_OUT = 7;
+ /** @hide */
+ public static final int OFFSET_SWAPPED_OUT_PSS = 8;
private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES];
@@ -337,6 +345,13 @@
}
/**
+ * @hide Return total RSS memory usage in kB.
+ */
+ public int getTotalRss() {
+ return dalvikRss + nativeRss + otherRss;
+ }
+
+ /**
* Return total private dirty memory usage in kB.
*/
public int getTotalPrivateDirty() {
@@ -382,29 +397,32 @@
/** @hide */
public int getOtherPss(int which) {
- return otherStats[which*NUM_CATEGORIES + offsetPss];
+ return otherStats[which * NUM_CATEGORIES + OFFSET_PSS];
}
-
/** @hide */
public int getOtherSwappablePss(int which) {
- return otherStats[which*NUM_CATEGORIES + offsetSwappablePss];
+ return otherStats[which * NUM_CATEGORIES + OFFSET_SWAPPABLE_PSS];
}
+ /** @hide */
+ public int getOtherRss(int which) {
+ return otherStats[which * NUM_CATEGORIES + OFFSET_RSS];
+ }
/** @hide */
public int getOtherPrivateDirty(int which) {
- return otherStats[which*NUM_CATEGORIES + offsetPrivateDirty];
+ return otherStats[which * NUM_CATEGORIES + OFFSET_PRIVATE_DIRTY];
}
/** @hide */
public int getOtherSharedDirty(int which) {
- return otherStats[which*NUM_CATEGORIES + offsetSharedDirty];
+ return otherStats[which * NUM_CATEGORIES + OFFSET_SHARED_DIRTY];
}
/** @hide */
public int getOtherPrivateClean(int which) {
- return otherStats[which*NUM_CATEGORIES + offsetPrivateClean];
+ return otherStats[which * NUM_CATEGORIES + OFFSET_PRIVATE_CLEAN];
}
/** @hide */
@@ -414,17 +432,17 @@
/** @hide */
public int getOtherSharedClean(int which) {
- return otherStats[which*NUM_CATEGORIES + offsetSharedClean];
+ return otherStats[which * NUM_CATEGORIES + OFFSET_SHARED_CLEAN];
}
/** @hide */
public int getOtherSwappedOut(int which) {
- return otherStats[which*NUM_CATEGORIES + offsetSwappedOut];
+ return otherStats[which * NUM_CATEGORIES + OFFSET_SWAPPED_OUT];
}
/** @hide */
public int getOtherSwappedOutPss(int which) {
- return otherStats[which*NUM_CATEGORIES + offsetSwappedOutPss];
+ return otherStats[which * NUM_CATEGORIES + OFFSET_SWAPPED_OUT_PSS];
}
/** @hide */
@@ -741,6 +759,7 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(dalvikPss);
dest.writeInt(dalvikSwappablePss);
+ dest.writeInt(dalvikRss);
dest.writeInt(dalvikPrivateDirty);
dest.writeInt(dalvikSharedDirty);
dest.writeInt(dalvikPrivateClean);
@@ -749,6 +768,7 @@
dest.writeInt(dalvikSwappedOutPss);
dest.writeInt(nativePss);
dest.writeInt(nativeSwappablePss);
+ dest.writeInt(nativeRss);
dest.writeInt(nativePrivateDirty);
dest.writeInt(nativeSharedDirty);
dest.writeInt(nativePrivateClean);
@@ -757,6 +777,7 @@
dest.writeInt(nativeSwappedOutPss);
dest.writeInt(otherPss);
dest.writeInt(otherSwappablePss);
+ dest.writeInt(otherRss);
dest.writeInt(otherPrivateDirty);
dest.writeInt(otherSharedDirty);
dest.writeInt(otherPrivateClean);
@@ -770,6 +791,7 @@
public void readFromParcel(Parcel source) {
dalvikPss = source.readInt();
dalvikSwappablePss = source.readInt();
+ dalvikRss = source.readInt();
dalvikPrivateDirty = source.readInt();
dalvikSharedDirty = source.readInt();
dalvikPrivateClean = source.readInt();
@@ -778,6 +800,7 @@
dalvikSwappedOutPss = source.readInt();
nativePss = source.readInt();
nativeSwappablePss = source.readInt();
+ nativeRss = source.readInt();
nativePrivateDirty = source.readInt();
nativeSharedDirty = source.readInt();
nativePrivateClean = source.readInt();
@@ -786,6 +809,7 @@
nativeSwappedOutPss = source.readInt();
otherPss = source.readInt();
otherSwappablePss = source.readInt();
+ otherRss = source.readInt();
otherPrivateDirty = source.readInt();
otherSharedDirty = source.readInt();
otherPrivateClean = source.readInt();
@@ -1001,8 +1025,8 @@
* under your package-specific directory on primary shared/external storage,
* as returned by {@link Context#getExternalFilesDir(String)}.
* <p>
- * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
- * A Graphical Log Viewer</a> for information about reading trace files.
+ * See <a href="{@docRoot}studio/profile/traceview.html">Inspect Trace Logs
+ * with Traceview</a> for information about reading trace files.
* <p class="note">
* When method tracing is enabled, the VM will run more slowly than usual,
* so the timings from the trace files should only be considered in relative
@@ -1025,8 +1049,8 @@
* your package-specific directory on primary shared/external storage, as
* returned by {@link Context#getExternalFilesDir(String)}.
* <p>
- * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
- * A Graphical Log Viewer</a> for information about reading trace files.
+ * See <a href="{@docRoot}studio/profile/traceview.html">Inspect Trace Logs
+ * with Traceview</a> for information about reading trace files.
* <p class="note">
* When method tracing is enabled, the VM will run more slowly than usual,
* so the timings from the trace files should only be considered in relative
@@ -1055,8 +1079,8 @@
* your package-specific directory on primary shared/external storage, as
* returned by {@link Context#getExternalFilesDir(String)}.
* <p>
- * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
- * A Graphical Log Viewer</a> for information about reading trace files.
+ * See <a href="{@docRoot}studio/profile/traceview.html">Inspect Trace Logs
+ * with Traceview</a> for information about reading trace files.
* <p class="note">
* When method tracing is enabled, the VM will run more slowly than usual,
* so the timings from the trace files should only be considered in relative
@@ -1087,8 +1111,8 @@
* your package-specific directory on primary shared/external storage, as
* returned by {@link Context#getExternalFilesDir(String)}.
* <p>
- * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
- * A Graphical Log Viewer</a> for information about reading trace files.
+ * See <a href="{@docRoot}studio/profile/traceview.html">Inspect Trace Logs
+ * with Traceview</a> for information about reading trace files.
* <p class="note">
* When method tracing is enabled, the VM will run more slowly than usual,
* so the timings from the trace files should only be considered in relative
@@ -1121,8 +1145,8 @@
* your package-specific directory on primary shared/external storage, as
* returned by {@link Context#getExternalFilesDir(String)}.
* <p>
- * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
- * A Graphical Log Viewer</a> for information about reading trace files.
+ * See <a href="{@docRoot}studio/profile/traceview.html">Inspect Trace Logs
+ * with Traceview</a> for information about reading trace files.
*
* @param tracePath Path to the trace log file to create. If {@code null},
* this will default to "dmtrace.trace". If the file already
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 158041d..03203d0 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -41,6 +41,7 @@
private static final String ENV_OEM_ROOT = "OEM_ROOT";
private static final String ENV_ODM_ROOT = "ODM_ROOT";
private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
+ private static final String ENV_PRODUCT_ROOT = "PRODUCT_ROOT";
/** {@hide} */
public static final String DIR_ANDROID = "Android";
@@ -62,6 +63,7 @@
private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm");
private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
+ private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product");
private static UserEnvironment sCurrentUser;
private static boolean sUserRequired;
@@ -180,6 +182,16 @@
}
/**
+ * Return root directory of the "product" partition holding product-specific
+ * customizations if any. If present, the partition is mounted read-only.
+ *
+ * @hide
+ */
+ public static File getProductDirectory() {
+ return DIR_PRODUCT_ROOT;
+ }
+
+ /**
* Return the system directory for a user. This is for use by system
* services to store files relating to the user. This directory will be
* automatically deleted when the user is removed.
diff --git a/core/java/android/os/HidlSupport.java b/core/java/android/os/HidlSupport.java
index 335bf9d..91b796a 100644
--- a/core/java/android/os/HidlSupport.java
+++ b/core/java/android/os/HidlSupport.java
@@ -212,9 +212,10 @@
}
/**
- * Return PID of process if sharable to clients.
+ * Return PID of process only if on a non-user build. For debugging purposes.
* @hide
*/
+ @SystemApi
public static native int getPidIfSharable();
/** @hide */
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index ecac002..cdee110 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -53,14 +53,30 @@
public native final void registerService(String serviceName)
throws RemoteException;
- /** @hide */
+ /**
+ * Returns the specified service from the hwservicemanager. Does not retry.
+ *
+ * @param iface fully-qualified interface name for example foo.bar@1.3::IBaz
+ * @param serviceName the instance name of the service for example default.
+ * @throws NoSuchElementException when the service is unavailable
+ * @hide
+ */
+ @SystemApi
public static final IHwBinder getService(
String iface,
String serviceName)
throws RemoteException, NoSuchElementException {
return getService(iface, serviceName, false /* retry */);
}
- /** @hide */
+ /**
+ * Returns the specified service from the hwservicemanager.
+ * @param iface fully-qualified interface name for example foo.bar@1.3::IBaz
+ * @param serviceName the instance name of the service for example default.
+ * @param retry whether to wait for the service to start if it's not already started
+ * @throws NoSuchElementException when the service is unavailable
+ * @hide
+ */
+ @SystemApi
public static native final IHwBinder getService(
String iface,
String serviceName,
@@ -71,6 +87,9 @@
* Configures how many threads the process-wide hwbinder threadpool
* has to process incoming requests.
*
+ * @param maxThreads total number of threads to create (includes this thread if
+ * callerWillJoin is true)
+ * @param callerWillJoin whether joinRpcThreadpool will be called in advance
* @hide
*/
@SystemApi
@@ -108,7 +127,25 @@
private static native void native_report_sysprop_change();
/**
+ * Enable instrumentation if available.
+ *
+ * On a non-user build, this method:
+ * - tries to enable atracing (if enabled)
+ * - tries to enable coverage dumps (if running in VTS)
+ * - tries to enable record and replay (if running in VTS)
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void enableInstrumentation() {
+ native_report_sysprop_change();
+ }
+
+ /**
* Notifies listeners that a system property has changed
+ *
+ * TODO(b/72480743): remove this method
+ *
* @hide
*/
public static void reportSyspropChanged() {
diff --git a/core/java/android/os/IHwBinder.java b/core/java/android/os/IHwBinder.java
index ce9f6c1..a565dee 100644
--- a/core/java/android/os/IHwBinder.java
+++ b/core/java/android/os/IHwBinder.java
@@ -27,12 +27,28 @@
/** @hide */
public static final int FLAG_ONEWAY = 1;
- /** @hide */
+ /**
+ * Process a hwbinder transaction.
+ *
+ * @param code interface specific code for interface.
+ * @param request parceled transaction
+ * @param reply object to parcel reply into
+ * @param flags transaction flags to be chosen by wire protocol
+ *
+ * @hide
+ */
+ @SystemApi
public void transact(
int code, HwParcel request, HwParcel reply, int flags)
throws RemoteException;
- /** @hide */
+ /**
+ * Return as IHwInterface instance only if this implements descriptor.
+ *
+ * @param descriptor for example foo.bar@1.0::IBaz
+ * @hide
+ */
+ @SystemApi
public IHwInterface queryLocalInterface(String descriptor);
/**
@@ -43,6 +59,8 @@
public interface DeathRecipient {
/**
* Callback for a registered process dying.
+ *
+ * @param cookie cookie this death recipient was registered with.
*/
@SystemApi
public void serviceDied(long cookie);
@@ -51,11 +69,16 @@
/**
* Notifies the death recipient with the cookie when the process containing
* this binder dies.
+ *
+ * @param recipient callback object to be called on object death.
+ * @param cookie value to be given to callback on object death.
*/
@SystemApi
public boolean linkToDeath(DeathRecipient recipient, long cookie);
/**
* Unregisters the death recipient from this binder.
+ *
+ * @param recipient callback to no longer recieve death notifications on this binder.
*/
@SystemApi
public boolean unlinkToDeath(DeathRecipient recipient);
diff --git a/core/java/android/os/IHwInterface.java b/core/java/android/os/IHwInterface.java
index a2f59a9..1d9e2b0 100644
--- a/core/java/android/os/IHwInterface.java
+++ b/core/java/android/os/IHwInterface.java
@@ -21,7 +21,7 @@
@SystemApi
public interface IHwInterface {
/**
- * Returns the binder object that corresponds to an interface.
+ * @return the binder object that corresponds to this interface.
*/
@SystemApi
public IHwBinder asBinder();
diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java
index 1336c66..9b6d6e5 100644
--- a/core/java/android/os/IncidentManager.java
+++ b/core/java/android/os/IncidentManager.java
@@ -33,10 +33,12 @@
@TestApi
@SystemService(Context.INCIDENT_SERVICE)
public class IncidentManager {
- private static final String TAG = "incident";
+ private static final String TAG = "IncidentManager";
private final Context mContext;
+ private IIncidentManager mService;
+
/**
* @hide
*/
@@ -96,19 +98,45 @@
reportIncidentInternal(args);
}
- private void reportIncidentInternal(IncidentReportArgs args) {
- final IIncidentManager service = IIncidentManager.Stub.asInterface(
- ServiceManager.getService(Context.INCIDENT_SERVICE));
- if (service == null) {
- Slog.e(TAG, "reportIncident can't find incident binder service");
- return;
+ private class IncidentdDeathRecipient implements IBinder.DeathRecipient {
+ @Override
+ public void binderDied() {
+ synchronized (this) {
+ mService = null;
+ }
}
+ }
+ private void reportIncidentInternal(IncidentReportArgs args) {
try {
+ final IIncidentManager service = getIIncidentManagerLocked();
+ if (service == null) {
+ Slog.e(TAG, "reportIncident can't find incident binder service");
+ return;
+ }
service.reportIncident(args);
} catch (RemoteException ex) {
Slog.e(TAG, "reportIncident failed", ex);
}
}
+
+ private IIncidentManager getIIncidentManagerLocked() throws RemoteException {
+ if (mService != null) {
+ return mService;
+ }
+
+ synchronized (this) {
+ if (mService != null) {
+ return mService;
+ }
+ mService = IIncidentManager.Stub.asInterface(
+ ServiceManager.getService(Context.INCIDENT_SERVICE));
+ if (mService != null) {
+ mService.asBinder().linkToDeath(new IncidentdDeathRecipient(), 0);
+ }
+ return mService;
+ }
+ }
+
}
diff --git a/core/java/android/os/IncidentReportArgs.java b/core/java/android/os/IncidentReportArgs.java
index fd0ebcf..9fa129c 100644
--- a/core/java/android/os/IncidentReportArgs.java
+++ b/core/java/android/os/IncidentReportArgs.java
@@ -32,6 +32,9 @@
@TestApi
public final class IncidentReportArgs implements Parcelable {
+ private static final int DEST_EXPLICIT = 100;
+ private static final int DEST_AUTO = 200;
+
private final IntArray mSections = new IntArray();
private final ArrayList<byte[]> mHeaders = new ArrayList<byte[]>();
private boolean mAll;
@@ -41,6 +44,7 @@
* Construct an incident report args with no fields.
*/
public IncidentReportArgs() {
+ mDest = DEST_AUTO;
}
/**
@@ -143,7 +147,14 @@
* @hide
*/
public void setPrivacyPolicy(int dest) {
- mDest = dest;
+ switch (dest) {
+ case DEST_EXPLICIT:
+ case DEST_AUTO:
+ mDest = dest;
+ break;
+ default:
+ mDest = DEST_AUTO;
+ }
}
/**
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 3d17ffb..811cc5e 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -110,7 +110,7 @@
/* NOTE: Wake lock levels were previously defined as a bit field, except that only a few
* combinations were actually supported so the bit field was removed. This explains
* why the numbering scheme is so odd. If adding a new wake lock level, any unused
- * value can be used.
+ * value (in frameworks/base/core/proto/android/os/enums.proto) can be used.
*/
/**
@@ -121,7 +121,7 @@
* but the CPU will be kept on until all partial wake locks have been released.
* </p>
*/
- public static final int PARTIAL_WAKE_LOCK = 0x00000001;
+ public static final int PARTIAL_WAKE_LOCK = OsProtoEnums.PARTIAL_WAKE_LOCK; // 0x00000001
/**
* Wake lock level: Ensures that the screen is on (but may be dimmed);
@@ -138,7 +138,7 @@
* as the user moves between applications and doesn't require a special permission.
*/
@Deprecated
- public static final int SCREEN_DIM_WAKE_LOCK = 0x00000006;
+ public static final int SCREEN_DIM_WAKE_LOCK = OsProtoEnums.SCREEN_DIM_WAKE_LOCK; // 0x00000006
/**
* Wake lock level: Ensures that the screen is on at full brightness;
@@ -155,7 +155,8 @@
* as the user moves between applications and doesn't require a special permission.
*/
@Deprecated
- public static final int SCREEN_BRIGHT_WAKE_LOCK = 0x0000000a;
+ public static final int SCREEN_BRIGHT_WAKE_LOCK =
+ OsProtoEnums.SCREEN_BRIGHT_WAKE_LOCK; // 0x0000000a
/**
* Wake lock level: Ensures that the screen and keyboard backlight are on at
@@ -172,7 +173,7 @@
* as the user moves between applications and doesn't require a special permission.
*/
@Deprecated
- public static final int FULL_WAKE_LOCK = 0x0000001a;
+ public static final int FULL_WAKE_LOCK = OsProtoEnums.FULL_WAKE_LOCK; // 0x0000001a
/**
* Wake lock level: Turns the screen off when the proximity sensor activates.
@@ -193,7 +194,8 @@
* Cannot be used with {@link #ACQUIRE_CAUSES_WAKEUP}.
* </p>
*/
- public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;
+ public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK =
+ OsProtoEnums.PROXIMITY_SCREEN_OFF_WAKE_LOCK; // 0x00000020
/**
* Wake lock level: Put the screen in a low power state and allow the CPU to suspend
@@ -207,7 +209,7 @@
*
* {@hide}
*/
- public static final int DOZE_WAKE_LOCK = 0x00000040;
+ public static final int DOZE_WAKE_LOCK = OsProtoEnums.DOZE_WAKE_LOCK; // 0x00000040
/**
* Wake lock level: Keep the device awake enough to allow drawing to occur.
@@ -221,7 +223,7 @@
*
* {@hide}
*/
- public static final int DRAW_WAKE_LOCK = 0x00000080;
+ public static final int DRAW_WAKE_LOCK = OsProtoEnums.DRAW_WAKE_LOCK; // 0x00000080
/**
* Mask for the wake lock level component of a combined wake lock level and flags integer.
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 6833908..96e2ae3 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -157,6 +157,12 @@
*/
public static final int INCIDENTD_UID = 1067;
+ /**
+ * Defines the UID/GID for the Secure Element service process.
+ * @hide
+ */
+ public static final int SE_UID = 1068;
+
/** {@hide} */
public static final int NOBODY_UID = 9999;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 13b5b5c9..b2b43cf 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2259,12 +2259,6 @@
}
}
- /** @removed */
- @Deprecated
- public boolean trySetQuietModeEnabled(boolean enableQuietMode, @NonNull UserHandle userHandle) {
- return requestQuietModeEnabled(enableQuietMode, userHandle);
- }
-
/**
* Enables or disables quiet mode for a managed profile. If quiet mode is enabled, apps in a
* managed profile don't run, generate notifications, or consume data or battery.
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index d592000..17d83db 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -1,6 +1,7 @@
package android.os;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.content.Context;
import android.os.WorkSourceProto;
import android.provider.Settings;
@@ -8,6 +9,8 @@
import android.util.Log;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.Arrays;
@@ -464,6 +467,7 @@
*
* @hide
*/
+ @SystemApi
public WorkChain createWorkChain() {
if (mChains == null) {
mChains = new ArrayList<>(4);
@@ -854,7 +858,8 @@
*
* @hide
*/
- public static class WorkChain implements Parcelable {
+ @SystemApi
+ public static final class WorkChain implements Parcelable {
private int mSize;
private int[] mUids;
private String[] mTags;
@@ -866,7 +871,8 @@
mTags = new String[4];
}
- // @VisibleForTesting
+ /** @hide */
+ @VisibleForTesting
public WorkChain(WorkChain other) {
mSize = other.mSize;
mUids = other.mUids.clone();
@@ -913,16 +919,22 @@
// TODO: The following three trivial getters are purely for testing and will be removed
// once we have higher level logic in place, e.g for serializing this WorkChain to a proto,
// diffing it etc.
- //
- // @VisibleForTesting
+
+
+ /** @hide */
+ @VisibleForTesting
public int[] getUids() {
return mUids;
}
- // @VisibleForTesting
+
+ /** @hide */
+ @VisibleForTesting
public String[] getTags() {
return mTags;
}
- // @VisibleForTesting
+
+ /** @hide */
+ @VisibleForTesting
public int getSize() {
return mSize;
}
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 3d2e1d1..d774281 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -34,6 +34,7 @@
import android.provider.Settings;
import android.provider.Settings.Global;
import android.provider.Settings.System;
+import android.service.notification.ZenModeConfig;
import android.util.Log;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
@@ -87,10 +88,22 @@
private static final int MSG_INIT_SAMPLE = 3;
private static final int CHECK_RINGTONE_PLAYBACK_DELAY_MS = 1000;
+ private NotificationManager.Policy mNotificationPolicy;
+ private boolean mAllowAlarms;
+ private boolean mAllowMediaSystem;
+ private boolean mAllowRinger;
+
public SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callback callback) {
mContext = context;
mAudioManager = context.getSystemService(AudioManager.class);
mNotificationManager = context.getSystemService(NotificationManager.class);
+ mNotificationPolicy = mNotificationManager.getNotificationPolicy();
+ mAllowAlarms = (mNotificationPolicy.priorityCategories & NotificationManager.Policy
+ .PRIORITY_CATEGORY_ALARMS) != 0;
+ mAllowMediaSystem = (mNotificationPolicy.priorityCategories & NotificationManager.Policy
+ .PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) != 0;
+ mAllowRinger = !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
+ mNotificationPolicy);
mStreamType = streamType;
mAffectedByRingerMode = mAudioManager.isStreamAffectedByRingerMode(mStreamType);
mNotificationOrRing = isNotificationOrRing(mStreamType);
@@ -122,6 +135,14 @@
return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION;
}
+ private static boolean isAlarmsStream(int stream) {
+ return stream == AudioManager.STREAM_ALARM;
+ }
+
+ private static boolean isMediaOrSystemStream(int stream) {
+ return stream == AudioManager.STREAM_MUSIC || stream == AudioManager.STREAM_SYSTEM;
+ }
+
public void setSeekBar(SeekBar seekBar) {
if (mSeekBar != null) {
mSeekBar.setOnSeekBarChangeListener(null);
@@ -135,7 +156,11 @@
private boolean isZenMuted() {
return mNotificationOrRing && mZenMode == Global.ZEN_MODE_ALARMS
- || mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+ || mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
+ || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+ && ((!mAllowAlarms && isAlarmsStream(mStreamType))
+ || (!mAllowMediaSystem && isMediaOrSystemStream(mStreamType))
+ || (!mAllowRinger && isNotificationOrRing(mStreamType))));
}
protected void updateSeekBar() {
@@ -396,6 +421,7 @@
final IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
+ filter.addAction(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
mContext.registerReceiver(this, filter);
} else {
@@ -424,6 +450,15 @@
} else if (NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED.equals(action)) {
mZenMode = mNotificationManager.getZenMode();
updateSlider();
+ } else if (NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED.equals(action)) {
+ mNotificationPolicy = mNotificationManager.getNotificationPolicy();
+ mAllowAlarms = (mNotificationPolicy.priorityCategories & NotificationManager.Policy
+ .PRIORITY_CATEGORY_ALARMS) != 0;
+ mAllowMediaSystem = (mNotificationPolicy.priorityCategories
+ & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) != 0;
+ mAllowRinger = !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
+ mNotificationPolicy);
+ updateSlider();
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 26495cd..1f0d683 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10503,6 +10503,15 @@
= "forced_app_standby_for_small_battery_enabled";
/**
+ * Whether or not to enable Time Only Mode for watch type devices.
+ * Type: int (0 for false, 1 for true)
+ * Default: 0
+ * @hide
+ */
+ public static final String TIME_ONLY_MODE_ENABLED
+ = "time_only_mode_enabled";
+
+ /**
* Whether or not Network Watchlist feature is enabled.
* Type: int (0 for false, 1 for true)
* Default: 0
@@ -10511,6 +10520,18 @@
public static final String NETWORK_WATCHLIST_ENABLED = "network_watchlist_enabled";
/**
+ * Flag to keep background restricted profiles running after exiting. If disabled,
+ * the restricted profile can be put into stopped state as soon as the user leaves it.
+ * Type: int (0 for false, 1 for true)
+ *
+ * Overridden by the system based on device information. If null, the value specified
+ * by {@code config_keepRestrictedProfilesInBackground} is used.
+ *
+ * @hide
+ */
+ public static final String KEEP_PROFILE_IN_BACKGROUND = "keep_profile_in_background";
+
+ /**
* Get the key that retrieves a bluetooth headset's priority.
* @hide
*/
diff --git a/core/java/android/se/omapi/Channel.java b/core/java/android/se/omapi/Channel.java
new file mode 100644
index 0000000..f0b9fa2d
--- /dev/null
+++ b/core/java/android/se/omapi/Channel.java
@@ -0,0 +1,251 @@
+/*
+ * 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.
+ */
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation.
+ */
+/*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+
+package android.se.omapi;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * Instances of this class represent an ISO/IEC 7816-4 channel opened to a
+ * Secure Element. It can be either a logical channel or the basic channel. They
+ * can be used to send APDUs to the secure element. Channels are opened by
+ * calling the Session.openBasicChannel(byte[]) or
+ * Session.openLogicalChannel(byte[]) methods.
+ *
+ * @see <a href="http://globalplatform.org">GlobalPlatform Open Mobile API</a>
+ */
+public class Channel {
+
+ private static final String TAG = "OMAPI.Channel";
+ private Session mSession;
+ private final ISecureElementChannel mChannel;
+ private final SEService mService;
+ private final Object mLock = new Object();
+
+ Channel(SEService service, Session session, ISecureElementChannel channel) {
+ if (service == null || session == null || channel == null) {
+ throw new IllegalArgumentException("Parameters cannot be null");
+ }
+ mService = service;
+ mSession = session;
+ mChannel = channel;
+ }
+
+ /**
+ * Closes this channel to the Secure Element. If the method is called when
+ * the channel is already closed, this method will be ignored. The close()
+ * method shall wait for completion of any pending transmit(byte[] command)
+ * before closing the channel.
+ */
+ public void close() {
+ if (!isClosed()) {
+ synchronized (mLock) {
+ try {
+ mChannel.close();
+ } catch (Exception e) {
+ Log.e(TAG, "Error closing channel", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Tells if this channel is closed.
+ *
+ * @return <code>true</code> if the channel is closed or in case of an error.
+ * <code>false</code> otherwise.
+ */
+ public boolean isClosed() {
+ if (!mService.isConnected()) {
+ Log.e(TAG, "service not connected to system");
+ return true;
+ }
+ try {
+ return mChannel.isClosed();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception in isClosed()");
+ return true;
+ }
+ }
+
+ /**
+ * Returns a boolean telling if this channel is the basic channel.
+ *
+ * @return <code>true</code> if this channel is a basic channel. <code>false</code> if
+ * this channel is a logical channel.
+ */
+ public boolean isBasicChannel() {
+ if (!mService.isConnected()) {
+ throw new IllegalStateException("service not connected to system");
+ }
+ try {
+ return mChannel.isBasicChannel();
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+
+ /**
+ * Transmit an APDU command (as per ISO/IEC 7816-4) to the Secure Element. The
+ * underlying layers generate as many TPDUs as necessary to transport this APDU. The
+ * API shall ensure that all available data returned from Secure Element, including
+ * concatenated responses, are retrieved and made available to the calling application. If a
+ * warning status code is received the API wont check for further response data but will
+ * return all data received so far and the warning status code.<br>
+ * The transport part is invisible from the application. The generated response is the
+ * response of the APDU which means that all protocols related responses are handled
+ * inside the API or the underlying implementation.<br>
+ * The transmit method shall support extended length APDU commands independently of
+ * the coding within the ATR.<br>
+ * For status word '61 XX' the API or underlying implementation shall issue a GET
+ * RESPONSE command as specified by ISO 7816-4 standard with LE=XX; for the status
+ * word '6C XX', the API or underlying implementation shall reissue the input command
+ * with LE=XX. For other status words, the API (or underlying implementation) shall return
+ * the complete response including data and status word to the device application. The API
+ * (or underlying implementation) shall not handle internally the received status words. The
+ * channel shall not be closed even if the Secure Element answered with an error code.
+ * The system ensures the synchronization between all the concurrent calls to this method,
+ * and that only one APDU will be sent at a time, irrespective of the number of TPDUs that
+ * might be required to transport it to the SE. The entire APDU communication to this SE is
+ * locked to the APDU.<br>
+ * The channel information in the class byte in the APDU will be ignored. The system will
+ * add any required information to ensure the APDU is transported on this channel.
+ * The only restrictions on the set of commands that can be sent is defined below, the API
+ * implementation shall be able to send all other commands: <br>
+ * <ul>
+ * <li>MANAGE_CHANNEL commands are not allowed.</li>
+ * <li>SELECT by DF Name (p1=04) are not allowed.</li>
+ * <li>CLA bytes with channel numbers are de-masked.</li>
+ * </ul>
+ *
+ * @param command the APDU command to be transmitted, as a byte array.
+ *
+ * @return the response received, as a byte array. The returned byte array contains the data
+ * bytes in the following order:
+ * [<first data byte>, ..., <last data byte>, <sw1>, <sw2>]
+ *
+ * @throws IOException if there is a communication problem to the reader or the Secure Element.
+ * @throws IllegalStateException if the channel is used after being closed.
+ * @throws IllegalArgumentException if the command byte array is less than 4 bytes long.
+ * @throws IllegalArgumentException if Lc byte is inconsistent with length of the byte array.
+ * @throws IllegalArgumentException if CLA byte is invalid according to [2] (0xff).
+ * @throws IllegalArgumentException if INS byte is invalid according to [2] (0x6x or 0x9x).
+ * @throws SecurityException if the command is filtered by the security policy.
+ * @throws NullPointerException if command is NULL.
+ */
+ public @NonNull byte[] transmit(byte[] command) throws IOException {
+ if (!mService.isConnected()) {
+ throw new IllegalStateException("service not connected to system");
+ }
+ synchronized (mLock) {
+ try {
+ byte[] response = mChannel.transmit(command);
+ if (response == null) {
+ throw new IOException("Error in communicating with Secure Element");
+ }
+ return response;
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Get the session that has opened this channel.
+ *
+ * @return the session object this channel is bound to.
+ */
+ public @NonNull Session getSession() {
+ return mSession;
+ }
+
+ /**
+ * Returns the data as received from the application select command inclusively the status word
+ * received at applet selection.
+ * The returned byte array contains the data bytes in the following order:
+ * [<first data byte>, ..., <last data byte>, <sw1>, <sw2>]
+ * @return The data as returned by the application select command inclusively the status word.
+ * Only the status word if the application select command has no returned data.
+ * Returns null if an application select command has not been performed or the selection
+ * response can not be retrieved by the reader implementation.
+ */
+ public @Nullable byte[] getSelectResponse() {
+ if (!mService.isConnected()) {
+ throw new IllegalStateException("service not connected to system");
+ }
+
+ byte[] response;
+ try {
+ response = mChannel.getSelectResponse();
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e.getMessage());
+ }
+
+ if (response != null && response.length == 0) {
+ response = null;
+ }
+ return response;
+ }
+
+ /**
+ * Performs a selection of the next Applet on this channel that matches to the partial AID
+ * specified in the openBasicChannel(byte[] aid) or openLogicalChannel(byte[] aid) method.
+ * This mechanism can be used by a device application to iterate through all Applets
+ * matching to the same partial AID.
+ * If selectNext() returns true a new Applet was successfully selected on this channel.
+ * If no further Applet exists with matches to the partial AID this method returns false
+ * and the already selected Applet stays selected. <br>
+ *
+ * Since the API cannot distinguish between a partial and full AID the API shall rely on the
+ * response of the Secure Element for the return value of this method. <br>
+ * The implementation of the underlying SELECT command within this method shall use
+ * the same values as the corresponding openBasicChannel(byte[] aid) or
+ * openLogicalChannel(byte[] aid) command with the option: <br>
+ * P2='02' (Next occurrence) <br>
+ * The select response stored in the Channel object shall be updated with the APDU
+ * response of the SELECT command.
+
+ * @return <code>true</code> if new Applet was selected on this channel.
+ <code>false</code> he already selected Applet stays selected on this channel.
+ *
+ * @throws IOException if there is a communication problem to the reader or the Secure Element.
+ * @throws IllegalStateException if the channel is used after being closed.
+ * @throws UnsupportedOperationException if this operation is not supported by the card.
+ */
+ public boolean selectNext() throws IOException {
+ if (!mService.isConnected()) {
+ throw new IllegalStateException("service not connected to system");
+ }
+ try {
+ synchronized (mLock) {
+ return mChannel.selectNext();
+ }
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+}
diff --git a/core/java/android/se/omapi/ISecureElementChannel.aidl b/core/java/android/se/omapi/ISecureElementChannel.aidl
new file mode 100644
index 0000000..4ae57ab
--- /dev/null
+++ b/core/java/android/se/omapi/ISecureElementChannel.aidl
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+/*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+
+package android.se.omapi;
+
+import android.se.omapi.ISecureElementSession;
+
+/** @hide */
+interface ISecureElementChannel {
+
+ /**
+ * Closes the specified connection and frees internal resources.
+ * A logical channel will be closed.
+ */
+ void close();
+
+ /**
+ * Tells if this channel is closed.
+ *
+ * @return <code>true</code> if the channel is closed,
+ * <code>false</code> otherwise.
+ */
+ boolean isClosed();
+
+ /**
+ * Returns a boolean telling if this channel is the basic channel.
+ *
+ * @return <code>true</code> if this channel is a basic channel.
+ * <code>false</code> if this channel is a logical channel.
+ */
+ boolean isBasicChannel();
+
+ /**
+ * Returns the data as received from the application select command
+ * inclusively the status word. The returned byte array contains the data
+ * bytes in the following order:
+ * [<first data byte>, ..., <last data byte>, <sw1>, <sw2>]
+ */
+ byte[] getSelectResponse();
+
+ /**
+ * Transmits the specified command APDU and returns the response APDU.
+ * MANAGE channel commands are not supported.
+ * Selection of applets is not supported in logical channels.
+ */
+ byte[] transmit(in byte[] command);
+
+ /**
+ * Performs a selection of the next Applet on this channel that matches to
+ * the partial AID specified in the openBasicChannel(byte[] aid) or
+ * openLogicalChannel(byte[] aid) method. This mechanism can be used by a
+ * device application to iterate through all Applets matching to the same
+ * partial AID.
+ * If selectNext() returns true a new Applet was successfully selected on
+ * this channel.
+ * If no further Applet exists with matches to the partial AID this method
+ * returns false and the already selected Applet stays selected.
+ *
+ * @return <code>true</code> if new Applet was successfully selected.
+ * <code>false</code> if no further Applet exists which matches the
+ * partial AID.
+ */
+ boolean selectNext();
+}
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl b/core/java/android/se/omapi/ISecureElementListener.aidl
similarity index 62%
copy from telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl
copy to core/java/android/se/omapi/ISecureElementListener.aidl
index 01cca2db..3a99d63 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl
+++ b/core/java/android/se/omapi/ISecureElementListener.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 The Android Open Source Project
+ * 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.
@@ -13,15 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+/*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
-package android.telephony.ims.internal.aidl;
-
-import android.telephony.ims.internal.stub.ImsFeatureConfiguration;
+package android.se.omapi;
/**
- * See ImsService#Listener for more information.
- * {@hide}
+ * Interface to receive call-backs when the service is connected.
*/
-oneway interface IImsServiceControllerListener {
- void onUpdateSupportedImsFeatures(in ImsFeatureConfiguration c);
+interface ISecureElementListener {
+ /**
+ * Called by the framework when the service is connected.
+ */
+ void serviceConnected();
}
diff --git a/core/java/android/se/omapi/ISecureElementReader.aidl b/core/java/android/se/omapi/ISecureElementReader.aidl
new file mode 100644
index 0000000..a312c44
--- /dev/null
+++ b/core/java/android/se/omapi/ISecureElementReader.aidl
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+/*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+
+package android.se.omapi;
+
+import android.se.omapi.ISecureElementSession;
+
+/** @hide */
+interface ISecureElementReader {
+
+ /**
+ * Returns true if a card is present in the specified reader.
+ * Returns false if a card is not present in the specified reader.
+ */
+ boolean isSecureElementPresent();
+
+ /**
+ * Connects to a secure element in this reader. <br>
+ * This method prepares (initialises) the Secure Element for communication
+ * before the Session object is returned (e.g. powers the Secure Element by
+ * ICC ON if its not already on). There might be multiple sessions opened at
+ * the same time on the same reader. The system ensures the interleaving of
+ * APDUs between the respective sessions.
+ *
+ * @return a Session object to be used to create Channels.
+ */
+ ISecureElementSession openSession();
+
+ /**
+ * Close all the sessions opened on this reader. All the channels opened by
+ * all these sessions will be closed.
+ */
+ void closeSessions();
+
+}
diff --git a/core/java/android/se/omapi/ISecureElementService.aidl b/core/java/android/se/omapi/ISecureElementService.aidl
new file mode 100644
index 0000000..4fa799e
--- /dev/null
+++ b/core/java/android/se/omapi/ISecureElementService.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation.
+ */
+/*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+
+package android.se.omapi;
+
+import android.se.omapi.ISecureElementReader;
+
+/**
+ * SecureElement service interface.
+ * @hide
+ */
+interface ISecureElementService {
+
+ /**
+ * Returns the friendly names of available Secure Element readers.
+ */
+ String[] getReaders();
+
+ /**
+ * Returns SecureElement Service reader object to the given name.
+ */
+ ISecureElementReader getReader(String reader);
+
+ /**
+ * Checks if the application defined by the package name is allowed to
+ * receive NFC transaction events for the defined AID.
+ */
+ boolean[] isNFCEventAllowed(String reader, in byte[] aid,
+ in String[] packageNames);
+
+}
diff --git a/core/java/android/se/omapi/ISecureElementSession.aidl b/core/java/android/se/omapi/ISecureElementSession.aidl
new file mode 100644
index 0000000..8ea599f
--- /dev/null
+++ b/core/java/android/se/omapi/ISecureElementSession.aidl
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation.
+ */
+/*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+
+package android.se.omapi;
+
+import android.se.omapi.ISecureElementChannel;
+import android.se.omapi.ISecureElementReader;
+import android.se.omapi.ISecureElementListener;
+
+/** @hide */
+interface ISecureElementSession {
+
+ /**
+ * Returns the ATR of the connected card or null if the ATR is not available
+ */
+ byte[] getAtr();
+
+ /**
+ * Close the connection with the Secure Element. This will close any
+ * channels opened by this application with this Secure Element.
+ */
+ void close();
+
+ /**
+ * Close any channel opened on this session.
+ */
+ void closeChannels();
+
+
+ /**
+ * Tells if this session is closed.
+ *
+ * @return <code>true</code> if the session is closed, false otherwise.
+ */
+ boolean isClosed();
+
+ /**
+ * Opens a connection using the basic channel of the card in the
+ * specified reader and returns a channel handle. Selects the specified
+ * applet if aid != null.
+ * Logical channels cannot be opened with this connection.
+ * Use interface method openLogicalChannel() to open a logical channel.
+ */
+ ISecureElementChannel openBasicChannel(in byte[] aid, in byte p2,
+ ISecureElementListener listener);
+
+ /**
+ * Opens a connection using the next free logical channel of the card in the
+ * specified reader. Selects the specified applet.
+ * Selection of other applets with this connection is not supported.
+ */
+ ISecureElementChannel openLogicalChannel(in byte[] aid, in byte p2,
+ ISecureElementListener listener);
+}
diff --git a/core/java/android/se/omapi/Reader.java b/core/java/android/se/omapi/Reader.java
new file mode 100644
index 0000000..9f15739
--- /dev/null
+++ b/core/java/android/se/omapi/Reader.java
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation.
+ */
+/*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+
+package android.se.omapi;
+
+import android.annotation.NonNull;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * Instances of this class represent Secure Element Readers supported to this
+ * device. These Readers can be physical devices or virtual devices. They can be
+ * removable or not. They can contain Secure Element that can or cannot be
+ * removed.
+ *
+ * @see <a href="http://globalplatform.org">GlobalPlatform Open Mobile API</a>
+ */
+public class Reader {
+
+ private static final String TAG = "OMAPI.Reader";
+ private final String mName;
+ private final SEService mService;
+ private ISecureElementReader mReader;
+ private final Object mLock = new Object();
+
+
+ Reader(SEService service, String name, ISecureElementReader reader) throws
+ IOException {
+ if (reader == null || service == null || name == null) {
+ throw new IllegalArgumentException("Parameters cannot be null");
+ }
+ mName = name;
+ mService = service;
+ mReader = reader;
+ }
+
+ /**
+ * Return the name of this reader.
+ * <ul>
+ * <li>If this reader is a SIM reader, then its name must be "SIM[Slot]".</li>
+ * <li>If the reader is a SD or micro SD reader, then its name must be "SD[Slot]"</li>
+ * <li>If the reader is a embedded SE reader, then its name must be "eSE[Slot]"</li>
+ * </ul>
+ * Slot is a decimal number without leading zeros. The Numbering must start with 1
+ * (e.g. SIM1, SIM2, ... or SD1, SD2, ... or eSE1, eSE2, ...).
+ * The slot number “1” for a reader is optional
+ * (SIM and SIM1 are both valid for the first SIM-reader,
+ * but if there are two readers then the second reader must be named SIM2).
+ * This applies also for other SD or SE readers.
+ *
+ * @return the reader name, as a String.
+ */
+ public @NonNull String getName() {
+ return mName;
+ }
+
+ /**
+ * Connects to a Secure Element in this reader. <br>
+ * This method prepares (initialises) the Secure Element for communication
+ * before the Session object is returned (e.g. powers the Secure Element by
+ * ICC ON if its not already on). There might be multiple sessions opened at
+ * the same time on the same reader. The system ensures the interleaving of
+ * APDUs between the respective sessions.
+ *
+ * @throws IOException if something went wrong with the communicating to the
+ * Secure Element or the reader.
+ * @return a Session object to be used to create Channels.
+ */
+ public @NonNull Session openSession() throws IOException {
+ if (!mService.isConnected()) {
+ throw new IllegalStateException("service is not connected");
+ }
+
+ synchronized (mLock) {
+ ISecureElementSession session;
+ try {
+ session = mReader.openSession();
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
+ if (session == null) {
+ throw new IOException("service session is null.");
+ }
+ return new Session(mService, session, this);
+ }
+ }
+
+ /**
+ * Check if a Secure Element is present in this reader.
+ *
+ * @throws IllegalStateException if the service is not connected
+ * @return <code>true</code> if the SE is present, <code>false</code> otherwise.
+ */
+ public boolean isSecureElementPresent() {
+ if (!mService.isConnected()) {
+ throw new IllegalStateException("service is not connected");
+ }
+
+ try {
+ return mReader.isSecureElementPresent();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Error in isSecureElementPresent()");
+ }
+ }
+
+ /**
+ * Return the Secure Element service this reader is bound to.
+ *
+ * @return the SEService object.
+ */
+ public @NonNull SEService getSEService() {
+ return mService;
+ }
+
+ /**
+ * Close all the sessions opened on this reader.
+ * All the channels opened by all these sessions will be closed.
+ */
+ public void closeSessions() {
+ if (!mService.isConnected()) {
+ Log.e(TAG, "service is not connected");
+ return;
+ }
+ synchronized (mLock) {
+ try {
+ mReader.closeSessions();
+ } catch (RemoteException ignore) { }
+ }
+ }
+}
diff --git a/core/java/android/se/omapi/SEService.java b/core/java/android/se/omapi/SEService.java
new file mode 100644
index 0000000..1e37277d
--- /dev/null
+++ b/core/java/android/se/omapi/SEService.java
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ */
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ */
+/*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+
+package android.se.omapi;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * The SEService realises the communication to available Secure Elements on the
+ * device. This is the entry point of this API. It is used to connect to the
+ * infrastructure and get access to a list of Secure Element Readers.
+ *
+ * @see <a href="http://simalliance.org">SIMalliance Open Mobile API v3.0</a>
+ */
+public class SEService {
+
+ private static final String TAG = "OMAPI.SEService";
+
+ private final Object mLock = new Object();
+
+ /** The client context (e.g. activity). */
+ private final Context mContext;
+
+ /** The backend system. */
+ private volatile ISecureElementService mSecureElementService;
+
+ /**
+ * Class for interacting with the main interface of the backend.
+ */
+ private ServiceConnection mConnection;
+
+ /**
+ * Collection of available readers
+ */
+ private final HashMap<String, Reader> mReaders = new HashMap<String, Reader>();
+
+ /**
+ * Listener object that allows the notification of the caller if this
+ * SEService could be bound to the backend.
+ */
+ private ISecureElementListener mSEListener;
+
+ /**
+ * Establishes a new connection that can be used to connect to all the
+ * Secure Elements available in the system. The connection process can be
+ * quite long, so it happens in an asynchronous way. It is usable only if
+ * the specified listener is called or if isConnected() returns
+ * <code>true</code>. <br>
+ * The call-back object passed as a parameter will have its
+ * serviceConnected() method called when the connection actually happen.
+ *
+ * @param context
+ * the context of the calling application. Cannot be
+ * <code>null</code>.
+ * @param listener
+ * a ISecureElementListener object. Can be <code>null</code>.
+ */
+ public SEService(Context context, ISecureElementListener listener) {
+
+ if (context == null) {
+ throw new NullPointerException("context must not be null");
+ }
+
+ mContext = context;
+ mSEListener = listener;
+
+ mConnection = new ServiceConnection() {
+
+ public synchronized void onServiceConnected(
+ ComponentName className, IBinder service) {
+
+ mSecureElementService = ISecureElementService.Stub.asInterface(service);
+ if (mSEListener != null) {
+ try {
+ mSEListener.serviceConnected();
+ } catch (RemoteException ignore) { }
+ }
+ Log.i(TAG, "Service onServiceConnected");
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ mSecureElementService = null;
+ Log.i(TAG, "Service onServiceDisconnected");
+ }
+ };
+
+ Intent intent = new Intent(ISecureElementService.class.getName());
+ intent.setClassName("com.android.se",
+ "com.android.se.SecureElementService");
+ boolean bindingSuccessful =
+ mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ if (bindingSuccessful) {
+ Log.i(TAG, "bindService successful");
+ }
+ }
+
+ /**
+ * Tells whether or not the service is connected.
+ *
+ * @return <code>true</code> if the service is connected.
+ */
+ public boolean isConnected() {
+ return mSecureElementService != null;
+ }
+
+ /**
+ * Returns the list of available Secure Element readers.
+ * There must be no duplicated objects in the returned list.
+ * All available readers shall be listed even if no card is inserted.
+ *
+ * @return The readers list, as an array of Readers. If there are no
+ * readers the returned array is of length 0.
+ */
+ public @NonNull Reader[] getReaders() {
+ if (mSecureElementService == null) {
+ throw new IllegalStateException("service not connected to system");
+ }
+ String[] readerNames;
+ try {
+ readerNames = mSecureElementService.getReaders();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+
+ Reader[] readers = new Reader[readerNames.length];
+ int i = 0;
+ for (String readerName : readerNames) {
+ if (mReaders.get(readerName) == null) {
+ try {
+ mReaders.put(readerName, new Reader(this, readerName,
+ getReader(readerName)));
+ readers[i++] = mReaders.get(readerName);
+ } catch (Exception e) {
+ Log.e(TAG, "Error adding Reader: " + readerName, e);
+ }
+ } else {
+ readers[i++] = mReaders.get(readerName);
+ }
+ }
+ return readers;
+ }
+
+ /**
+ * Releases all Secure Elements resources allocated by this SEService
+ * (including any binding to an underlying service).
+ * As a result isConnected() will return false after shutdown() was called.
+ * After this method call, the SEService object is not connected.
+ * It is recommended to call this method in the termination method of the calling application
+ * (or part of this application) which is bound to this SEService.
+ */
+ public void shutdown() {
+ synchronized (mLock) {
+ if (mSecureElementService != null) {
+ for (Reader reader : mReaders.values()) {
+ try {
+ reader.closeSessions();
+ } catch (Exception ignore) { }
+ }
+ }
+ try {
+ mContext.unbindService(mConnection);
+ } catch (IllegalArgumentException e) {
+ // Do nothing and fail silently since an error here indicates
+ // that binding never succeeded in the first place.
+ }
+ mSecureElementService = null;
+ }
+ }
+
+ /**
+ * Returns the version of the OpenMobile API specification this
+ * implementation is based on.
+ *
+ * @return String containing the OpenMobile API version (e.g. "3.0").
+ */
+ public String getVersion() {
+ return "3.2";
+ }
+
+ @NonNull ISecureElementListener getListener() {
+ return mSEListener;
+ }
+
+ /**
+ * Obtain a Reader instance from the SecureElementService
+ */
+ private @NonNull ISecureElementReader getReader(String name) {
+ try {
+ return mSecureElementService.getReader(name);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+}
diff --git a/core/java/android/se/omapi/Session.java b/core/java/android/se/omapi/Session.java
new file mode 100644
index 0000000..bb2a032
--- /dev/null
+++ b/core/java/android/se/omapi/Session.java
@@ -0,0 +1,347 @@
+/*
+ * 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.
+ */
+/*
+ * Copyright (c) 2017, The Linux Foundation.
+ */
+/*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+
+package android.se.omapi;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.NoSuchElementException;
+
+/**
+ * Instances of this class represent a connection session to one of the Secure
+ * Elements available on the device. These objects can be used to get a
+ * communication channel with an Applet in the Secure Element.
+ * This channel can be the basic channel or a logical channel.
+ *
+ * @see <a href="http://simalliance.org">SIMalliance Open Mobile API v3.0</a>
+ */
+public class Session {
+
+ private final Object mLock = new Object();
+ private final SEService mService;
+ private final Reader mReader;
+ private final ISecureElementSession mSession;
+ private static final String TAG = "OMAPI.Session";
+
+ Session(SEService service, ISecureElementSession session, Reader reader) {
+ if (service == null || reader == null || session == null) {
+ throw new IllegalArgumentException("Parameters cannot be null");
+ }
+ mService = service;
+ mReader = reader;
+ mSession = session;
+ }
+
+ /**
+ * Get the reader that provides this session.
+ *
+ * @return The Reader object.
+ */
+ public @NonNull Reader getReader() {
+ return mReader;
+ }
+
+ /**
+ * Get the Answer to Reset of this Secure Element. <br>
+ * The returned byte array can be null if the ATR for this Secure Element is
+ * not available.
+ *
+ * @throws IllegalStateException if there was an error connecting to SE or
+ * if the service was not connected.
+ * @return the ATR as a byte array or null.
+ */
+ public @Nullable byte[] getATR() {
+ if (!mService.isConnected()) {
+ throw new IllegalStateException("service not connected to system");
+ }
+ try {
+ return mSession.getAtr();
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+
+ /**
+ * Close the connection with the Secure Element. This will close any
+ * channels opened by this application with this Secure Element.
+ */
+ public void close() {
+ if (!mService.isConnected()) {
+ Log.e(TAG, "service not connected to system");
+ return;
+ }
+ synchronized (mLock) {
+ try {
+ mSession.close();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error closing session", e);
+ }
+ }
+ }
+
+ /**
+ * Tells if this session is closed.
+ *
+ * @return <code>true</code> if the session is closed, false otherwise.
+ */
+ public boolean isClosed() {
+ try {
+ return mSession.isClosed();
+ } catch (RemoteException e) {
+ // If there was an error here, then the session is considered close
+ return true;
+ }
+ }
+
+ /**
+ * Close any channel opened on this session.
+ */
+ public void closeChannels() {
+ if (!mService.isConnected()) {
+ Log.e(TAG, "service not connected to system");
+ return;
+ }
+
+ synchronized (mLock) {
+ try {
+ mSession.closeChannels();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error closing channels", e);
+ }
+ }
+ }
+
+ /**
+ * Get an access to the basic channel, as defined in the ISO/IEC 7816-4 specification (the
+ * one that has number 0). The obtained object is an instance of the Channel class.
+ * If the AID is null, it means no Applet is to be selected on this channel and the default
+ * Applet is used. If the AID is defined then the corresponding Applet is selected.
+ * Once this channel has been opened by a device application, it is considered as "locked"
+ * by this device application, and other calls to this method will return null, until the
+ * channel is closed. Some Secure Elements (like the UICC) might always keep the basic channel
+ * locked (i.e. return null to applications), to prevent access to the basic channel, while
+ * some other might return a channel object implementing some kind of filtering on the
+ * commands, restricting the set of accepted command to a smaller set.
+ * It is recommended for the UICC to reject the opening of the basic channel to a specific
+ * applet, by always answering null to such a request.
+ * For other Secure Elements, the recommendation is to accept opening the basic channel
+ * on the default applet until another applet is selected on the basic channel. As there is no
+ * other way than a reset to select again the default applet, the implementation of the
+ * transport API should guarantee that the openBasicChannel(null) command will return
+ * null until a reset occurs.
+ * With previous release (V2.05) it was not possible to set P2 value, this value was always
+ * set to '00'.Except for specific needs it is recommended to keep P2 to '00'. It is
+ * recommended that the device allows all values for P2, however only the following values
+ * are mandatory: '00', '04', '08', '0C'(as defined in [2])
+ * The implementation of the underlying SELECT command within this method shall be
+ * based on ISO 7816-4 with following options:
+ * <ul>
+ * <li>CLA = '00'</li>
+ * <li>INS = 'A4'</li>
+ * <li>P1 = '04' (Select by DF name/application identifier)</li>
+ * </ul>
+ *
+ * The select response data can be retrieved with byte[] getSelectResponse().
+ * The API shall handle received status word as follow. If the status word indicates that the
+ * Secure Element was able to open a channel (e.g. status word '90 00' or status words
+ * referencing a warning in ISO-7816-4: '62 XX' or '63 XX') the API shall keep the
+ * channel opened and the next getSelectResponse() shall return the received status
+ * word.
+ * Other received status codes indicating that the Secure Element was able not to open a
+ * channel shall be considered as an error and the corresponding channel shall not be
+ * opened.
+ * The function without P2 as parameter is provided for backwards compatibility and will
+ * fall back to a select command with P2='00'.
+ *
+ * @param aid the AID of the Applet to be selected on this channel, as a
+ * byte array, or null if no Applet is to be selected.
+ * @param p2 the P2 parameter of the SELECT APDU executed on this channel.
+ * @throws IOException if there is a communication problem to the reader or
+ * the Secure Element.
+ * @throws IllegalStateException if the Secure Element session is used after
+ * being closed.
+ * @throws IllegalArgumentException if the aid's length is not within 5 to
+ * 16 (inclusive).
+ * @throws SecurityException if the calling application cannot be granted
+ * access to this AID or the default Applet on this
+ * session.
+ * @throws NoSuchElementException if the AID on the Secure Element is not available or cannot be
+ * selected.
+ * @throws UnsupportedOperationException if the given P2 parameter is not
+ * supported by the device
+ * @return an instance of Channel if available or null.
+ */
+ public @Nullable Channel openBasicChannel(byte[] aid, byte p2) throws IOException {
+ if (!mService.isConnected()) {
+ throw new IllegalStateException("service not connected to system");
+ }
+
+ synchronized (mLock) {
+ try {
+ ISecureElementChannel channel = mSession.openBasicChannel(aid, p2,
+ mReader.getSEService().getListener());
+ if (channel == null) {
+ return null;
+ }
+ return new Channel(mService, this, channel);
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * This method is provided to ease the development of mobile application and for compliancy
+ * with existing applications.
+ * This method is equivalent to openBasicChannel(aid, P2=0x00)
+ *
+ * @param aid the AID of the Applet to be selected on this channel, as a
+ * byte array, or null if no Applet is to be selected.
+ * @throws IOException if there is a communication problem to the reader or
+ * the Secure Element.
+ * @throws IllegalStateException if the Secure Element session is used after
+ * being closed.
+ * @throws IllegalArgumentException if the aid's length is not within 5 to
+ * 16 (inclusive).
+ * @throws SecurityException if the calling application cannot be granted
+ * access to this AID or the default Applet on this
+ * session.
+ * @throws NoSuchElementException if the AID on the Secure Element is not available or cannot be
+ * selected.
+ * @throws UnsupportedOperationException if the given P2 parameter is not
+ * supported by the device
+ * @return an instance of Channel if available or null.
+ */
+ public @Nullable Channel openBasicChannel(byte[] aid) throws IOException {
+ return openBasicChannel(aid, (byte) 0x00);
+ }
+
+ /**
+ * Open a logical channel with the Secure Element, selecting the Applet represented by
+ * the given AID. If the AID is null, which means no Applet is to be selected on this
+ * channel, the default Applet is used. It's up to the Secure Element to choose which
+ * logical channel will be used.
+ * With previous release (V2.05) it was not possible to set P2 value, this value was always
+ * set to '00'.Except for specific needs it is recommended to keep P2 to '00'. It is
+ * recommended that the device allows all values for P2, however only the following values
+ * are mandatory: '00', '04', '08', '0C'(as defined in [2])
+ * The implementation of the underlying SELECT command within this method shall be
+ * based on ISO 7816-4 with following options:
+ *
+ * <ul>
+ * <li>CLA = '01' to '03', '40 to 4F'</li>
+ * <li>INS = 'A4'</li>
+ * <li>P1 = '04' (Select by DF name/application identifier)</li>
+ * </ul>
+ *
+ * The select response data can be retrieved with byte[] getSelectResponse().
+ * The API shall handle received status word as follow. If the status word indicates that the
+ * Secure Element was able to open a channel (e.g. status word '90 00' or status words
+ * referencing a warning in ISO-7816-4: '62 XX' or '63 XX') the API shall keep the
+ * channel opened and the next getSelectResponse() shall return the received status
+ * word.
+ * Other received status codes indicating that the Secure Element was able not to open a
+ * channel shall be considered as an error and the corresponding channel shall not be
+ * opened.
+ * In case of UICC it is recommended for the API to reject the opening of the logical
+ * channel without a specific AID, by always answering null to such a request.
+ * The function without P2 as parameter is provided for backwards compatibility and will
+ * fall back to a select command with P2=00.
+ *
+ * @param aid the AID of the Applet to be selected on this channel, as a
+ * byte array.
+ * @param p2 the P2 parameter of the SELECT APDU executed on this channel.
+ * @throws IOException if there is a communication problem to the reader or
+ * the Secure Element.
+ * @throws IllegalStateException if the Secure Element is used after being
+ * closed.
+ * @throws IllegalArgumentException if the aid's length is not within 5 to
+ * 16 (inclusive).
+ * @throws SecurityException if the calling application cannot be granted
+ * access to this AID or the default Applet on this
+ * session.
+ * @throws NoSuchElementException if the AID on the Secure Element is not
+ * available or cannot be selected or a logical channel is already
+ * open to a non-multiselectable Applet.
+ * @throws UnsupportedOperationException if the given P2 parameter is not
+ * supported by the device.
+ * @return an instance of Channel. Null if the Secure Element is unable to
+ * provide a new logical channel.
+ */
+ public @Nullable Channel openLogicalChannel(byte[] aid, byte p2) throws IOException {
+
+ if ((mReader.getName().startsWith("SIM")) && (aid == null)) {
+ Log.e(TAG, "NULL AID not supported on " + mReader.getName());
+ return null;
+ }
+
+ if (!mService.isConnected()) {
+ throw new IllegalStateException("service not connected to system");
+ }
+ synchronized (mLock) {
+ try {
+ ISecureElementChannel channel = mSession.openLogicalChannel(
+ aid,
+ p2,
+ mReader.getSEService().getListener());
+ if (channel == null) {
+ return null;
+ }
+ return new Channel(mService, this, channel);
+ } catch (RemoteException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * This method is provided to ease the development of mobile application and for compliancy
+ * with existing applications.
+ * This method is equivalent to openLogicalChannel(aid, P2=0x00)
+ *
+ * @param aid the AID of the Applet to be selected on this channel, as a
+ * byte array.
+ * @throws IOException if there is a communication problem to the reader or
+ * the Secure Element.
+ * @throws IllegalStateException if the Secure Element is used after being
+ * closed.
+ * @throws IllegalArgumentException if the aid's length is not within 5 to
+ * 16 (inclusive).
+ * @throws SecurityException if the calling application cannot be granted
+ * access to this AID or the default Applet on this
+ * session.
+ * @throws NoSuchElementException if the AID on the Secure Element is not
+ * available or cannot be selected or a logical channel is already
+ * open to a non-multiselectable Applet.
+ * @throws UnsupportedOperationException if the given P2 parameter is not
+ * supported by the device.
+ * @return an instance of Channel. Null if the Secure Element is unable to
+ * provide a new logical channel.
+ */
+ public @Nullable Channel openLogicalChannel(byte[] aid) throws IOException {
+ return openLogicalChannel(aid, (byte) 0x00);
+ }
+}
diff --git a/core/java/android/security/ConfirmationAlreadyPresentingException.java b/core/java/android/security/ConfirmationAlreadyPresentingException.java
new file mode 100644
index 0000000..ae4ec5a
--- /dev/null
+++ b/core/java/android/security/ConfirmationAlreadyPresentingException.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package android.security;
+
+/**
+ * This exception is thrown when presenting a prompt fails because another prompt is already
+ * being presented.
+ */
+public class ConfirmationAlreadyPresentingException extends Exception {
+ public ConfirmationAlreadyPresentingException() {}
+
+ public ConfirmationAlreadyPresentingException(String message) {
+ super(message);
+ }
+}
diff --git a/core/java/android/security/ConfirmationCallback.java b/core/java/android/security/ConfirmationCallback.java
new file mode 100644
index 0000000..4670bce
--- /dev/null
+++ b/core/java/android/security/ConfirmationCallback.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package android.security;
+
+import android.annotation.NonNull;
+
+/**
+ * Callback class used when signaling that a prompt is no longer being presented.
+ */
+public abstract class ConfirmationCallback {
+ /**
+ * Called when the requested prompt was accepted by the user.
+ *
+ * The format of 'dataThatWasConfirmed' parameter is a <a href="http://cbor.io/">CBOR</a>
+ * encoded map (type 5) with (at least) the keys <strong>prompt</strong> and
+ * <strong>extra</strong>. The keys are encoded as CBOR text string (type 3). The value of
+ * promptText is encoded as CBOR text string (type 3), and the value of extraData is encoded as
+ * CBOR byte string (type 2). Other keys may be added in the future.
+ *
+ * @param dataThatWasConfirmed the data that was confirmed, see above for the format.
+ */
+ public void onConfirmedByUser(@NonNull byte[] dataThatWasConfirmed) {}
+
+ /**
+ * Called when the requested prompt was dismissed (not accepted) by the user.
+ */
+ public void onDismissedByUser() {}
+
+ /**
+ * Called when the requested prompt was dismissed by the application.
+ */
+ public void onDismissedByApplication() {}
+
+ /**
+ * Called when the requested prompt was dismissed because of a low-level error.
+ *
+ * @param e an exception representing the error.
+ */
+ public void onError(Exception e) {}
+}
diff --git a/core/java/android/security/ConfirmationDialog.java b/core/java/android/security/ConfirmationDialog.java
new file mode 100644
index 0000000..e9df370
--- /dev/null
+++ b/core/java/android/security/ConfirmationDialog.java
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ */
+
+package android.security;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.Locale;
+import java.util.concurrent.Executor;
+
+/**
+ * Class used for displaying confirmation prompts.
+ *
+ * <p>Confirmation prompts are prompts shown to the user to confirm a given text and are
+ * implemented in a way that a positive response indicates with high confidence that the user has
+ * seen the given text, even if the Android framework (including the kernel) was
+ * compromised. Implementing confirmation prompts with these guarantees requires dedicated
+ * hardware-support and may not always be available.
+ *
+ * <p>Confirmation prompts are typically used with an external entitity - the <i>Relying Party</i> -
+ * in the following way. The setup steps are as follows:
+ * <ul>
+ * <li> Before first use, the application generates a key-pair with the
+ * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserConfirmationRequired
+ * CONFIRMATION tag} set. Device attestation,
+ * e.g. {@link java.security.KeyStore#getCertificateChain getCertificateChain()}, is used to
+ * generate a certificate chain that includes the public key (<code>Kpub</code> in the following)
+ * of the newly generated key.
+ * <li> The application sends <code>Kpub</code> and the certificate chain resulting from device
+ * attestation to the <i>Relying Party</i>.
+ * <li> The <i>Relying Party</i> validates the certificate chain which involves checking the root
+ * certificate is what is expected (e.g. a certificate from Google), each certificate signs the
+ * next one in the chain, ending with <code>Kpub</code>, and that the attestation certificate
+ * asserts that <code>Kpub</code> has the
+ * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserConfirmationRequired
+ * CONFIRMATION tag} set.
+ * Additionally the relying party stores <code>Kpub</code> and associates it with the device
+ * it was received from.
+ * </ul>
+ *
+ * <p>The <i>Relying Party</i> is typically an external device (for example connected via
+ * Bluetooth) or application server.
+ *
+ * <p>Before executing a transaction which requires a high assurance of user content, the
+ * application does the following:
+ * <ul>
+ * <li> The application gets a cryptographic nonce from the <i>Relying Party</i> and passes this as
+ * the <code>extraData</code> (via the Builder helper class) to the
+ * {@link #presentPrompt presentPrompt()} method. The <i>Relying Party</i> stores the nonce locally
+ * since it'll use it in a later step.
+ * <li> If the user approves the prompt a <i>Confirmation Response</i> is returned in the
+ * {@link ConfirmationCallback#onConfirmedByUser onConfirmedByUser(byte[])} callback as the
+ * <code>dataThatWasConfirmed</code> parameter. This blob contains the text that was shown to the
+ * user, the <code>extraData</code> parameter, and possibly other data.
+ * <li> The application signs the <i>Confirmation Response</i> with the previously created key and
+ * sends the blob and the signature to the <i>Relying Party</i>.
+ * <li> The <i>Relying Party</i> checks that the signature was made with <code>Kpub</code> and then
+ * extracts <code>promptText</code> matches what is expected and <code>extraData</code> matches the
+ * previously created nonce. If all checks passes, the transaction is executed.
+ * </ul>
+ *
+ * <p>A common way of implementing the "<code>promptText</code> is what is expected" check in the
+ * last bullet, is to have the <i>Relying Party</i> generate <code>promptText</code> and store it
+ * along the nonce in the <code>extraData</code> blob.
+ */
+public class ConfirmationDialog {
+ private static final String TAG = "ConfirmationDialog";
+
+ private CharSequence mPromptText;
+ private byte[] mExtraData;
+ private ConfirmationCallback mCallback;
+ private Executor mExecutor;
+
+ private final KeyStore mKeyStore = KeyStore.getInstance();
+
+ private void doCallback(int responseCode, byte[] dataThatWasConfirmed,
+ ConfirmationCallback callback) {
+ switch (responseCode) {
+ case KeyStore.CONFIRMATIONUI_OK:
+ callback.onConfirmedByUser(dataThatWasConfirmed);
+ break;
+
+ case KeyStore.CONFIRMATIONUI_CANCELED:
+ callback.onDismissedByUser();
+ break;
+
+ case KeyStore.CONFIRMATIONUI_ABORTED:
+ callback.onDismissedByApplication();
+ break;
+
+ case KeyStore.CONFIRMATIONUI_SYSTEM_ERROR:
+ callback.onError(new Exception("System error returned by ConfirmationUI."));
+ break;
+
+ default:
+ callback.onError(new Exception("Unexpected responseCode=" + responseCode
+ + " from onConfirmtionPromptCompleted() callback."));
+ break;
+ }
+ }
+
+ private final android.os.IBinder mCallbackBinder =
+ new android.security.IConfirmationPromptCallback.Stub() {
+ @Override
+ public void onConfirmationPromptCompleted(
+ int responseCode, final byte[] dataThatWasConfirmed)
+ throws android.os.RemoteException {
+ if (mCallback != null) {
+ ConfirmationCallback callback = mCallback;
+ Executor executor = mExecutor;
+ mCallback = null;
+ mExecutor = null;
+ if (executor == null) {
+ doCallback(responseCode, dataThatWasConfirmed, callback);
+ } else {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ doCallback(responseCode, dataThatWasConfirmed, callback);
+ }
+ });
+ }
+ }
+ }
+ };
+
+ /**
+ * A builder that collects arguments, to be shown on the system-provided confirmation dialog.
+ */
+ public static class Builder {
+
+ private CharSequence mPromptText;
+ private byte[] mExtraData;
+
+ /**
+ * Creates a builder for the confirmation dialog.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Sets the prompt text for the dialog.
+ *
+ * @param promptText the text to present in the prompt.
+ * @return the builder.
+ */
+ public Builder setPromptText(CharSequence promptText) {
+ mPromptText = promptText;
+ return this;
+ }
+
+ /**
+ * Sets the extra data for the dialog.
+ *
+ * @param extraData data to include in the response data.
+ * @return the builder.
+ */
+ public Builder setExtraData(byte[] extraData) {
+ mExtraData = extraData;
+ return this;
+ }
+
+ /**
+ * Creates a {@link ConfirmationDialog} with the arguments supplied to this builder.
+ *
+ * @param context the application context
+ * @return a {@link ConfirmationDialog}
+ * @throws IllegalArgumentException if any of the required fields are not set.
+ */
+ public ConfirmationDialog build(Context context) {
+ if (TextUtils.isEmpty(mPromptText)) {
+ throw new IllegalArgumentException("prompt text must be set and non-empty");
+ }
+ if (mExtraData == null) {
+ throw new IllegalArgumentException("extraData must be set");
+ }
+ return new ConfirmationDialog(mPromptText, mExtraData);
+ }
+ }
+
+ private ConfirmationDialog(CharSequence promptText, byte[] extraData) {
+ mPromptText = promptText;
+ mExtraData = extraData;
+ }
+
+ /**
+ * Requests a confirmation prompt to be presented to the user.
+ *
+ * When the prompt is no longer being presented, one of the methods in
+ * {@link ConfirmationCallback} is called on the supplied callback object.
+ *
+ * @param executor the executor identifying the thread that will receive the callback.
+ * @param callback the callback to use when the dialog is done showing.
+ * @throws IllegalArgumentException if the prompt text is too long or malfomed.
+ * @throws ConfirmationAlreadyPresentingException if another prompt is being presented.
+ * @throws ConfirmationNotAvailableException if confirmation prompts are not supported.
+ */
+ public void presentPrompt(@NonNull Executor executor, @NonNull ConfirmationCallback callback)
+ throws ConfirmationAlreadyPresentingException,
+ ConfirmationNotAvailableException {
+ if (mCallback != null) {
+ throw new ConfirmationAlreadyPresentingException();
+ }
+ mCallback = callback;
+ mExecutor = executor;
+
+ int uiOptionsAsFlags = 0;
+ // TODO: set AccessibilityInverted, AccessibilityMagnified in uiOptionsAsFlags as needed.
+ String locale = Locale.getDefault().toLanguageTag();
+ int responseCode = mKeyStore.presentConfirmationPrompt(
+ mCallbackBinder, mPromptText.toString(), mExtraData, locale, uiOptionsAsFlags);
+ switch (responseCode) {
+ case KeyStore.CONFIRMATIONUI_OK:
+ return;
+
+ case KeyStore.CONFIRMATIONUI_OPERATION_PENDING:
+ throw new ConfirmationAlreadyPresentingException();
+
+ case KeyStore.CONFIRMATIONUI_UNIMPLEMENTED:
+ throw new ConfirmationNotAvailableException();
+
+ case KeyStore.CONFIRMATIONUI_UIERROR:
+ throw new IllegalArgumentException();
+
+ default:
+ // Unexpected error code.
+ Log.w(TAG,
+ "Unexpected responseCode=" + responseCode
+ + " from presentConfirmationPrompt() call.");
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Cancels a prompt currently being displayed.
+ *
+ * On success, the
+ * {@link ConfirmationCallback#onDismissedByApplication onDismissedByApplication()} method on
+ * the supplied callback object will be called asynchronously.
+ *
+ * @throws IllegalStateException if no prompt is currently being presented.
+ */
+ public void cancelPrompt() {
+ int responseCode = mKeyStore.cancelConfirmationPrompt(mCallbackBinder);
+ if (responseCode == KeyStore.CONFIRMATIONUI_OK) {
+ return;
+ } else if (responseCode == KeyStore.CONFIRMATIONUI_OPERATION_PENDING) {
+ throw new IllegalStateException();
+ } else {
+ // Unexpected error code.
+ Log.w(TAG,
+ "Unexpected responseCode=" + responseCode
+ + " from cancelConfirmationPrompt() call.");
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Checks if the device supports confirmation prompts.
+ *
+ * @return true if confirmation prompts are supported by the device.
+ */
+ public static boolean isSupported() {
+ // TODO: read and return system property.
+ return true;
+ }
+}
diff --git a/core/java/android/security/ConfirmationNotAvailableException.java b/core/java/android/security/ConfirmationNotAvailableException.java
new file mode 100644
index 0000000..8d0e672
--- /dev/null
+++ b/core/java/android/security/ConfirmationNotAvailableException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+package android.security;
+
+/**
+ * This exception is thrown when presenting a prompt fails because the the environment lacks
+ * facilities for showing confirmations.
+ */
+public class ConfirmationNotAvailableException extends Exception {
+ public ConfirmationNotAvailableException() {
+ }
+
+ public ConfirmationNotAvailableException(String message) {
+ super(message);
+ }
+}
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 3464370..1d13335 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -74,6 +74,7 @@
public static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505;
public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507;
+ public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508;
public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
diff --git a/core/java/android/security/keystore/RecoveryController.java b/core/java/android/security/keystore/RecoveryController.java
index 8be6d52..98e6a20 100644
--- a/core/java/android/security/keystore/RecoveryController.java
+++ b/core/java/android/security/keystore/RecoveryController.java
@@ -167,7 +167,7 @@
public @NonNull KeychainSnapshot getRecoveryData(@NonNull byte[] account)
throws InternalRecoveryServiceException {
try {
- return BackwardsCompat.toLegacyKeychainSnapshot(mBinder.getRecoveryData(account));
+ return BackwardsCompat.toLegacyKeychainSnapshot(mBinder.getKeyChainSnapshot());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
diff --git a/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
index a43952a..aa09f10 100644
--- a/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
+++ b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
@@ -235,17 +235,7 @@
}
/**
- * Removes secret from memory than object is no longer used.
- * Since finalizer call is not reliable, please use @link {#clearSecret} directly.
- */
- @Override
- protected void finalize() throws Throwable {
- clearSecret();
- super.finalize();
- }
-
- /**
- * Fills mSecret with zeroes.
+ * Fills secret with zeroes.
*/
public void clearSecret() {
Arrays.fill(mSecret, (byte) 0);
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
index 71a36f1..4e4a037 100644
--- a/core/java/android/security/keystore/recovery/RecoveryController.java
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -171,6 +171,8 @@
}
/**
+ * Deprecated - use getKeyChainSnapshot.
+ *
* Returns data necessary to store all recoverable keys. Key material is
* encrypted with user secret and recovery public key.
*
@@ -179,10 +181,35 @@
* service.
*/
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
- public @NonNull KeyChainSnapshot getRecoveryData()
+ public @Nullable KeyChainSnapshot getRecoveryData()
throws InternalRecoveryServiceException {
try {
- return mBinder.getRecoveryData(/*account=*/ new byte[]{});
+ return mBinder.getKeyChainSnapshot();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode == ERROR_NO_SNAPSHOT_PENDING) {
+ return null;
+ }
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Returns data necessary to store all recoverable keys. Key material is
+ * encrypted with user secret and recovery public key.
+ *
+ * @return Data necessary to recover keystore or {@code null} if snapshot is not available.
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+ public @Nullable KeyChainSnapshot getKeyChainSnapshot()
+ throws InternalRecoveryServiceException {
+ try {
+ return mBinder.getKeyChainSnapshot();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 917efa8..12aa64e 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -468,9 +468,8 @@
* <p>Typically, field classification can be used to detect fields that can be autofilled with
* user data that is not associated with a specific app—such as email and physical
* address. Once the service identifies that a such field was manually filled by the user, the
- * service could use this signal to improve its heuristics, either locally (i.e., in the same
- * device) or globally (i.e., by crowdsourcing the results back to the service's server so it can
- * be used by other users).
+ * service could use this signal to improve its heuristics on subsequent requests (for example, by
+ * infering which resource ids are associated with known fields).
*
* <p>The field classification workflow involves 4 steps:
*
@@ -481,8 +480,8 @@
* <li>Identify which fields should be analysed by calling
* {@link FillResponse.Builder#setFieldClassificationIds(AutofillId...)}.
* <li>Verify the results through {@link FillEventHistory.Event#getFieldsClassification()}.
- * <li>Use the results to dynamically create {@link Dataset} or {@link SaveInfo} objects in future
- * requests.
+ * <li>Use the results to dynamically create {@link Dataset} or {@link SaveInfo} objects in
+ * subsequent requests.
* </ol>
*
* <p>The field classification is an expensive operation and should be used carefully, otherwise it
diff --git a/core/java/android/service/autofill/AutofillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java
index 5c7388f..4f2f6cb 100644
--- a/core/java/android/service/autofill/AutofillServiceInfo.java
+++ b/core/java/android/service/autofill/AutofillServiceInfo.java
@@ -25,16 +25,20 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
+import android.metrics.LogMaker;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
import com.android.internal.R;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
/**
@@ -91,10 +95,20 @@
private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si) {
// Check for permissions.
if (!Manifest.permission.BIND_AUTOFILL_SERVICE.equals(si.permission)) {
- Log.w(TAG, "AutofillService from '" + si.packageName + "' does not require permission "
- + Manifest.permission.BIND_AUTOFILL_SERVICE);
- throw new SecurityException("Service does not require permission "
- + Manifest.permission.BIND_AUTOFILL_SERVICE);
+ if (Manifest.permission.BIND_AUTOFILL.equals(si.permission)) {
+ // Let it go for now...
+ Log.w(TAG, "AutofillService from '" + si.packageName + "' uses unsupported "
+ + "permission " + Manifest.permission.BIND_AUTOFILL + ". It works for "
+ + "now, but might not be supported on future releases");
+ new MetricsLogger().write(new LogMaker(MetricsEvent.AUTOFILL_INVALID_PERMISSION)
+ .setPackageName(si.packageName));
+ } else {
+ Log.w(TAG, "AutofillService from '" + si.packageName
+ + "' does not require permission "
+ + Manifest.permission.BIND_AUTOFILL_SERVICE);
+ throw new SecurityException("Service does not require permission "
+ + Manifest.permission.BIND_AUTOFILL_SERVICE);
+ }
}
// Get the AutoFill metadata, if declared.
diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java
index b8e8b19..fb468a8 100644
--- a/core/java/android/service/autofill/CustomDescription.java
+++ b/core/java/android/service/autofill/CustomDescription.java
@@ -173,7 +173,10 @@
}
/**
- * Updates the {@link RemoteViews presentation template} when a condition is satisfied.
+ * Updates the {@link RemoteViews presentation template} when a condition is satisfied by
+ * applying a series of remote view operations. This allows dynamic customization of the
+ * portion of the save UI that is controlled by the autofill service. Such dynamic
+ * customization is based on the content of target views.
*
* <p>The updates are applied in the sequence they are added, after the
* {@link #addChild(int, Transformation) transformations} are applied to the children
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index 266bcda..f32dee1 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -29,7 +29,6 @@
import com.android.internal.util.Preconditions;
-import java.io.Serializable;
import java.util.ArrayList;
import java.util.regex.Pattern;
@@ -99,7 +98,7 @@
private final ArrayList<AutofillId> mFieldIds;
private final ArrayList<AutofillValue> mFieldValues;
private final ArrayList<RemoteViews> mFieldPresentations;
- private final ArrayList<Pattern> mFieldFilters;
+ private final ArrayList<DatasetFieldFilter> mFieldFilters;
private final RemoteViews mPresentation;
private final IntentSender mAuthentication;
@Nullable String mId;
@@ -132,7 +131,7 @@
/** @hide */
@Nullable
- public Pattern getFilter(int index) {
+ public DatasetFieldFilter getFilter(int index) {
return mFieldFilters.get(index);
}
@@ -189,7 +188,7 @@
private ArrayList<AutofillId> mFieldIds;
private ArrayList<AutofillValue> mFieldValues;
private ArrayList<RemoteViews> mFieldPresentations;
- private ArrayList<Pattern> mFieldFilters;
+ private ArrayList<DatasetFieldFilter> mFieldFilters;
private RemoteViews mPresentation;
private IntentSender mAuthentication;
private boolean mDestroyed;
@@ -363,19 +362,21 @@
* @param value the value to be autofilled. Pass {@code null} if you do not have the value
* but the target view is a logical part of the dataset. For example, if
* the dataset needs authentication and you have no access to the value.
- * @param filter regex used to determine if the dataset should be shown in the autofill UI.
+ * @param filter regex used to determine if the dataset should be shown in the autofill UI;
+ * when {@code null}, it disables filtering on that dataset (this is the recommended
+ * approach when {@code value} is not {@code null} and field contains sensitive data
+ * such as passwords).
*
* @return this builder.
* @throws IllegalStateException if the builder was constructed without a
* {@link RemoteViews presentation}.
*/
public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value,
- @NonNull Pattern filter) {
+ @Nullable Pattern filter) {
throwIfDestroyed();
- Preconditions.checkNotNull(filter, "filter cannot be null");
Preconditions.checkState(mPresentation != null,
"Dataset presentation not set on constructor");
- setLifeTheUniverseAndEverything(id, value, null, filter);
+ setLifeTheUniverseAndEverything(id, value, null, new DatasetFieldFilter(filter));
return this;
}
@@ -398,23 +399,26 @@
* @param value the value to be autofilled. Pass {@code null} if you do not have the value
* but the target view is a logical part of the dataset. For example, if
* the dataset needs authentication and you have no access to the value.
+ * @param filter regex used to determine if the dataset should be shown in the autofill UI;
+ * when {@code null}, it disables filtering on that dataset (this is the recommended
+ * approach when {@code value} is not {@code null} and field contains sensitive data
+ * such as passwords).
* @param presentation the presentation used to visualize this field.
- * @param filter regex used to determine if the dataset should be shown in the autofill UI.
*
* @return this builder.
*/
public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value,
- @NonNull Pattern filter, @NonNull RemoteViews presentation) {
+ @Nullable Pattern filter, @NonNull RemoteViews presentation) {
throwIfDestroyed();
- Preconditions.checkNotNull(filter, "filter cannot be null");
Preconditions.checkNotNull(presentation, "presentation cannot be null");
- setLifeTheUniverseAndEverything(id, value, presentation, filter);
+ setLifeTheUniverseAndEverything(id, value, presentation,
+ new DatasetFieldFilter(filter));
return this;
}
private void setLifeTheUniverseAndEverything(@NonNull AutofillId id,
@Nullable AutofillValue value, @Nullable RemoteViews presentation,
- @Nullable Pattern filter) {
+ @Nullable DatasetFieldFilter filter) {
Preconditions.checkNotNull(id, "id cannot be null");
if (mFieldIds != null) {
final int existingIdx = mFieldIds.indexOf(id);
@@ -477,8 +481,8 @@
parcel.writeParcelable(mPresentation, flags);
parcel.writeTypedList(mFieldIds, flags);
parcel.writeTypedList(mFieldValues, flags);
- parcel.writeParcelableList(mFieldPresentations, flags);
- parcel.writeSerializable(mFieldFilters);
+ parcel.writeTypedList(mFieldPresentations, flags);
+ parcel.writeTypedList(mFieldFilters, flags);
parcel.writeParcelable(mAuthentication, flags);
parcel.writeString(mId);
}
@@ -493,22 +497,19 @@
final Builder builder = (presentation == null)
? new Builder()
: new Builder(presentation);
- final ArrayList<AutofillId> ids = parcel.createTypedArrayList(AutofillId.CREATOR);
+ final ArrayList<AutofillId> ids =
+ parcel.createTypedArrayList(AutofillId.CREATOR);
final ArrayList<AutofillValue> values =
parcel.createTypedArrayList(AutofillValue.CREATOR);
- final ArrayList<RemoteViews> presentations = new ArrayList<>();
- parcel.readParcelableList(presentations, null);
- @SuppressWarnings("unchecked")
- final ArrayList<Serializable> filters =
- (ArrayList<Serializable>) parcel.readSerializable();
- final int idCount = (ids != null) ? ids.size() : 0;
- final int valueCount = (values != null) ? values.size() : 0;
- for (int i = 0; i < idCount; i++) {
+ final ArrayList<RemoteViews> presentations =
+ parcel.createTypedArrayList(RemoteViews.CREATOR);
+ final ArrayList<DatasetFieldFilter> filters =
+ parcel.createTypedArrayList(DatasetFieldFilter.CREATOR);
+ for (int i = 0; i < ids.size(); i++) {
final AutofillId id = ids.get(i);
- final AutofillValue value = (valueCount > i) ? values.get(i) : null;
- final RemoteViews fieldPresentation = presentations.isEmpty() ? null
- : presentations.get(i);
- final Pattern filter = (Pattern) filters.get(i);
+ final AutofillValue value = values.get(i);
+ final RemoteViews fieldPresentation = presentations.get(i);
+ final DatasetFieldFilter filter = filters.get(i);
builder.setLifeTheUniverseAndEverything(id, value, fieldPresentation, filter);
}
builder.setAuthentication(parcel.readParcelable(null));
@@ -521,4 +522,55 @@
return new Dataset[size];
}
};
+
+ /**
+ * Helper class used to indicate when the service explicitly set a {@link Pattern} filter for a
+ * dataset field‐ we cannot use a {@link Pattern} directly because then we wouldn't be
+ * able to differentiate whether the service explicitly passed a {@code null} filter to disable
+ * filter, or when it called the methods that does not take a filter {@link Pattern}.
+ *
+ * @hide
+ */
+ public static final class DatasetFieldFilter implements Parcelable {
+
+ @Nullable
+ public final Pattern pattern;
+
+ private DatasetFieldFilter(@Nullable Pattern pattern) {
+ this.pattern = pattern;
+ }
+
+ @Override
+ public String toString() {
+ if (!sDebug) return super.toString();
+
+ // Cannot log pattern because it could contain PII
+ return pattern == null ? "null" : pattern.pattern().length() + "_chars";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeSerializable(pattern);
+ }
+
+ @SuppressWarnings("hiding")
+ public static final Creator<DatasetFieldFilter> CREATOR =
+ new Creator<DatasetFieldFilter>() {
+
+ @Override
+ public DatasetFieldFilter createFromParcel(Parcel parcel) {
+ return new DatasetFieldFilter((Pattern) parcel.readSerializable());
+ }
+
+ @Override
+ public DatasetFieldFilter[] newArray(int size) {
+ return new DatasetFieldFilter[size];
+ }
+ };
+ }
}
diff --git a/core/java/android/service/autofill/DateTransformation.java b/core/java/android/service/autofill/DateTransformation.java
new file mode 100644
index 0000000..4e1425d
--- /dev/null
+++ b/core/java/android/service/autofill/DateTransformation.java
@@ -0,0 +1,127 @@
+/*
+ * 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.service.autofill;
+
+import static android.view.autofill.Helper.sDebug;
+
+import android.annotation.NonNull;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+import android.widget.RemoteViews;
+import android.widget.TextView;
+
+import com.android.internal.util.Preconditions;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+/**
+ * Replaces a {@link TextView} child of a {@link CustomDescription} with the contents of a field
+ * that is expected to have a {@link AutofillValue#forDate(long) date value}.
+ *
+ * <p>For example, a transformation to display a credit card expiration date as month/year would be:
+ *
+ * <pre class="prettyprint">
+ * new DateTransformation(ccExpDate, new java.text.SimpleDateFormat("MM/yyyy")
+ * </pre>
+ */
+public final class DateTransformation extends InternalTransformation implements
+ Transformation, Parcelable {
+ private static final String TAG = "DateTransformation";
+
+ private final AutofillId mFieldId;
+ private final DateFormat mDateFormat;
+
+ /**
+ * Creates a new transformation.
+ *
+ * @param id id of the screen field.
+ * @param dateFormat object used to transform the date value of the field to a String.
+ */
+ public DateTransformation(@NonNull AutofillId id, @NonNull DateFormat dateFormat) {
+ mFieldId = Preconditions.checkNotNull(id);
+ mDateFormat = Preconditions.checkNotNull(dateFormat);
+ }
+
+ /** @hide */
+ @Override
+ @TestApi
+ public void apply(@NonNull ValueFinder finder, @NonNull RemoteViews parentTemplate,
+ int childViewId) throws Exception {
+ final AutofillValue value = finder.findRawValueByAutofillId(mFieldId);
+ if (value == null) {
+ Log.w(TAG, "No value for id " + mFieldId);
+ return;
+ }
+ if (!value.isDate()) {
+ Log.w(TAG, "Value for " + mFieldId + " is not date: " + value);
+ return;
+ }
+
+ try {
+ final Date date = new Date(value.getDateValue());
+ final String transformed = mDateFormat.format(date);
+ if (sDebug) Log.d(TAG, "Transformed " + date + " to " + transformed);
+
+ parentTemplate.setCharSequence(childViewId, "setText", transformed);
+ } catch (Exception e) {
+ Log.w(TAG, "Could not apply " + mDateFormat + " to " + value + ": " + e);
+ }
+ }
+
+ /////////////////////////////////////
+ // Object "contract" methods. //
+ /////////////////////////////////////
+ @Override
+ public String toString() {
+ if (!sDebug) return super.toString();
+
+ return "DateTransformation: [id=" + mFieldId + ", format=" + mDateFormat + "]";
+ }
+
+ /////////////////////////////////////
+ // Parcelable "contract" methods. //
+ /////////////////////////////////////
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeParcelable(mFieldId, flags);
+ parcel.writeSerializable(mDateFormat);
+ }
+
+ public static final Parcelable.Creator<DateTransformation> CREATOR =
+ new Parcelable.Creator<DateTransformation>() {
+ @Override
+ public DateTransformation createFromParcel(Parcel parcel) {
+ return new DateTransformation(parcel.readParcelable(null),
+ (DateFormat) parcel.readSerializable());
+ }
+
+ @Override
+ public DateTransformation[] newArray(int size) {
+ return new DateTransformation[size];
+ }
+ };
+}
diff --git a/core/java/android/service/autofill/DateValueSanitizer.java b/core/java/android/service/autofill/DateValueSanitizer.java
new file mode 100644
index 0000000..0f7b540
--- /dev/null
+++ b/core/java/android/service/autofill/DateValueSanitizer.java
@@ -0,0 +1,123 @@
+/*
+ * 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.service.autofill;
+
+import static android.view.autofill.Helper.sDebug;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import android.view.autofill.AutofillValue;
+
+import com.android.internal.util.Preconditions;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+/**
+ * Sanitizes a date {@link AutofillValue} using a {@link DateFormat}.
+ *
+ * <p>For example, to sanitize a credit card expiration date to just its month and year:
+ *
+ * <pre class="prettyprint">
+ * new DateValueSanitizer(new java.text.SimpleDateFormat("MM/yyyy");
+ * </pre>
+ */
+public final class DateValueSanitizer extends InternalSanitizer implements Sanitizer, Parcelable {
+
+ private static final String TAG = "DateValueSanitizer";
+
+ private final DateFormat mDateFormat;
+
+ /**
+ * Default constructor.
+ *
+ * @param dateFormat date format applied to the actual date value of an input field.
+ */
+ public DateValueSanitizer(@NonNull DateFormat dateFormat) {
+ mDateFormat = Preconditions.checkNotNull(dateFormat);
+ }
+
+ /** @hide */
+ @Override
+ @TestApi
+ @Nullable
+ public AutofillValue sanitize(@NonNull AutofillValue value) {
+ if (value == null) {
+ Log.w(TAG, "sanitize() called with null value");
+ return null;
+ }
+ if (!value.isDate()) {
+ if (sDebug) Log.d(TAG, value + " is not a date");
+ return null;
+ }
+
+ try {
+ final Date date = new Date(value.getDateValue());
+
+ // First convert it to string
+ final String converted = mDateFormat.format(date);
+ if (sDebug) Log.d(TAG, "Transformed " + date + " to " + converted);
+ // Then parse it back to date
+ final Date sanitized = mDateFormat.parse(converted);
+ if (sDebug) Log.d(TAG, "Sanitized to " + sanitized);
+ return AutofillValue.forDate(sanitized.getTime());
+ } catch (Exception e) {
+ Log.w(TAG, "Could not apply " + mDateFormat + " to " + value + ": " + e);
+ return null;
+ }
+ }
+
+ /////////////////////////////////////
+ // Object "contract" methods. //
+ /////////////////////////////////////
+ @Override
+ public String toString() {
+ if (!sDebug) return super.toString();
+
+ return "DateValueSanitizer: [dateFormat=" + mDateFormat + "]";
+ }
+
+ /////////////////////////////////////
+ // Parcelable "contract" methods. //
+ /////////////////////////////////////
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeSerializable(mDateFormat);
+ }
+
+ public static final Parcelable.Creator<DateValueSanitizer> CREATOR =
+ new Parcelable.Creator<DateValueSanitizer>() {
+ @Override
+ public DateValueSanitizer createFromParcel(Parcel parcel) {
+ return new DateValueSanitizer((DateFormat) parcel.readSerializable());
+ }
+
+ @Override
+ public DateValueSanitizer[] newArray(int size) {
+ return new DateValueSanitizer[size];
+ }
+ };
+}
diff --git a/core/java/android/service/autofill/UserData.java b/core/java/android/service/autofill/UserData.java
index 9017848..6bab6aa 100644
--- a/core/java/android/service/autofill/UserData.java
+++ b/core/java/android/service/autofill/UserData.java
@@ -30,6 +30,7 @@
import android.os.Parcelable;
import android.provider.Settings;
import android.service.autofill.FieldClassification.Match;
+import android.text.TextUtils;
import android.util.Log;
import android.view.autofill.AutofillManager;
import android.view.autofill.Helper;
@@ -52,12 +53,14 @@
private static final int DEFAULT_MIN_VALUE_LENGTH = 5;
private static final int DEFAULT_MAX_VALUE_LENGTH = 100;
+ private final String mId;
private final String mAlgorithm;
private final Bundle mAlgorithmArgs;
private final String[] mRemoteIds;
private final String[] mValues;
private UserData(Builder builder) {
+ mId = builder.mId;
mAlgorithm = builder.mAlgorithm;
mAlgorithmArgs = builder.mAlgorithmArgs;
mRemoteIds = new String[builder.mRemoteIds.size()];
@@ -75,6 +78,13 @@
return mAlgorithm;
}
+ /**
+ * Gets the id.
+ */
+ public String getId() {
+ return mId;
+ }
+
/** @hide */
public Bundle getAlgorithmArgs() {
return mAlgorithmArgs;
@@ -92,6 +102,7 @@
/** @hide */
public void dump(String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.print("id: "); pw.print(mId);
pw.print(prefix); pw.print("Algorithm: "); pw.print(mAlgorithm);
pw.print(" Args: "); pw.println(mAlgorithmArgs);
@@ -121,6 +132,7 @@
* A builder for {@link UserData} objects.
*/
public static final class Builder {
+ private final String mId;
private final ArrayList<String> mRemoteIds;
private final ArrayList<String> mValues;
private String mAlgorithm;
@@ -131,16 +143,28 @@
* Creates a new builder for the user data used for <a href="#FieldClassification">field
* classification</a>.
*
+ * <p>The user data must contain at least one pair of {@code remoteId} -> {@code value}, and
+ * more pairs can be added through the {@link #add(String, String)} method.
+ *
+ * @param id id used to identify the whole {@link UserData} object. This id is also returned
+ * by {@link AutofillManager#getUserDataId()}, which can be used to check if the
+ * {@link UserData} is up-to-date without fetching the whole object (through
+ * {@link AutofillManager#getUserData()}).
+ * @param remoteId unique string used to identify a user data value.
+ * @param value value of the user data.
+ *
* @throws IllegalArgumentException if any of the following occurs:
* <ol>
+ * <li>{@code id} is empty
* <li>{@code remoteId} is empty
* <li>{@code value} is empty
* <li>the length of {@code value} is lower than {@link UserData#getMinValueLength()}
* <li>the length of {@code value} is higher than {@link UserData#getMaxValueLength()}
* </ol>
*/
- public Builder(@NonNull String remoteId, @NonNull String value) {
- checkValidRemoteId(remoteId);
+ public Builder(@NonNull String id, @NonNull String remoteId, @NonNull String value) {
+ mId = checkNotEmpty("id", id);
+ checkNotEmpty("remoteId", remoteId);
checkValidValue(value);
final int capacity = getMaxUserDataSize();
mRemoteIds = new ArrayList<>(capacity);
@@ -188,7 +212,7 @@
*/
public Builder add(@NonNull String remoteId, @NonNull String value) {
throwIfDestroyed();
- checkValidRemoteId(remoteId);
+ checkNotEmpty("remoteId", remoteId);
checkValidValue(value);
Preconditions.checkState(!mRemoteIds.contains(remoteId),
@@ -205,9 +229,10 @@
return this;
}
- private void checkValidRemoteId(@Nullable String remoteId) {
- Preconditions.checkNotNull(remoteId);
- Preconditions.checkArgument(!remoteId.isEmpty(), "remoteId cannot be empty");
+ private String checkNotEmpty(@NonNull String name, @Nullable String value) {
+ Preconditions.checkNotNull(value);
+ Preconditions.checkArgument(!TextUtils.isEmpty(value), "%s cannot be empty", name);
+ return value;
}
private void checkValidValue(@Nullable String value) {
@@ -246,7 +271,8 @@
public String toString() {
if (!sDebug) return super.toString();
- final StringBuilder builder = new StringBuilder("UserData: [algorithm=").append(mAlgorithm);
+ final StringBuilder builder = new StringBuilder("UserData: [id=").append(mId)
+ .append(", algorithm=").append(mAlgorithm);
// Cannot disclose remote ids or values because they could contain PII
builder.append(", remoteIds=");
Helper.appendRedacted(builder, mRemoteIds);
@@ -266,6 +292,7 @@
@Override
public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeString(mId);
parcel.writeStringArray(mRemoteIds);
parcel.writeStringArray(mValues);
parcel.writeString(mAlgorithm);
@@ -279,9 +306,10 @@
// Always go through the builder to ensure the data ingested by
// the system obeys the contract of the builder to avoid attacks
// using specially crafted parcels.
+ final String id = parcel.readString();
final String[] remoteIds = parcel.readStringArray();
final String[] values = parcel.readStringArray();
- final Builder builder = new Builder(remoteIds[0], values[0])
+ final Builder builder = new Builder(id, remoteIds[0], values[0])
.setFieldClassificationAlgorithm(parcel.readString(), parcel.readBundle());
for (int i = 1; i < remoteIds.length; i++) {
builder.add(remoteIds[i], values[i]);
diff --git a/core/java/android/service/autofill/ValueFinder.java b/core/java/android/service/autofill/ValueFinder.java
index 1705b7d..7f195d6 100644
--- a/core/java/android/service/autofill/ValueFinder.java
+++ b/core/java/android/service/autofill/ValueFinder.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
/**
* Helper object used to obtain the value of a field in the screen being autofilled.
@@ -29,7 +30,17 @@
public interface ValueFinder {
/**
+ * Gets the value of a field as String, or {@code null} when not found.
+ */
+ @Nullable
+ default String findByAutofillId(@NonNull AutofillId id) {
+ final AutofillValue value = findRawValueByAutofillId(id);
+ return (value == null || !value.isText()) ? null : value.getTextValue().toString();
+ }
+
+ /**
* Gets the value of a field, or {@code null} when not found.
*/
- @Nullable String findByAutofillId(@NonNull AutofillId id);
+ @Nullable
+ AutofillValue findRawValueByAutofillId(@NonNull AutofillId id);
}
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 2a352ad..b6c6bdc 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -18,11 +18,11 @@
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.app.AutomaticZenRule;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.proto.ProtoOutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -161,6 +161,22 @@
.append(']').toString();
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ // id is guarantreed not to be null.
+ proto.write(ConditionProto.ID, id.toString());
+ proto.write(ConditionProto.SUMMARY, summary);
+ proto.write(ConditionProto.LINE_1, line1);
+ proto.write(ConditionProto.LINE_2, line2);
+ proto.write(ConditionProto.ICON, icon);
+ proto.write(ConditionProto.STATE, state);
+ proto.write(ConditionProto.FLAGS, flags);
+
+ proto.end(token);
+ }
+
@SystemApi
public static String stateToString(int state) {
if (state == STATE_FALSE) return "STATE_FALSE";
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index f658ae0..23ae4b9 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -17,6 +17,7 @@
package android.service.notification;
import android.app.ActivityManager;
+import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.ComponentName;
import android.content.Context;
@@ -33,6 +34,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
@@ -1262,6 +1264,30 @@
.append(']').toString();
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ proto.write(ZenRuleProto.ID, id);
+ proto.write(ZenRuleProto.NAME, name);
+ proto.write(ZenRuleProto.CREATION_TIME_MS, creationTime);
+ proto.write(ZenRuleProto.ENABLED, enabled);
+ proto.write(ZenRuleProto.ENABLER, enabler);
+ proto.write(ZenRuleProto.IS_SNOOZING, snoozing);
+ proto.write(ZenRuleProto.ZEN_MODE, zenMode);
+ if (conditionId != null) {
+ proto.write(ZenRuleProto.CONDITION_ID, conditionId.toString());
+ }
+ if (condition != null) {
+ condition.writeToProto(proto, ZenRuleProto.CONDITION);
+ }
+ if (component != null) {
+ component.writeToProto(proto, ZenRuleProto.COMPONENT);
+ }
+
+ proto.end(token);
+ }
+
private static void appendDiff(Diff d, String item, ZenRule from, ZenRule to) {
if (d == null) return;
if (from == null) {
@@ -1385,4 +1411,38 @@
}
}
+ /**
+ * Determines whether dnd behavior should mute all notification sounds
+ */
+ public static boolean areAllPriorityOnlyNotificationZenSoundsMuted(NotificationManager.Policy
+ policy) {
+ boolean allowReminders = (policy.priorityCategories
+ & NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS) != 0;
+ boolean allowCalls = (policy.priorityCategories
+ & NotificationManager.Policy.PRIORITY_CATEGORY_CALLS) != 0;
+ boolean allowMessages = (policy.priorityCategories
+ & NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) != 0;
+ boolean allowEvents = (policy.priorityCategories
+ & NotificationManager.Policy.PRIORITY_CATEGORY_EVENTS) != 0;
+ boolean allowRepeatCallers = (policy.priorityCategories
+ & NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS) != 0;
+ return !allowReminders && !allowCalls && !allowMessages && !allowEvents
+ && !allowRepeatCallers;
+ }
+
+ /**
+ * Determines whether dnd behavior should mute all notification sounds
+ */
+ public static boolean areAllPriorityOnlyNotificationZenSoundsMuted(ZenModeConfig config) {
+ return !config.allowReminders && !config.allowCalls && !config.allowMessages
+ && !config.allowEvents && !config.allowRepeatCallers;
+ }
+
+ /**
+ * Determines whether all dnd mutes all sounds
+ */
+ public static boolean areAllZenBehaviorSoundsMuted(ZenModeConfig config) {
+ return !config.allowAlarms && !config.allowMediaSystemOther
+ && areAllPriorityOnlyNotificationZenSoundsMuted(config);
+ }
}
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl b/core/java/android/service/textclassifier/ITextClassificationCallback.aidl
similarity index 63%
copy from telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl
copy to core/java/android/service/textclassifier/ITextClassificationCallback.aidl
index 52efd23..10bfe63 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl
+++ b/core/java/android/service/textclassifier/ITextClassificationCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -14,15 +14,15 @@
* limitations under the License.
*/
+package android.service.textclassifier;
-package android.telephony.ims.internal.aidl;
+import android.view.textclassifier.TextClassification;
/**
- * Provides callback interface for ImsConfig when a value has changed.
- *
- * {@hide}
+ * Callback for a TextClassification request.
+ * @hide
*/
-oneway interface IImsConfigCallback {
- void onIntConfigChanged(int item, int value);
- void onStringConfigChanged(int item, String value);
+oneway interface ITextClassificationCallback {
+ void onSuccess(in TextClassification classification);
+ void onFailure();
}
diff --git a/core/java/android/service/textclassifier/ITextClassifierService.aidl b/core/java/android/service/textclassifier/ITextClassifierService.aidl
new file mode 100644
index 0000000..d2ffe34
--- /dev/null
+++ b/core/java/android/service/textclassifier/ITextClassifierService.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.service.textclassifier;
+
+import android.service.textclassifier.ITextClassificationCallback;
+import android.service.textclassifier.ITextLinksCallback;
+import android.service.textclassifier.ITextSelectionCallback;
+import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextLinks;
+import android.view.textclassifier.TextSelection;
+
+/**
+ * TextClassifierService binder interface.
+ * See TextClassifier for interface documentation.
+ * {@hide}
+ */
+oneway interface ITextClassifierService {
+
+ void onSuggestSelection(
+ in CharSequence text, int selectionStartIndex, int selectionEndIndex,
+ in TextSelection.Options options,
+ in ITextSelectionCallback c);
+
+ void onClassifyText(
+ in CharSequence text, int startIndex, int endIndex,
+ in TextClassification.Options options,
+ in ITextClassificationCallback c);
+
+ void onGenerateLinks(
+ in CharSequence text,
+ in TextLinks.Options options,
+ in ITextLinksCallback c);
+}
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl b/core/java/android/service/textclassifier/ITextLinksCallback.aidl
similarity index 66%
copy from telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
copy to core/java/android/service/textclassifier/ITextLinksCallback.aidl
index f6005b6..a9e0dde 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
+++ b/core/java/android/service/textclassifier/ITextLinksCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 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.
@@ -14,12 +14,15 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.service.textclassifier;
+
+import android.view.textclassifier.TextLinks;
/**
- * See RcsFeature for more information.
- * {@hide}
+ * Callback for a TextLinks request.
+ * @hide
*/
-interface IImsRcsFeature {
- //Empty Default Implementation
+oneway interface ITextLinksCallback {
+ void onSuccess(in TextLinks links);
+ void onFailure();
}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl b/core/java/android/service/textclassifier/ITextSelectionCallback.aidl
similarity index 64%
copy from telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
copy to core/java/android/service/textclassifier/ITextSelectionCallback.aidl
index f6005b6..1b4c4d1 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
+++ b/core/java/android/service/textclassifier/ITextSelectionCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 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.
@@ -14,12 +14,15 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.service.textclassifier;
+
+import android.view.textclassifier.TextSelection;
/**
- * See RcsFeature for more information.
- * {@hide}
+ * Callback for a TextSelection request.
+ * @hide
*/
-interface IImsRcsFeature {
- //Empty Default Implementation
+oneway interface ITextSelectionCallback {
+ void onSuccess(in TextSelection selection);
+ void onFailure();
}
\ No newline at end of file
diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java
new file mode 100644
index 0000000..6c8c8bc
--- /dev/null
+++ b/core/java/android/service/textclassifier/TextClassifierService.java
@@ -0,0 +1,290 @@
+/*
+ * 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.service.textclassifier;
+
+import android.Manifest;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.os.CancellationSignal;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Slog;
+import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextLinks;
+import android.view.textclassifier.TextSelection;
+
+import com.android.internal.R;
+
+/**
+ * Abstract base class for the TextClassifier service.
+ *
+ * <p>A TextClassifier service provides text classification related features for the system.
+ * The system's default TextClassifierService is configured in
+ * {@code config_defaultTextClassifierService}. If this config has no value, a
+ * {@link android.view.textclassifier.TextClassifierImpl} is loaded in the calling app's process.
+ *
+ * <p>See: {@link TextClassifier}.
+ * See: {@link android.view.textclassifier.TextClassificationManager}.
+ *
+ * <p>Include the following in the manifest:
+ *
+ * <pre>
+ * {@literal
+ * <service android:name=".YourTextClassifierService"
+ * android:permission="android.permission.BIND_TEXTCLASSIFIER_SERVICE">
+ * <intent-filter>
+ * <action android:name="android.service.textclassifier.TextClassifierService" />
+ * </intent-filter>
+ * </service>}</pre>
+ *
+ * @see TextClassifier
+ * @hide
+ */
+@SystemApi
+public abstract class TextClassifierService extends Service {
+
+ private static final String LOG_TAG = "TextClassifierService";
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ * To be supported, the service must also require the
+ * {@link android.Manifest.permission#BIND_TEXTCLASSIFIER_SERVICE} permission so
+ * that other applications can not abuse it.
+ */
+ @SystemApi
+ public static final String SERVICE_INTERFACE =
+ "android.service.textclassifier.TextClassifierService";
+
+ private final ITextClassifierService.Stub mBinder = new ITextClassifierService.Stub() {
+
+ // TODO(b/72533911): Implement cancellation signal
+ @NonNull private final CancellationSignal mCancellationSignal = new CancellationSignal();
+
+ /** {@inheritDoc} */
+ @Override
+ public void onSuggestSelection(
+ CharSequence text, int selectionStartIndex, int selectionEndIndex,
+ TextSelection.Options options, ITextSelectionCallback callback)
+ throws RemoteException {
+ TextClassifierService.this.onSuggestSelection(
+ text, selectionStartIndex, selectionEndIndex, options, mCancellationSignal,
+ new Callback<TextSelection>() {
+ @Override
+ public void onSuccess(TextSelection result) {
+ try {
+ callback.onSuccess(result);
+ } catch (RemoteException e) {
+ Slog.d(LOG_TAG, "Error calling callback");
+ }
+ }
+
+ @Override
+ public void onFailure(CharSequence error) {
+ try {
+ if (callback.asBinder().isBinderAlive()) {
+ callback.onFailure();
+ }
+ } catch (RemoteException e) {
+ Slog.d(LOG_TAG, "Error calling callback");
+ }
+ }
+ });
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onClassifyText(
+ CharSequence text, int startIndex, int endIndex,
+ TextClassification.Options options, ITextClassificationCallback callback)
+ throws RemoteException {
+ TextClassifierService.this.onClassifyText(
+ text, startIndex, endIndex, options, mCancellationSignal,
+ new Callback<TextClassification>() {
+ @Override
+ public void onSuccess(TextClassification result) {
+ try {
+ callback.onSuccess(result);
+ } catch (RemoteException e) {
+ Slog.d(LOG_TAG, "Error calling callback");
+ }
+ }
+
+ @Override
+ public void onFailure(CharSequence error) {
+ try {
+ callback.onFailure();
+ } catch (RemoteException e) {
+ Slog.d(LOG_TAG, "Error calling callback");
+ }
+ }
+ });
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onGenerateLinks(
+ CharSequence text, TextLinks.Options options, ITextLinksCallback callback)
+ throws RemoteException {
+ TextClassifierService.this.onGenerateLinks(
+ text, options, mCancellationSignal,
+ new Callback<TextLinks>() {
+ @Override
+ public void onSuccess(TextLinks result) {
+ try {
+ callback.onSuccess(result);
+ } catch (RemoteException e) {
+ Slog.d(LOG_TAG, "Error calling callback");
+ }
+ }
+
+ @Override
+ public void onFailure(CharSequence error) {
+ try {
+ callback.onFailure();
+ } catch (RemoteException e) {
+ Slog.d(LOG_TAG, "Error calling callback");
+ }
+ }
+ });
+ }
+ };
+
+ @Nullable
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
+ return mBinder;
+ }
+ return null;
+ }
+
+ /**
+ * Returns suggested text selection start and end indices, recognized entity types, and their
+ * associated confidence scores. The entity types are ordered from highest to lowest scoring.
+ *
+ * @param text text providing context for the selected text (which is specified
+ * by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex)
+ * @param selectionStartIndex start index of the selected part of text
+ * @param selectionEndIndex end index of the selected part of text
+ * @param options optional input parameters
+ * @param cancellationSignal object to watch for canceling the current operation
+ * @param callback the callback to return the result to
+ */
+ public abstract void onSuggestSelection(
+ @NonNull CharSequence text,
+ @IntRange(from = 0) int selectionStartIndex,
+ @IntRange(from = 0) int selectionEndIndex,
+ @Nullable TextSelection.Options options,
+ @NonNull CancellationSignal cancellationSignal,
+ @NonNull Callback<TextSelection> callback);
+
+ /**
+ * Classifies the specified text and returns a {@link TextClassification} object that can be
+ * used to generate a widget for handling the classified text.
+ *
+ * @param text text providing context for the text to classify (which is specified
+ * by the sub sequence starting at startIndex and ending at endIndex)
+ * @param startIndex start index of the text to classify
+ * @param endIndex end index of the text to classify
+ * @param options optional input parameters
+ * @param cancellationSignal object to watch for canceling the current operation
+ * @param callback the callback to return the result to
+ */
+ public abstract void onClassifyText(
+ @NonNull CharSequence text,
+ @IntRange(from = 0) int startIndex,
+ @IntRange(from = 0) int endIndex,
+ @Nullable TextClassification.Options options,
+ @NonNull CancellationSignal cancellationSignal,
+ @NonNull Callback<TextClassification> callback);
+
+ /**
+ * Generates and returns a {@link TextLinks} that may be applied to the text to annotate it with
+ * links information.
+ *
+ * @param text the text to generate annotations for
+ * @param options configuration for link generation
+ * @param cancellationSignal object to watch for canceling the current operation
+ * @param callback the callback to return the result to
+ */
+ public abstract void onGenerateLinks(
+ @NonNull CharSequence text,
+ @Nullable TextLinks.Options options,
+ @NonNull CancellationSignal cancellationSignal,
+ @NonNull Callback<TextLinks> callback);
+
+ /**
+ * Callbacks for TextClassifierService results.
+ *
+ * @param <T> the type of the result
+ * @hide
+ */
+ @SystemApi
+ public interface Callback<T> {
+ /**
+ * Returns the result.
+ */
+ void onSuccess(T result);
+
+ /**
+ * Signals a failure.
+ */
+ void onFailure(CharSequence error);
+ }
+
+ /**
+ * Returns the component name of the system default textclassifier service if it can be found
+ * on the system. Otherwise, returns null.
+ * @hide
+ */
+ @Nullable
+ public static ComponentName getServiceComponentName(Context context) {
+ final String str = context.getString(R.string.config_defaultTextClassifierService);
+ if (!TextUtils.isEmpty(str)) {
+ try {
+ final ComponentName componentName = ComponentName.unflattenFromString(str);
+ final Intent intent = new Intent(SERVICE_INTERFACE).setComponent(componentName);
+ final ServiceInfo si = context.getPackageManager()
+ .getServiceInfo(intent.getComponent(), 0);
+ final String permission = si == null ? null : si.permission;
+ if (Manifest.permission.BIND_TEXTCLASSIFIER_SERVICE.equals(permission)) {
+ return componentName;
+ }
+ Slog.w(LOG_TAG, String.format(
+ "Service %s should require %s permission. Found %s permission",
+ intent.getComponent().flattenToString(),
+ Manifest.permission.BIND_TEXTCLASSIFIER_SERVICE,
+ si.permission));
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.w(LOG_TAG, String.format("Service %s not found", str));
+ }
+ } else {
+ Slog.d(LOG_TAG, "No configured system TextClassifierService");
+ }
+ return null;
+ }
+}
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index 45fbf6f..aafcf44 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -672,6 +672,13 @@
return width;
}
+ /**
+ * This only works if the MeasuredParagraph is computed with buildForStaticLayout.
+ */
+ @IntRange(from = 0) int getMemoryUsage() {
+ return nGetMemoryUsage(mNativePtr);
+ }
+
private static native /* Non Zero */ long nInitBuilder();
/**
@@ -718,4 +725,7 @@
@CriticalNative
private static native /* Non Zero */ long nGetReleaseFunc();
+
+ @CriticalNative
+ private static native int nGetMemoryUsage(/* Non Zero */ long nativePtr);
}
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index ff23395..bb7a9e0 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -333,6 +333,20 @@
return getMeasuredParagraph(paraIndex).getWidth(start - paraStart, end - paraStart);
}
+ /**
+ * Returns the size of native MeasuredText memory usage
+ *
+ * Note that this may not be aculate. Must be used only for testing purposes.
+ * @hide
+ */
+ public int getMemoryUsage() {
+ int r = 0;
+ for (int i = 0; i < getParagraphCount(); ++i) {
+ r += getMeasuredParagraph(i).getMemoryUsage();
+ }
+ return r;
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////////
// Spanned overrides
//
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index de2dcce..413cd10 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -431,7 +431,7 @@
int c = s.charAt(i);
if (c == QUOTE) {
- count = appendQuotedText(s, i, len);
+ count = appendQuotedText(s, i);
len = s.length();
continue;
}
@@ -574,36 +574,48 @@
: String.format(Locale.getDefault(), "%d", year);
}
- private static int appendQuotedText(SpannableStringBuilder s, int i, int len) {
- if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
- s.delete(i, i + 1);
+
+ /**
+ * Strips quotation marks from the {@code formatString} and appends the result back to the
+ * {@code formatString}.
+ *
+ * @param formatString the format string, as described in
+ * {@link android.text.format.DateFormat}, to be modified
+ * @param index index of the first quote
+ * @return the length of the quoted text that was appended.
+ * @hide
+ */
+ public static int appendQuotedText(SpannableStringBuilder formatString, int index) {
+ int length = formatString.length();
+ if (index + 1 < length && formatString.charAt(index + 1) == QUOTE) {
+ formatString.delete(index, index + 1);
return 1;
}
int count = 0;
// delete leading quote
- s.delete(i, i + 1);
- len--;
+ formatString.delete(index, index + 1);
+ length--;
- while (i < len) {
- char c = s.charAt(i);
+ while (index < length) {
+ char c = formatString.charAt(index);
if (c == QUOTE) {
// QUOTEQUOTE -> QUOTE
- if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
+ if (index + 1 < length && formatString.charAt(index + 1) == QUOTE) {
- s.delete(i, i + 1);
- len--;
+ formatString.delete(index, index + 1);
+ length--;
count++;
- i++;
+ index++;
} else {
// Closing QUOTE ends quoted text copying
- s.delete(i, i + 1);
+ formatString.delete(index, index + 1);
break;
}
} else {
- i++;
+ index++;
count++;
}
}
diff --git a/core/java/android/text/style/AlignmentSpan.java b/core/java/android/text/style/AlignmentSpan.java
index 6158309..18c3e16 100644
--- a/core/java/android/text/style/AlignmentSpan.java
+++ b/core/java/android/text/style/AlignmentSpan.java
@@ -16,49 +16,90 @@
package android.text.style;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.text.Layout;
import android.text.ParcelableSpan;
import android.text.TextUtils;
+/**
+ * Span that allows defining the alignment of text at the paragraph level.
+ */
public interface AlignmentSpan extends ParagraphStyle {
+
+ /**
+ * Returns the alignment of the text.
+ *
+ * @return the text alignment
+ */
Layout.Alignment getAlignment();
+ /**
+ * Default implementation of the {@link AlignmentSpan}.
+ * <p>
+ * For example, a text written in a left to right language, like English, which is by default
+ * aligned to the left, can be aligned opposite to the layout direction like this:
+ * <pre>{@code SpannableString string = new SpannableString("Text with opposite alignment");
+ *string.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE), 0,
+ *string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/ltralignmentspan.png" />
+ * <figcaption>Align left to right text opposite to the layout direction.</figcaption>
+ * <p>
+ * A text written in a right to left language, like Hebrew, which is by default aligned to the
+ * right, can be aligned opposite to the layout direction like this:
+ * <pre>{@code SpannableString string = new SpannableString("טקסט עם יישור הפוך");
+ *string.setSpan(new AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE), 0,
+ *string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/rtlalignmentspan.png" />
+ * <figcaption>Align right to left text opposite to the layout direction.</figcaption>
+ */
class Standard implements AlignmentSpan, ParcelableSpan {
- public Standard(Layout.Alignment align) {
+ private final Layout.Alignment mAlignment;
+
+ /**
+ * Constructs a {@link Standard} from an alignment.
+ */
+ public Standard(@NonNull Layout.Alignment align) {
mAlignment = align;
}
- public Standard(Parcel src) {
+ /**
+ * Constructs a {@link Standard} from a parcel.
+ */
+ public Standard(@NonNull Parcel src) {
mAlignment = Layout.Alignment.valueOf(src.readString());
}
-
- public int getSpanTypeId() {
- return getSpanTypeIdInternal();
- }
- /** @hide */
- public int getSpanTypeIdInternal() {
+ @Override
+ public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ @Override
+ public int getSpanTypeIdInternal() {
return TextUtils.ALIGNMENT_SPAN;
}
-
+
+ @Override
public int describeContents() {
return 0;
}
- public void writeToParcel(Parcel dest, int flags) {
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
writeToParcelInternal(dest, flags);
}
/** @hide */
- public void writeToParcelInternal(Parcel dest, int flags) {
+ @Override
+ public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
dest.writeString(mAlignment.name());
}
+ @Override
public Layout.Alignment getAlignment() {
return mAlignment;
}
-
- private final Layout.Alignment mAlignment;
}
}
diff --git a/core/java/android/text/style/ClickableSpan.java b/core/java/android/text/style/ClickableSpan.java
index b098f16..60aed2a 100644
--- a/core/java/android/text/style/ClickableSpan.java
+++ b/core/java/android/text/style/ClickableSpan.java
@@ -16,6 +16,7 @@
package android.text.style;
+import android.annotation.NonNull;
import android.text.TextPaint;
import android.view.View;
@@ -24,6 +25,16 @@
* with a movement method of LinkMovementMethod, the affected spans of
* text can be selected. If selected and clicked, the {@link #onClick} method will
* be called.
+ * <p>
+ * The text with a <code>ClickableSpan</code> attached will be underlined and the link color will be
+ * used as a text color. The default link color is the theme's accent color or
+ * <code>android:textColorLink</code> if this attribute is defined in the theme.
+ * For example, considering that we have a <code>CustomClickableSpan</code> that extends
+ * <code>ClickableSpan</code>, it can be used like this:
+ * <pre>{@code SpannableString string = new SpannableString("Text with clickable text");
+ *string.setSpan(new CustomClickableSpan(), 10, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/clickablespan.png" />
+ * <figcaption>Text with <code>ClickableSpan</code>.</figcaption>
*/
public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
private static int sIdCounter = 0;
@@ -33,13 +44,13 @@
/**
* Performs the click action associated with this span.
*/
- public abstract void onClick(View widget);
+ public abstract void onClick(@NonNull View widget);
/**
* Makes the text underlined and in the link color.
*/
@Override
- public void updateDrawState(TextPaint ds) {
+ public void updateDrawState(@NonNull TextPaint ds) {
ds.setColor(ds.linkColor);
ds.setUnderlineText(true);
}
diff --git a/core/java/android/text/style/EasyEditSpan.java b/core/java/android/text/style/EasyEditSpan.java
index 7af1c2c..9ee0b07 100644
--- a/core/java/android/text/style/EasyEditSpan.java
+++ b/core/java/android/text/style/EasyEditSpan.java
@@ -16,6 +16,7 @@
package android.text.style;
+import android.annotation.NonNull;
import android.app.PendingIntent;
import android.os.Parcel;
import android.text.ParcelableSpan;
@@ -79,7 +80,7 @@
/**
* Constructor called from {@link TextUtils} to restore the span.
*/
- public EasyEditSpan(Parcel source) {
+ public EasyEditSpan(@NonNull Parcel source) {
mPendingIntent = source.readParcelable(null);
mDeleteEnabled = (source.readByte() == 1);
}
@@ -90,12 +91,12 @@
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
writeToParcelInternal(dest, flags);
}
/** @hide */
- public void writeToParcelInternal(Parcel dest, int flags) {
+ public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
dest.writeParcelable(mPendingIntent, 0);
dest.writeByte((byte) (mDeleteEnabled ? 1 : 0));
}
diff --git a/core/java/android/text/style/MetricAffectingSpan.java b/core/java/android/text/style/MetricAffectingSpan.java
index 853ecc6..61b7947 100644
--- a/core/java/android/text/style/MetricAffectingSpan.java
+++ b/core/java/android/text/style/MetricAffectingSpan.java
@@ -16,6 +16,7 @@
package android.text.style;
+import android.annotation.NonNull;
import android.text.TextPaint;
/**
@@ -23,13 +24,19 @@
* changes the width or height of characters extend this class.
*/
public abstract class MetricAffectingSpan
-extends CharacterStyle
-implements UpdateLayout {
-
- public abstract void updateMeasureState(TextPaint p);
+ extends CharacterStyle
+ implements UpdateLayout {
/**
- * Returns "this" for most MetricAffectingSpans, but for
+ * Classes that extend MetricAffectingSpan implement this method to update the text formatting
+ * in a way that can change the width or height of characters.
+ *
+ * @param textPaint the paint used for drawing the text
+ */
+ public abstract void updateMeasureState(@NonNull TextPaint textPaint);
+
+ /**
+ * Returns "this" for most MetricAffectingSpans, but for
* MetricAffectingSpans that were generated by {@link #wrap},
* returns the underlying MetricAffectingSpan.
*/
@@ -41,18 +48,18 @@
/**
* A Passthrough MetricAffectingSpan is one that
* passes {@link #updateDrawState} and {@link #updateMeasureState}
- * calls through to the specified MetricAffectingSpan
+ * calls through to the specified MetricAffectingSpan
* while still being a distinct object,
* and is therefore able to be attached to the same Spannable
* to which the specified MetricAffectingSpan is already attached.
*/
/* package */ static class Passthrough extends MetricAffectingSpan {
private MetricAffectingSpan mStyle;
-
+
/**
* Creates a new Passthrough of the specfied MetricAffectingSpan.
*/
- public Passthrough(MetricAffectingSpan cs) {
+ Passthrough(@NonNull MetricAffectingSpan cs) {
mStyle = cs;
}
@@ -60,7 +67,7 @@
* Passes updateDrawState through to the underlying MetricAffectingSpan.
*/
@Override
- public void updateDrawState(TextPaint tp) {
+ public void updateDrawState(@NonNull TextPaint tp) {
mStyle.updateDrawState(tp);
}
@@ -68,10 +75,10 @@
* Passes updateMeasureState through to the underlying MetricAffectingSpan.
*/
@Override
- public void updateMeasureState(TextPaint tp) {
+ public void updateMeasureState(@NonNull TextPaint tp) {
mStyle.updateMeasureState(tp);
}
-
+
/**
* Returns the MetricAffectingSpan underlying this one, or the one
* underlying it if it too is a Passthrough.
diff --git a/core/java/android/text/style/QuoteSpan.java b/core/java/android/text/style/QuoteSpan.java
index 7217e1e..a1c12c2 100644
--- a/core/java/android/text/style/QuoteSpan.java
+++ b/core/java/android/text/style/QuoteSpan.java
@@ -17,6 +17,9 @@
package android.text.style;
import android.annotation.ColorInt;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Px;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Parcel;
@@ -24,68 +27,178 @@
import android.text.ParcelableSpan;
import android.text.TextUtils;
+/**
+ * A span which styles paragraphs by adding a vertical stripe at the beginning of the text
+ * (respecting layout direction).
+ * <p>
+ * A <code>QuoteSpan</code> must be attached from the first character to the last character of a
+ * single paragraph, otherwise the span will not be displayed.
+ * <p>
+ * <code>QuoteSpans</code> allow configuring the following elements:
+ * <ul>
+ * <li><b>color</b> - the vertical stripe color. By default, the stripe color is 0xff0000ff</li>
+ * <li><b>gap width</b> - the distance, in pixels, between the stripe and the paragraph.
+ * Default value is 2px.</li>
+ * <li><b>stripe width</b> - the width, in pixels, of the stripe. Default value is
+ * 2px.</li>
+ * </ul>
+ * For example, a <code>QuoteSpan</code> using the default values can be constructed like this:
+ * <pre>{@code SpannableString string = new SpannableString("Text with quote span on a long line");
+ *string.setSpan(new QuoteSpan(), 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/defaultquotespan.png" />
+ * <figcaption><code>QuoteSpan</code> constructed with default values.</figcaption>
+ * <p>
+ * <p>
+ * To construct a <code>QuoteSpan</code> with a green stripe, of 20px in width and a gap width of
+ * 40px:
+ * <pre>{@code SpannableString string = new SpannableString("Text with quote span on a long line");
+ *string.setSpan(new QuoteSpan(Color.GREEN, 20, 40), 0, string.length(),
+ *Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/customquotespan.png" />
+ * <figcaption>Customized <code>QuoteSpan</code>.</figcaption>
+ */
public class QuoteSpan implements LeadingMarginSpan, ParcelableSpan {
- private static final int STRIPE_WIDTH = 2;
- private static final int GAP_WIDTH = 2;
+ /**
+ * Default stripe width in pixels.
+ */
+ public static final int STANDARD_STRIPE_WIDTH_PX = 2;
+ /**
+ * Default gap width in pixels.
+ */
+ public static final int STANDARD_GAP_WIDTH_PX = 2;
+
+ /**
+ * Default color for the quote stripe.
+ */
+ @ColorInt
+ public static final int STANDARD_COLOR = 0xff0000ff;
+
+ @ColorInt
private final int mColor;
+ @Px
+ private final int mStripeWidth;
+ @Px
+ private final int mGapWidth;
+ /**
+ * Creates a {@link QuoteSpan} with the default values.
+ */
public QuoteSpan() {
- super();
- mColor = 0xff0000ff;
+ this(STANDARD_COLOR, STANDARD_STRIPE_WIDTH_PX, STANDARD_GAP_WIDTH_PX);
}
+ /**
+ * Creates a {@link QuoteSpan} based on a color.
+ *
+ * @param color the color of the quote stripe.
+ */
public QuoteSpan(@ColorInt int color) {
- super();
+ this(color, STANDARD_STRIPE_WIDTH_PX, STANDARD_GAP_WIDTH_PX);
+ }
+
+ /**
+ * Creates a {@link QuoteSpan} based on a color, a stripe width and the width of the gap
+ * between the stripe and the text.
+ *
+ * @param color the color of the quote stripe.
+ * @param stripeWidth the width of the stripe.
+ * @param gapWidth the width of the gap between the stripe and the text.
+ */
+ public QuoteSpan(@ColorInt int color, @IntRange(from = 0) int stripeWidth,
+ @IntRange(from = 0) int gapWidth) {
mColor = color;
+ mStripeWidth = stripeWidth;
+ mGapWidth = gapWidth;
}
- public QuoteSpan(Parcel src) {
+ /**
+ * Create a {@link QuoteSpan} from a parcel.
+ */
+ public QuoteSpan(@NonNull Parcel src) {
mColor = src.readInt();
+ mStripeWidth = src.readInt();
+ mGapWidth = src.readInt();
}
+ @Override
public int getSpanTypeId() {
return getSpanTypeIdInternal();
}
- /** @hide */
+ /**
+ * @hide
+ */
+ @Override
public int getSpanTypeIdInternal() {
return TextUtils.QUOTE_SPAN;
}
+ @Override
public int describeContents() {
return 0;
}
+ @Override
public void writeToParcel(Parcel dest, int flags) {
writeToParcelInternal(dest, flags);
}
- /** @hide */
+ /**
+ * @hide
+ */
+ @Override
public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeInt(mColor);
+ dest.writeInt(mStripeWidth);
+ dest.writeInt(mGapWidth);
}
+ /**
+ * Get the color of the quote stripe.
+ *
+ * @return the color of the quote stripe.
+ */
@ColorInt
public int getColor() {
return mColor;
}
- public int getLeadingMargin(boolean first) {
- return STRIPE_WIDTH + GAP_WIDTH;
+ /**
+ * Get the width of the quote stripe.
+ *
+ * @return the width of the quote stripe.
+ */
+ public int getStripeWidth() {
+ return mStripeWidth;
}
- public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout) {
+ /**
+ * Get the width of the gap between the stripe and the text.
+ *
+ * @return the width of the gap between the stripe and the text.
+ */
+ public int getGapWidth() {
+ return mGapWidth;
+ }
+
+ @Override
+ public int getLeadingMargin(boolean first) {
+ return mStripeWidth + mGapWidth;
+ }
+
+ @Override
+ public void drawLeadingMargin(@NonNull Canvas c, @NonNull Paint p, int x, int dir,
+ int top, int baseline, int bottom,
+ @NonNull CharSequence text, int start, int end,
+ boolean first, @NonNull Layout layout) {
Paint.Style style = p.getStyle();
int color = p.getColor();
p.setStyle(Paint.Style.FILL);
p.setColor(mColor);
- c.drawRect(x, top, x + dir * STRIPE_WIDTH, bottom, p);
+ c.drawRect(x, top, x + dir * mStripeWidth, bottom, p);
p.setStyle(style);
p.setColor(color);
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index 768aee9..d973d4a 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UiThread;
import android.content.Context;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
@@ -29,12 +30,16 @@
import android.text.method.MovementMethod;
import android.text.style.URLSpan;
import android.util.Patterns;
+import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextLinks;
+import android.view.textclassifier.TextLinks.TextLinkSpan;
import android.webkit.WebView;
import android.widget.TextView;
import com.android.i18n.phonenumbers.PhoneNumberMatch;
import com.android.i18n.phonenumbers.PhoneNumberUtil;
import com.android.i18n.phonenumbers.PhoneNumberUtil.Leniency;
+import com.android.internal.util.Preconditions;
import libcore.util.EmptyArray;
@@ -46,6 +51,12 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Locale;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -479,6 +490,195 @@
return hasMatches;
}
+ /**
+ * Scans the text of the provided TextView and turns all occurrences of the entity types
+ * specified by {@code options} into clickable links. If links are found, this method
+ * removes any pre-existing {@link TextLinkSpan} attached to the text (to avoid
+ * problems if you call it repeatedly on the same text) and sets the movement method for the
+ * TextView to LinkMovementMethod.
+ *
+ * <p><strong>Note:</strong> This method returns immediately but generates the links with
+ * the specified classifier on a background thread. The generated links are applied on the
+ * calling thread.
+ *
+ * @param textView TextView whose text is to be marked-up with links
+ * @param options optional parameters to specify how to generate the links
+ *
+ * @return a future that may be used to interrupt or query the background task
+ */
+ @UiThread
+ public static Future<Void> addLinksAsync(
+ @NonNull TextView textView,
+ @Nullable TextLinks.Options options) {
+ return addLinksAsync(textView, options, null /* executor */, null /* callback */);
+ }
+
+ /**
+ * Scans the text of the provided TextView and turns all occurrences of the entity types
+ * specified by {@code options} into clickable links. If links are found, this method
+ * removes any pre-existing {@link TextLinkSpan} attached to the text (to avoid
+ * problems if you call it repeatedly on the same text) and sets the movement method for the
+ * TextView to LinkMovementMethod.
+ *
+ * <p><strong>Note:</strong> This method returns immediately but generates the links with
+ * the specified classifier on a background thread. The generated links are applied on the
+ * calling thread.
+ *
+ * @param textView TextView whose text is to be marked-up with links
+ * @param options optional parameters to specify how to generate the links
+ * @param executor Executor that runs the background task
+ * @param callback Callback that receives the final status of the background task execution
+ *
+ * @return a future that may be used to interrupt or query the background task
+ */
+ @UiThread
+ public static Future<Void> addLinksAsync(
+ @NonNull TextView textView,
+ @Nullable TextLinks.Options options,
+ @Nullable Executor executor,
+ @Nullable Consumer<Integer> callback) {
+ Preconditions.checkNotNull(textView);
+ final CharSequence text = textView.getText();
+ final Spannable spannable = (text instanceof Spannable)
+ ? (Spannable) text : SpannableString.valueOf(text);
+ final Runnable modifyTextView = () -> {
+ addLinkMovementMethod(textView);
+ if (spannable != text) {
+ textView.setText(spannable);
+ }
+ };
+ return addLinksAsync(spannable, textView.getTextClassifier(),
+ options, executor, callback, modifyTextView);
+ }
+
+ /**
+ * Scans the text of the provided TextView and turns all occurrences of the entity types
+ * specified by {@code options} into clickable links. If links are found, this method
+ * removes any pre-existing {@link TextLinkSpan} attached to the text to avoid
+ * problems if you call it repeatedly on the same text.
+ *
+ * <p><strong>Note:</strong> This method returns immediately but generates the links with
+ * the specified classifier on a background thread. The generated links are applied on the
+ * calling thread.
+ *
+ * <p><strong>Note:</strong> If the text is currently attached to a TextView, this method
+ * should be called on the UI thread.
+ *
+ * @param text Spannable whose text is to be marked-up with links
+ * @param classifier the TextClassifier to use to generate the links
+ * @param options optional parameters to specify how to generate the links
+ *
+ * @return a future that may be used to interrupt or query the background task
+ */
+ public static Future<Void> addLinksAsync(
+ @NonNull Spannable text,
+ @NonNull TextClassifier classifier,
+ @Nullable TextLinks.Options options) {
+ return addLinksAsync(text, classifier, options, null /* executor */, null /* callback */);
+ }
+
+ /**
+ * Scans the text of the provided TextView and turns all occurrences of the entity types
+ * specified by the link {@code mask} into clickable links. If links are found, this method
+ * removes any pre-existing {@link TextLinkSpan} attached to the text to avoid
+ * problems if you call it repeatedly on the same text.
+ *
+ * <p><strong>Note:</strong> This method returns immediately but generates the links with
+ * the specified classifier on a background thread. The generated links are applied on the
+ * calling thread.
+ *
+ * <p><strong>Note:</strong> If the text is currently attached to a TextView, this method
+ * should be called on the UI thread.
+ *
+ * @param text Spannable whose text is to be marked-up with links
+ * @param classifier the TextClassifier to use to generate the links
+ * @param mask mask to define which kinds of links will be generated
+ *
+ * @return a future that may be used to interrupt or query the background task
+ */
+ public static Future<Void> addLinksAsync(
+ @NonNull Spannable text,
+ @NonNull TextClassifier classifier,
+ @LinkifyMask int mask) {
+ return addLinksAsync(text, classifier, TextLinks.Options.fromLinkMask(mask),
+ null /* executor */, null /* callback */);
+ }
+
+ /**
+ * Scans the text of the provided TextView and turns all occurrences of the entity types
+ * specified by {@code options} into clickable links. If links are found, this method
+ * removes any pre-existing {@link TextLinkSpan} attached to the text to avoid
+ * problems if you call it repeatedly on the same text.
+ *
+ * <p><strong>Note:</strong> This method returns immediately but generates the links with
+ * the specified classifier on a background thread. The generated links are applied on the
+ * calling thread.
+ *
+ * <p><strong>Note:</strong> If the text is currently attached to a TextView, this method
+ * should be called on the UI thread.
+ *
+ * @param text Spannable whose text is to be marked-up with links
+ * @param classifier the TextClassifier to use to generate the links
+ * @param options optional parameters to specify how to generate the links
+ * @param executor Executor that runs the background task
+ * @param callback Callback that receives the final status of the background task execution
+ *
+ * @return a future that may be used to interrupt or query the background task
+ */
+ public static Future<Void> addLinksAsync(
+ @NonNull Spannable text,
+ @NonNull TextClassifier classifier,
+ @Nullable TextLinks.Options options,
+ @Nullable Executor executor,
+ @Nullable Consumer<Integer> callback) {
+ return addLinksAsync(text, classifier, options, executor, callback,
+ null /* modifyTextView */);
+ }
+
+ private static Future<Void> addLinksAsync(
+ @NonNull Spannable text,
+ @NonNull TextClassifier classifier,
+ @Nullable TextLinks.Options options,
+ @Nullable Executor executor,
+ @Nullable Consumer<Integer> callback,
+ @Nullable Runnable modifyTextView) {
+ Preconditions.checkNotNull(text);
+ Preconditions.checkNotNull(classifier);
+ final Supplier<TextLinks> supplier = () -> classifier.generateLinks(text, options);
+ final Consumer<TextLinks> consumer = links -> {
+ if (links.getLinks().isEmpty()) {
+ if (callback != null) {
+ callback.accept(TextLinks.STATUS_NO_LINKS_FOUND);
+ }
+ return;
+ }
+
+ final TextLinkSpan[] old = text.getSpans(0, text.length(), TextLinkSpan.class);
+ for (int i = old.length - 1; i >= 0; i--) {
+ text.removeSpan(old[i]);
+ }
+
+ final Function<TextLinks.TextLink, TextLinkSpan> spanFactory = (options == null)
+ ? null : options.getSpanFactory();
+ final @TextLinks.ApplyStrategy int applyStrategy = (options == null)
+ ? TextLinks.APPLY_STRATEGY_IGNORE : options.getApplyStrategy();
+ final @TextLinks.Status int result = links.apply(text, applyStrategy, spanFactory);
+ if (result == TextLinks.STATUS_LINKS_APPLIED) {
+ if (modifyTextView != null) {
+ modifyTextView.run();
+ }
+ }
+ if (callback != null) {
+ callback.accept(result);
+ }
+ };
+ if (executor == null) {
+ return CompletableFuture.supplyAsync(supplier).thenAccept(consumer);
+ } else {
+ return CompletableFuture.supplyAsync(supplier, executor).thenAccept(consumer);
+ }
+ }
+
private static final void applyLink(String url, int start, int end, Spannable text) {
URLSpan span = new URLSpan(url);
diff --git a/core/java/android/util/AtomicFile.java b/core/java/android/util/AtomicFile.java
index 6342c8b..cf7ed9b 100644
--- a/core/java/android/util/AtomicFile.java
+++ b/core/java/android/util/AtomicFile.java
@@ -17,6 +17,7 @@
package android.util;
import android.os.FileUtils;
+import android.os.SystemClock;
import libcore.io.IoUtils;
@@ -47,14 +48,25 @@
public class AtomicFile {
private final File mBaseName;
private final File mBackupName;
+ private final String mCommitTag;
+ private long mStartTime;
/**
* Create a new AtomicFile for a file located at the given File path.
* The secondary backup file will be the same file path with ".bak" appended.
*/
public AtomicFile(File baseName) {
+ this(baseName, null);
+ }
+
+ /**
+ * @hide Internal constructor that also allows you to have the class
+ * automatically log commit events.
+ */
+ public AtomicFile(File baseName, String commitTag) {
mBaseName = baseName;
mBackupName = new File(baseName.getPath() + ".bak");
+ mCommitTag = commitTag;
}
/**
@@ -88,6 +100,18 @@
* access to AtomicFile.
*/
public FileOutputStream startWrite() throws IOException {
+ return startWrite(mCommitTag != null ? SystemClock.uptimeMillis() : 0);
+ }
+
+ /**
+ * @hide Internal version of {@link #startWrite()} that allows you to specify an earlier
+ * start time of the operation to adjust how the commit is logged.
+ * @param startTime The effective start time of the operation, in the time
+ * base of {@link SystemClock#uptimeMillis()}.
+ */
+ public FileOutputStream startWrite(long startTime) throws IOException {
+ mStartTime = startTime;
+
// Rename the current file so it may be used as a backup during the next read
if (mBaseName.exists()) {
if (!mBackupName.exists()) {
@@ -135,6 +159,10 @@
} catch (IOException e) {
Log.w("AtomicFile", "finishWrite: Got exception:", e);
}
+ if (mCommitTag != null) {
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ mCommitTag, SystemClock.uptimeMillis() - mStartTime);
+ }
}
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 25a177e..410cdc6 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -38,13 +38,10 @@
static {
DEFAULT_FLAGS = new HashMap<>();
DEFAULT_FLAGS.put("device_info_v2", "true");
- DEFAULT_FLAGS.put("settings_app_info_v2", "true");
DEFAULT_FLAGS.put("settings_connected_device_v2", "true");
DEFAULT_FLAGS.put("settings_battery_v2", "true");
DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
- DEFAULT_FLAGS.put("settings_security_settings_v2", "true");
DEFAULT_FLAGS.put("settings_zone_picker_v2", "true");
- DEFAULT_FLAGS.put("settings_suggestion_ui_v2", "false");
DEFAULT_FLAGS.put("settings_about_phone_v2", "false");
DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
}
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index bf33519..5970892 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -16,12 +16,18 @@
package android.util;
+import static android.os.Process.FIRST_APPLICATION_UID;
+
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+import android.os.Process;
+
+import com.android.internal.annotations.GuardedBy;
+
+import dalvik.system.CloseGuard;
import libcore.io.IoUtils;
-import dalvik.system.CloseGuard;
import java.io.Closeable;
import java.io.IOException;
@@ -49,13 +55,18 @@
*/
public final class MemoryIntArray implements Parcelable, Closeable {
private static final String TAG = "MemoryIntArray";
+ private static final boolean DEBUG = Process.myUid() < FIRST_APPLICATION_UID;
private static final int MAX_SIZE = 1024;
+ private final Object mLock = new Object();
private final CloseGuard mCloseGuard = CloseGuard.get();
private final boolean mIsOwner;
private final long mMemoryAddr;
+
+ /** Fd for the shared memory object, -1 when closed */
+ @GuardedBy("mLock")
private int mFd = -1;
/**
@@ -74,6 +85,7 @@
mFd = nativeCreate(name, size);
mMemoryAddr = nativeOpen(mFd, mIsOwner);
mCloseGuard.open("close");
+ if (DEBUG) Log.i(TAG, "created " + getString());
}
private MemoryIntArray(Parcel parcel) throws IOException {
@@ -85,6 +97,8 @@
mFd = pfd.detachFd();
mMemoryAddr = nativeOpen(mFd, mIsOwner);
mCloseGuard.open("close");
+
+ if (DEBUG) Log.i(TAG, "created from parcel " + getString());
}
/**
@@ -141,13 +155,33 @@
*/
@Override
public void close() throws IOException {
- if (!isClosed()) {
- nativeClose(mFd, mMemoryAddr, mIsOwner);
- mFd = -1;
- mCloseGuard.close();
+ synchronized (mLock) {
+ if (!isClosed()) {
+ if (DEBUG) {
+ try {
+ throw new Exception();
+ } catch (Exception here) {
+ Log.i(TAG, "closing " + getString(), here);
+ }
+ }
+ nativeClose(mFd, mMemoryAddr, mIsOwner);
+ mFd = -1;
+ mCloseGuard.close();
+ } else {
+ try {
+ throw new Exception();
+ } catch (Exception here) {
+ if (DEBUG) Log.i(TAG, getString() + " already closed", here);
+ }
+ }
}
}
+ private String getString() {
+ return this.getClass().getSimpleName() + "@" + System.identityHashCode(this)
+ + " mMemoryAddr=" + mMemoryAddr + " mFd=" + mFd;
+ }
+
/**
* @return Whether this array is closed and shouldn't be used.
*/
@@ -162,7 +196,9 @@
mCloseGuard.warnIfOpen();
}
- IoUtils.closeQuietly(this);
+ if (!isClosed()) {
+ IoUtils.closeQuietly(this);
+ }
} finally {
super.finalize();
}
@@ -206,7 +242,8 @@
private void enforceNotClosed() {
if (isClosed()) {
- throw new IllegalStateException("cannot interact with a closed instance");
+ throw new IllegalStateException("cannot interact with a closed instance "
+ + getString());
}
}
diff --git a/core/java/android/util/SparseSetArray.java b/core/java/android/util/SparseSetArray.java
new file mode 100644
index 0000000..d100f12
--- /dev/null
+++ b/core/java/android/util/SparseSetArray.java
@@ -0,0 +1,98 @@
+/*
+ * 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.util;
+
+/**
+ * A sparse array of ArraySets, which is suitable to hold userid->packages association.
+ *
+ * @hide
+ */
+public class SparseSetArray<T> {
+ private final SparseArray<ArraySet<T>> mData = new SparseArray<>();
+
+ public SparseSetArray() {
+ }
+
+ /**
+ * Add a value at index n.
+ * @return FALSE when the value already existed at the given index, TRUE otherwise.
+ */
+ public boolean add(int n, T value) {
+ ArraySet<T> set = mData.get(n);
+ if (set == null) {
+ set = new ArraySet<>();
+ mData.put(n, set);
+ }
+ if (set.contains(value)) {
+ return true;
+ }
+ set.add(value);
+ return false;
+ }
+
+ /**
+ * @return whether a value exists at index n.
+ */
+ public boolean contains(int n, T value) {
+ final ArraySet<T> set = mData.get(n);
+ if (set == null) {
+ return false;
+ }
+ return set.contains(value);
+ }
+
+ /**
+ * Remove a value from index n.
+ * @return TRUE when the value existed at the given index and removed, FALSE otherwise.
+ */
+ public boolean remove(int n, T value) {
+ final ArraySet<T> set = mData.get(n);
+ if (set == null) {
+ return false;
+ }
+ final boolean ret = set.remove(value);
+ if (set.size() == 0) {
+ mData.remove(n);
+ }
+ return ret;
+ }
+
+ /**
+ * Remove all values from index n.
+ */
+ public void remove(int n) {
+ mData.remove(n);
+ }
+ public int size() {
+ return mData.size();
+ }
+
+ public int keyAt(int index) {
+ return mData.keyAt(index);
+ }
+
+ public int sizeAt(int index) {
+ final ArraySet<T> set = mData.valueAt(index);
+ if (set == null) {
+ return 0;
+ }
+ return set.size();
+ }
+
+ public T valueAt(int intIndex, int valueIndex) {
+ return mData.valueAt(intIndex).valueAt(valueIndex);
+ }
+}
diff --git a/core/java/android/util/StatsManager.java b/core/java/android/util/StatsManager.java
index 687aa83..51fb18a 100644
--- a/core/java/android/util/StatsManager.java
+++ b/core/java/android/util/StatsManager.java
@@ -60,9 +60,19 @@
*/
@RequiresPermission(Manifest.permission.DUMP)
public boolean addConfiguration(String configKey, byte[] config, String pkg, String cls) {
- // To prevent breakages of dependencies on old API.
-
- return false;
+ synchronized (this) {
+ try {
+ IStatsManager service = getIStatsManagerLocked();
+ if (service == null) {
+ Slog.d(TAG, "Failed to find statsd when adding configuration");
+ return false;
+ }
+ return service.addConfiguration(Long.parseLong(configKey), config, pkg, cls);
+ } catch (RemoteException e) {
+ Slog.d(TAG, "Failed to connect to statsd when adding configuration");
+ return false;
+ }
+ }
}
/**
@@ -99,7 +109,19 @@
@RequiresPermission(Manifest.permission.DUMP)
public boolean removeConfiguration(String configKey) {
// To prevent breakages of old dependencies.
- return false;
+ synchronized (this) {
+ try {
+ IStatsManager service = getIStatsManagerLocked();
+ if (service == null) {
+ Slog.d(TAG, "Failed to find statsd when removing configuration");
+ return false;
+ }
+ return service.removeConfiguration(Long.parseLong(configKey));
+ } catch (RemoteException e) {
+ Slog.d(TAG, "Failed to connect to statsd when removing configuration");
+ return false;
+ }
+ }
}
/**
@@ -132,7 +154,19 @@
public byte[] getData(String configKey) {
// TODO: remove this and all other methods with String-based config keys.
// To prevent build breakages of dependencies.
- return null;
+ synchronized (this) {
+ try {
+ IStatsManager service = getIStatsManagerLocked();
+ if (service == null) {
+ Slog.d(TAG, "Failed to find statsd when getting data");
+ return null;
+ }
+ return service.getData(Long.parseLong(configKey));
+ } catch (RemoteException e) {
+ Slog.d(TAG, "Failed to connecto statsd when getting data");
+ return null;
+ }
+ }
}
/**
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index ee6fc07..9436b29 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -438,8 +438,8 @@
List<Integer> flagsList = new ArrayList<>();
// Proof-of-rotation struct:
- // is basically a singly linked list of nodes, called levels here, each of which have the
- // following structure:
+ // A uint32 version code followed by basically a singly linked list of nodes, called levels
+ // here, each of which have the following structure:
// * length-prefix for the entire level
// - length-prefixed signed data (if previous level exists)
// * length-prefixed X509 Certificate
@@ -450,9 +450,13 @@
// - length-prefixed signature over the signed data in this level. The signature here
// is verified using the certificate from the previous level.
// The linking is provided by the certificate of each level signing the one of the next.
- while (porBuf.hasRemaining()) {
- levelCount++;
- try {
+
+ try {
+
+ // get the version code, but don't do anything with it: creator knew about all our flags
+ porBuf.getInt();
+ while (porBuf.hasRemaining()) {
+ levelCount++;
ByteBuffer level = getLengthPrefixedSlice(porBuf);
ByteBuffer signedData = getLengthPrefixedSlice(level);
int flags = level.getInt();
@@ -477,6 +481,7 @@
}
}
+ signedData.rewind();
byte[] encodedCert = readLengthPrefixedByteArray(signedData);
int signedSigAlgorithm = signedData.getInt();
if (lastCert != null && lastSigAlgorithm != signedSigAlgorithm) {
@@ -490,17 +495,17 @@
lastSigAlgorithm = sigAlgorithm;
certs.add(lastCert);
flagsList.add(flags);
- } catch (IOException | BufferUnderflowException e) {
- throw new IOException("Failed to parse Proof-of-rotation record", e);
- } catch (NoSuchAlgorithmException | InvalidKeyException
- | InvalidAlgorithmParameterException | SignatureException e) {
- throw new SecurityException(
- "Failed to verify signature over signed data for certificate #"
- + levelCount + " when verifying Proof-of-rotation record", e);
- } catch (CertificateException e) {
- throw new SecurityException("Failed to decode certificate #" + levelCount
- + " when verifying Proof-of-rotation record", e);
}
+ } catch (IOException | BufferUnderflowException e) {
+ throw new IOException("Failed to parse Proof-of-rotation record", e);
+ } catch (NoSuchAlgorithmException | InvalidKeyException
+ | InvalidAlgorithmParameterException | SignatureException e) {
+ throw new SecurityException(
+ "Failed to verify signature over signed data for certificate #"
+ + levelCount + " when verifying Proof-of-rotation record", e);
+ } catch (CertificateException e) {
+ throw new SecurityException("Failed to decode certificate #" + levelCount
+ + " when verifying Proof-of-rotation record", e);
}
return new VerifiedProofOfRotation(certs, flagsList);
}
diff --git a/core/java/android/util/apk/ApkVerityBuilder.java b/core/java/android/util/apk/ApkVerityBuilder.java
index ba21ccb..4c6e511 100644
--- a/core/java/android/util/apk/ApkVerityBuilder.java
+++ b/core/java/android/util/apk/ApkVerityBuilder.java
@@ -308,14 +308,6 @@
return rootHash;
}
- private static void bufferPut(ByteBuffer buffer, byte value) {
- // FIXME(b/72459251): buffer.put(value) does NOT work surprisingly. The position() after put
- // does NOT even change. This hack workaround the problem, but the root cause remains
- // unkonwn yet. This seems only happen when it goes through the apk install flow on my
- // setup.
- buffer.put(new byte[] { value });
- }
-
private static ByteBuffer generateFsverityHeader(ByteBuffer buffer, long fileSize, int depth,
byte[] salt) {
if (salt.length != 8) {
@@ -325,10 +317,10 @@
// TODO(b/30972906): update the reference when there is a better one in public.
buffer.put("TrueBrew".getBytes()); // magic
- bufferPut(buffer, (byte) 1); // major version
- bufferPut(buffer, (byte) 0); // minor version
- bufferPut(buffer, (byte) 12); // log2(block-size): log2(4096)
- bufferPut(buffer, (byte) 7); // log2(leaves-per-node): log2(4096 / 32)
+ buffer.put((byte) 1); // major version
+ buffer.put((byte) 0); // minor version
+ buffer.put((byte) 12); // log2(block-size): log2(4096)
+ buffer.put((byte) 7); // log2(leaves-per-node): log2(4096 / 32)
buffer.putShort((short) 1); // meta algorithm, SHA256_MODE == 1
buffer.putShort((short) 1); // data algorithm, SHA256_MODE == 1
@@ -338,8 +330,8 @@
buffer.putLong(fileSize); // original file size
- bufferPut(buffer, (byte) 0); // auth block offset, disabled here
- bufferPut(buffer, (byte) 2); // extension count
+ buffer.put((byte) 0); // auth block offset, disabled here
+ buffer.put((byte) 2); // extension count
buffer.put(salt); // salt (8 bytes)
// skip(buffer, 22); // reserved
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5bd7446..31cfebc 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -267,21 +267,21 @@
*
* @see #getState
*/
- public static final int STATE_UNKNOWN = 0;
+ public static final int STATE_UNKNOWN = ViewProtoEnums.DISPLAY_STATE_UNKNOWN; // 0
/**
* Display state: The display is off.
*
* @see #getState
*/
- public static final int STATE_OFF = 1;
+ public static final int STATE_OFF = ViewProtoEnums.DISPLAY_STATE_OFF; // 1
/**
* Display state: The display is on.
*
* @see #getState
*/
- public static final int STATE_ON = 2;
+ public static final int STATE_ON = ViewProtoEnums.DISPLAY_STATE_ON; // 2
/**
* Display state: The display is dozing in a low power state; it is still
@@ -291,7 +291,7 @@
* @see #getState
* @see android.os.PowerManager#isInteractive
*/
- public static final int STATE_DOZE = 3;
+ public static final int STATE_DOZE = ViewProtoEnums.DISPLAY_STATE_DOZE; // 3
/**
* Display state: The display is dozing in a suspended low power state; it is still
@@ -303,7 +303,7 @@
* @see #getState
* @see android.os.PowerManager#isInteractive
*/
- public static final int STATE_DOZE_SUSPEND = 4;
+ public static final int STATE_DOZE_SUSPEND = ViewProtoEnums.DISPLAY_STATE_DOZE_SUSPEND; // 4
/**
* Display state: The display is on and optimized for VR mode.
@@ -311,7 +311,7 @@
* @see #getState
* @see android.os.PowerManager#isInteractive
*/
- public static final int STATE_VR = 5;
+ public static final int STATE_VR = ViewProtoEnums.DISPLAY_STATE_VR; // 5
/**
* Display state: The display is in a suspended full power state; it is still
@@ -323,7 +323,7 @@
* @see #getState
* @see android.os.PowerManager#isInteractive
*/
- public static final int STATE_ON_SUSPEND = 6;
+ public static final int STATE_ON_SUSPEND = ViewProtoEnums.DISPLAY_STATE_ON_SUSPEND; // 6
/* The color mode constants defined below must be kept in sync with the ones in
* system/core/include/system/graphics-base.h */
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
new file mode 100644
index 0000000..5607b11
--- /dev/null
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.view;
+
+import android.app.ActivityManager;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.graphics.GraphicBuffer;
+
+/**
+ * Passed to the {@link IRecentsAnimationRunner} in order for the runner to control to let the
+ * runner control certain aspects of the recents animation, and to notify window manager when the
+ * animation has completed.
+ *
+ * {@hide}
+ */
+interface IRecentsAnimationController {
+
+ /**
+ * Takes a screenshot of the task associated with the given {@param taskId}. Only valid for the
+ * current set of task ids provided to the handler.
+ */
+ ActivityManager.TaskSnapshot screenshotTask(int taskId);
+
+ /**
+ * Notifies to the system that the animation into Recents should end, and all leashes associated
+ * with remote animation targets should be relinquished. If {@param moveHomeToTop} is true, then
+ * the home activity should be moved to the top. Otherwise, the home activity is hidden and the
+ * user is returned to the app.
+ */
+ void finish(boolean moveHomeToTop);
+
+ /**
+ * Called by the handler to indicate that the recents animation input consumer should be
+ * enabled. This is currently used to work around an issue where registering an input consumer
+ * mid-animation causes the existing motion event chain to be canceled. Instead, the caller
+ * may register the recents animation input consumer prior to starting the recents animation
+ * and then enable it mid-animation to start receiving touch events.
+ */
+ void setInputConsumerEnabled(boolean enabled);
+}
diff --git a/core/java/android/view/IRecentsAnimationRunner.aidl b/core/java/android/view/IRecentsAnimationRunner.aidl
new file mode 100644
index 0000000..ea6226b
--- /dev/null
+++ b/core/java/android/view/IRecentsAnimationRunner.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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.view;
+
+import android.view.RemoteAnimationTarget;
+import android.view.IRecentsAnimationController;
+
+/**
+ * Interface that is used to callback from window manager to the process that runs a recents
+ * animation to start or cancel it.
+ *
+ * {@hide}
+ */
+oneway interface IRecentsAnimationRunner {
+
+ /**
+ * Called when the system is ready for the handler to start animating all the visible tasks.
+ */
+ void onAnimationStart(in IRecentsAnimationController controller,
+ in RemoteAnimationTarget[] apps);
+
+ /**
+ * Called when the system needs to cancel the current animation. This can be due to the
+ * wallpaper not drawing in time, or the handler not finishing the animation within a predefined
+ * amount of time.
+ */
+ void onAnimationCanceled();
+}
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index f39e618..c28c389 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -17,6 +17,7 @@
package android.view;
import android.annotation.IntDef;
+import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Parcel;
@@ -98,8 +99,14 @@
*/
public final Rect sourceContainerBounds;
+ /**
+ * The window configuration for the target.
+ */
+ public final WindowConfiguration windowConfiguration;
+
public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
- Rect clipRect, int prefixOrderIndex, Point position, Rect sourceContainerBounds) {
+ Rect clipRect, int prefixOrderIndex, Point position, Rect sourceContainerBounds,
+ WindowConfiguration windowConfig) {
this.mode = mode;
this.taskId = taskId;
this.leash = leash;
@@ -108,6 +115,7 @@
this.prefixOrderIndex = prefixOrderIndex;
this.position = new Point(position);
this.sourceContainerBounds = new Rect(sourceContainerBounds);
+ this.windowConfiguration = windowConfig;
}
public RemoteAnimationTarget(Parcel in) {
@@ -119,6 +127,7 @@
prefixOrderIndex = in.readInt();
position = in.readParcelable(null);
sourceContainerBounds = in.readParcelable(null);
+ windowConfiguration = in.readParcelable(null);
}
@Override
@@ -136,6 +145,7 @@
dest.writeInt(prefixOrderIndex);
dest.writeParcelable(position, 0 /* flags */);
dest.writeParcelable(sourceContainerBounds, 0 /* flags */);
+ dest.writeParcelable(windowConfiguration, 0 /* flags */);
}
public static final Creator<RemoteAnimationTarget> CREATOR
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 5070151..ce7e8f3 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -353,9 +353,24 @@
return nHasShadow(mNativeRenderNode);
}
- /** setShadowColor */
- public boolean setShadowColor(int color) {
- return nSetShadowColor(mNativeRenderNode, color);
+ /** setSpotShadowColor */
+ public boolean setSpotShadowColor(int color) {
+ return nSetSpotShadowColor(mNativeRenderNode, color);
+ }
+
+ /** setAmbientShadowColor */
+ public boolean setAmbientShadowColor(int color) {
+ return nSetAmbientShadowColor(mNativeRenderNode, color);
+ }
+
+ /** getSpotShadowColor */
+ public int getSpotShadowColor() {
+ return nGetSpotShadowColor(mNativeRenderNode);
+ }
+
+ /** getAmbientShadowColor */
+ public int getAmbientShadowColor() {
+ return nGetAmbientShadowColor(mNativeRenderNode);
}
/**
@@ -915,7 +930,13 @@
@CriticalNative
private static native boolean nHasShadow(long renderNode);
@CriticalNative
- private static native boolean nSetShadowColor(long renderNode, int color);
+ private static native boolean nSetSpotShadowColor(long renderNode, int color);
+ @CriticalNative
+ private static native boolean nSetAmbientShadowColor(long renderNode, int color);
+ @CriticalNative
+ private static native int nGetSpotShadowColor(long renderNode);
+ @CriticalNative
+ private static native int nGetAmbientShadowColor(long renderNode);
@CriticalNative
private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
@CriticalNative
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 8b730f2..370c97e 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -166,18 +166,6 @@
public static final String OVERDRAW_PROPERTY_SHOW = "show";
/**
- * Defines the rendering pipeline to be used by the ThreadedRenderer.
- *
- * Possible values:
- * "opengl", will use the existing OpenGL renderer
- * "skiagl", will use Skia's OpenGL renderer
- * "skiavk", will use Skia's Vulkan renderer
- *
- * @hide
- */
- public static final String DEBUG_RENDERER_PROPERTY = "debug.hwui.renderer";
-
- /**
* Turn on to debug non-rectangular clip operations.
*
* Possible values:
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3d6a6fe..3cbd275 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,7 +17,6 @@
package android.view;
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
-
import static java.lang.Math.max;
import android.animation.AnimatorInflater;
@@ -726,6 +725,8 @@
* @attr ref android.R.styleable#View_nextFocusRight
* @attr ref android.R.styleable#View_nextFocusUp
* @attr ref android.R.styleable#View_onClick
+ * @attr ref android.R.styleable#View_outlineSpotShadowColor
+ * @attr ref android.R.styleable#View_outlineAmbientShadowColor
* @attr ref android.R.styleable#View_padding
* @attr ref android.R.styleable#View_paddingHorizontal
* @attr ref android.R.styleable#View_paddingVertical
@@ -3975,6 +3976,7 @@
/**
* Current clip bounds. to which all drawing of this view are constrained.
*/
+ @ViewDebug.ExportedProperty(category = "drawing")
Rect mClipBounds = null;
private boolean mLastIsOpaque;
@@ -4442,6 +4444,7 @@
private CheckForLongPress mPendingCheckForLongPress;
private CheckForTap mPendingCheckForTap = null;
private PerformClick mPerformClick;
+ private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
private UnsetPressedState mUnsetPressedState;
@@ -5445,6 +5448,12 @@
setAccessibilityPaneTitle(a.getString(attr));
}
break;
+ case R.styleable.View_outlineSpotShadowColor:
+ setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
+ break;
+ case R.styleable.View_outlineAmbientShadowColor:
+ setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
+ break;
}
}
@@ -7201,7 +7210,7 @@
if (gainFocus) {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
} else {
- notifyAccessibilityStateChanged(
+ notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
@@ -7271,7 +7280,8 @@
public void setAccessibilityPaneTitle(CharSequence accessibilityPaneTitle) {
if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
mAccessibilityPaneTitle = accessibilityPaneTitle;
- notifyAccessibilityStateChanged(AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
}
}
@@ -8924,9 +8934,9 @@
final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
} else {
- notifyAccessibilityStateChanged(
+ notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
}
}
@@ -8959,7 +8969,8 @@
return;
}
mAccessibilityTraversalBeforeId = beforeId;
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
/**
@@ -9002,7 +9013,8 @@
return;
}
mAccessibilityTraversalAfterId = afterId;
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
/**
@@ -9044,7 +9056,8 @@
&& mID == View.NO_ID) {
mID = generateViewId();
}
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
/**
@@ -10544,7 +10557,8 @@
if (pflags3 != mPrivateFlags3) {
mPrivateFlags3 = pflags3;
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
}
@@ -11374,7 +11388,8 @@
mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
& PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
}
@@ -11431,9 +11446,10 @@
mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
& PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
} else {
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
}
}
@@ -11609,32 +11625,11 @@
*
* @hide
*/
- public void notifyAccessibilityStateChanged(int changeType) {
- notifyAccessibilityStateChanged(this, changeType);
- }
-
- /**
- * Notifies that the accessibility state of this view changed. The change
- * is *not* local to this view and does represent structural changes such
- * as children and parent. For example, the view size changed. The
- * notification is at at most once every
- * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
- * to avoid unnecessary load to the system. Also once a view has a pending
- * notification this method is a NOP until the notification has been sent.
- *
- * @hide
- */
- public void notifyAccessibilitySubtreeChanged() {
- if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
- mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
- notifyAccessibilityStateChanged(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
- }
- }
-
- void notifyAccessibilityStateChanged(View source, int changeType) {
+ public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
return;
}
+
// Changes to views with a pane title count as window state changes, as the pane title
// marks them as significant parts of the UI.
if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) {
@@ -11652,12 +11647,49 @@
}
}
- if (mParent != null) {
+ // If this is a live region, we should send a subtree change event
+ // from this view immediately. Otherwise, we can let it propagate up.
+ if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
+ final AccessibilityEvent event = AccessibilityEvent.obtain();
+ event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ event.setContentChangeTypes(changeType);
+ sendAccessibilityEventUnchecked(event);
+ } else if (mParent != null) {
try {
- mParent.notifySubtreeAccessibilityStateChanged(this, source, changeType);
+ mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
} catch (AbstractMethodError e) {
- Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
- + " does not fully implement ViewParent", e);
+ Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
+ " does not fully implement ViewParent", e);
+ }
+ }
+ }
+
+ /**
+ * Notifies that the accessibility state of this view changed. The change
+ * is *not* local to this view and does represent structural changes such
+ * as children and parent. For example, the view size changed. The
+ * notification is at at most once every
+ * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
+ * to avoid unnecessary load to the system. Also once a view has a pending
+ * notification this method is a NOP until the notification has been sent.
+ *
+ * @hide
+ */
+ public void notifySubtreeAccessibilityStateChangedIfNeeded() {
+ if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
+ return;
+ }
+
+ if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
+ mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
+ if (mParent != null) {
+ try {
+ mParent.notifySubtreeAccessibilityStateChanged(
+ this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
+ } catch (AbstractMethodError e) {
+ Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
+ " does not fully implement ViewParent", e);
+ }
}
}
}
@@ -11679,10 +11711,8 @@
/**
* Reset the flag indicating the accessibility state of the subtree rooted
* at this view changed.
- *
- * @hide
*/
- public void resetSubtreeAccessibilityStateChanged() {
+ void resetSubtreeAccessibilityStateChanged() {
mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
}
@@ -11843,7 +11873,8 @@
|| getAccessibilitySelectionEnd() != end)
&& (start == end)) {
setAccessibilitySelection(start, end);
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
return true;
}
} break;
@@ -12643,7 +12674,7 @@
}
if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) {
if (isVisible != oldVisible) {
- notifyAccessibilityStateChanged(isVisible
+ notifyViewAccessibilityStateChangedIfNeeded(isVisible
? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
: AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
}
@@ -13860,7 +13891,7 @@
((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
dispatchVisibilityAggregated(newVisibility == VISIBLE);
}
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
}
@@ -13906,12 +13937,14 @@
|| (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
|| (changed & CONTEXT_CLICKABLE) != 0) {
if (oldIncludeForAccessibility != includeForAccessibility()) {
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
} else {
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
} else if ((changed & ENABLED_MASK) != 0) {
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
}
}
@@ -13945,13 +13978,10 @@
* @param oldt Previous vertical scroll origin.
*/
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
- ViewRootImpl root = getViewRootImpl();
- if (root != null) {
- root.getAccessibilityState()
- .getSendViewScrolledAccessibilityEvent()
- .post(this, /* dx */ l - oldl, /* dy */ t - oldt);
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
}
mBackgroundSizeChanged = true;
@@ -14347,7 +14377,7 @@
invalidateViewProperty(false, true);
invalidateParentIfNeededAndWasQuickRejected();
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
}
@@ -14391,7 +14421,7 @@
invalidateViewProperty(false, true);
invalidateParentIfNeededAndWasQuickRejected();
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
}
@@ -14435,7 +14465,7 @@
invalidateViewProperty(false, true);
invalidateParentIfNeededAndWasQuickRejected();
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
}
@@ -14472,7 +14502,7 @@
invalidateViewProperty(false, true);
invalidateParentIfNeededAndWasQuickRejected();
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
}
@@ -14509,7 +14539,7 @@
invalidateViewProperty(false, true);
invalidateParentIfNeededAndWasQuickRejected();
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
}
@@ -14712,7 +14742,7 @@
if (mTransformationInfo.mAlpha != alpha) {
// Report visibility changes, which can affect children, to accessibility
if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
mTransformationInfo.mAlpha = alpha;
if (onSetAlpha((int) (alpha * 255))) {
@@ -15214,7 +15244,7 @@
invalidateViewProperty(false, true);
invalidateParentIfNeededAndWasQuickRejected();
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
}
@@ -15248,7 +15278,7 @@
invalidateViewProperty(false, true);
invalidateParentIfNeededAndWasQuickRejected();
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
}
@@ -15418,7 +15448,7 @@
public void invalidateOutline() {
rebuildOutline();
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
invalidateViewProperty(false, false);
}
@@ -15459,14 +15489,61 @@
}
/**
- * @hide
+ * Sets the color of the spot shadow that is drawn when the view has a positive Z or
+ * elevation value.
+ * <p>
+ * By default the shadow color is black. Generally, this color will be opaque so the intensity
+ * of the shadow is consistent between different views with different colors.
+ * <p>
+ * The opacity of the final spot shadow is a function of the shadow caster height, the
+ * alpha channel of the outlineSpotShadowColor (typically opaque), and the
+ * {@link android.R.attr#spotShadowAlpha} theme attribute.
+ *
+ * @attr ref android.R.styleable#View_outlineSpotShadowColor
+ * @param color The color this View will cast for its elevation spot shadow.
*/
- public void setShadowColor(@ColorInt int color) {
- if (mRenderNode.setShadowColor(color)) {
+ public void setOutlineSpotShadowColor(@ColorInt int color) {
+ if (mRenderNode.setSpotShadowColor(color)) {
invalidateViewProperty(true, true);
}
}
+ /**
+ * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
+ * was set
+ */
+ public @ColorInt int getOutlineSpotShadowColor() {
+ return mRenderNode.getSpotShadowColor();
+ }
+
+ /**
+ * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
+ * elevation value.
+ * <p>
+ * By default the shadow color is black. Generally, this color will be opaque so the intensity
+ * of the shadow is consistent between different views with different colors.
+ * <p>
+ * The opacity of the final ambient shadow is a function of the shadow caster height, the
+ * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
+ * {@link android.R.attr#ambientShadowAlpha} theme attribute.
+ *
+ * @attr ref android.R.styleable#View_outlineAmbientShadowColor
+ * @param color The color this View will cast for its elevation shadow.
+ */
+ public void setOutlineAmbientShadowColor(@ColorInt int color) {
+ if (mRenderNode.setAmbientShadowColor(color)) {
+ invalidateViewProperty(true, true);
+ }
+ }
+
+ /**
+ * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
+ * nothing was set
+ */
+ public @ColorInt int getOutlineAmbientShadowColor() {
+ return mRenderNode.getAmbientShadowColor();
+ }
+
/** @hide */
public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
@@ -15613,7 +15690,7 @@
}
invalidateParentIfNeeded();
}
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
}
@@ -15661,7 +15738,7 @@
}
invalidateParentIfNeeded();
}
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
}
@@ -16539,6 +16616,18 @@
}
/**
+ * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
+ * This event is sent at most once every
+ * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
+ */
+ private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
+ if (mSendViewScrolledAccessibilityEvent == null) {
+ mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
+ }
+ mSendViewScrolledAccessibilityEvent.post(dx, dy);
+ }
+
+ /**
* Called by a parent to request that a child update its values for mScrollX
* and mScrollY if necessary. This will typically be done if the child is
* animating a scroll using a {@link android.widget.Scroller Scroller}
@@ -17793,13 +17882,7 @@
removeUnsetPressCallback();
removeLongPressCallback();
removePerformClickCallback();
- if (mAttachInfo != null
- && mAttachInfo.mViewRootImpl.mAccessibilityState != null
- && mAttachInfo.mViewRootImpl.mAccessibilityState.isScrollEventSenderInitialized()) {
- mAttachInfo.mViewRootImpl.mAccessibilityState
- .getSendViewScrolledAccessibilityEvent()
- .cancelIfPendingFor(this);
- }
+ cancel(mSendViewScrolledAccessibilityEvent);
stopNestedScroll();
// Anything that started animating right before detach should already
@@ -20427,7 +20510,7 @@
mForegroundInfo.mBoundsChanged = true;
}
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
return changed;
}
@@ -21871,7 +21954,8 @@
if (selected) {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
} else {
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
}
}
@@ -26458,6 +26542,53 @@
}
/**
+ * Resuable callback for sending
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
+ */
+ private class SendViewScrolledAccessibilityEvent implements Runnable {
+ public volatile boolean mIsPending;
+ public int mDeltaX;
+ public int mDeltaY;
+
+ public void post(int dx, int dy) {
+ mDeltaX += dx;
+ mDeltaY += dy;
+ if (!mIsPending) {
+ mIsPending = true;
+ postDelayed(this, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
+ }
+ }
+
+ @Override
+ public void run() {
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ AccessibilityEvent event = AccessibilityEvent.obtain(
+ AccessibilityEvent.TYPE_VIEW_SCROLLED);
+ event.setScrollDeltaX(mDeltaX);
+ event.setScrollDeltaY(mDeltaY);
+ sendAccessibilityEventUnchecked(event);
+ }
+ reset();
+ }
+
+ private void reset() {
+ mIsPending = false;
+ mDeltaX = 0;
+ mDeltaY = 0;
+ }
+ }
+
+ /**
+ * Remove the pending callback for sending a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
+ */
+ private void cancel(@Nullable SendViewScrolledAccessibilityEvent callback) {
+ if (callback == null || !callback.mIsPending) return;
+ removeCallbacks(callback);
+ callback.reset();
+ }
+
+ /**
* <p>
* This class represents a delegate that can be registered in a {@link View}
* to enhance accessibility support via composition rather via inheritance.
@@ -26903,6 +27034,8 @@
stream.addProperty("drawing:scaleY", getScaleY());
stream.addProperty("drawing:pivotX", getPivotX());
stream.addProperty("drawing:pivotY", getPivotY());
+ stream.addProperty("drawing:clipBounds",
+ mClipBounds == null ? null : mClipBounds.toString());
stream.addProperty("drawing:opaque", isOpaque());
stream.addProperty("drawing:alpha", getAlpha());
stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
@@ -26914,6 +27047,8 @@
stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
+ stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
+ stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
// focus
stream.addProperty("focus:hasFocus", hasFocus());
@@ -27074,7 +27209,7 @@
mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
mAttachInfo.mTooltipHost = this;
// The available accessibility actions have changed
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
return true;
}
@@ -27094,7 +27229,7 @@
mAttachInfo.mTooltipHost = null;
}
// The available accessibility actions have changed
- notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
}
private boolean showLongClickTooltip(int x, int y) {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 4631261..a8bdb85 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3649,34 +3649,44 @@
return ViewGroup.class.getName();
}
+ @Override
+ public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) {
+ // If this is a live region, we should send a subtree change event
+ // from this view. Otherwise, we can let it propagate up.
+ if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
+ } else if (mParent != null) {
+ try {
+ mParent.notifySubtreeAccessibilityStateChanged(this, source, changeType);
+ } catch (AbstractMethodError e) {
+ Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
+ " does not fully implement ViewParent", e);
+ }
+ }
+ }
+
/** @hide */
@Override
- public void notifyAccessibilitySubtreeChanged() {
+ public void notifySubtreeAccessibilityStateChangedIfNeeded() {
if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
return;
}
// If something important for a11y is happening in this subtree, make sure it's dispatched
// from a view that is important for a11y so it doesn't get lost.
- if (getImportantForAccessibility() != IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
- && !isImportantForAccessibility()
- && getChildCount() > 0) {
+ if ((getImportantForAccessibility() != IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
+ && !isImportantForAccessibility() && (getChildCount() > 0)) {
ViewParent a11yParent = getParentForAccessibility();
if (a11yParent instanceof View) {
- ((View) a11yParent).notifyAccessibilitySubtreeChanged();
+ ((View) a11yParent).notifySubtreeAccessibilityStateChangedIfNeeded();
return;
}
}
- super.notifyAccessibilitySubtreeChanged();
+ super.notifySubtreeAccessibilityStateChangedIfNeeded();
}
@Override
- public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) {
- notifyAccessibilityStateChanged(source, changeType);
- }
-
- /** @hide */
- @Override
- public void resetSubtreeAccessibilityStateChanged() {
+ void resetSubtreeAccessibilityStateChanged() {
super.resetSubtreeAccessibilityStateChanged();
View[] children = mChildren;
final int childCount = mChildrenCount;
@@ -5088,7 +5098,7 @@
}
if (child.getVisibility() != View.GONE) {
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
if (mTransientIndices != null) {
@@ -5358,7 +5368,7 @@
dispatchViewRemoved(view);
if (view.getVisibility() != View.GONE) {
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
@@ -6077,7 +6087,7 @@
if (invalidate) {
invalidateViewProperty(false, false);
}
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
@Override
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 30f584c..7bd197e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -89,11 +89,9 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.AccessibilityNodeProvider;
-import android.view.accessibility.AccessibilityViewHierarchyState;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
-import android.view.accessibility.ThrottlingAccessibilityEventSender;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.inputmethod.InputMethodManager;
@@ -115,6 +113,7 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.concurrent.CountDownLatch;
/**
@@ -461,6 +460,10 @@
new AccessibilityInteractionConnectionManager();
final HighContrastTextManager mHighContrastTextManager;
+ SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent;
+
+ HashSet<View> mTempHashSet;
+
private final int mDensity;
private final int mNoncompatDensity;
@@ -475,8 +478,6 @@
private boolean mNeedsRendererSetup;
- protected AccessibilityViewHierarchyState mAccessibilityState;
-
/**
* Consistency verifier for debugging purposes.
*/
@@ -895,6 +896,26 @@
return mWindowAttributes.getTitle();
}
+ /**
+ * @return the width of the root view. Note that this will return {@code -1} until the first
+ * layout traversal, when the width is set.
+ *
+ * @hide
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * @return the height of the root view. Note that this will return {@code -1} until the first
+ * layout traversal, when the height is set.
+ *
+ * @hide
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
void destroyHardwareResources() {
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mThreadedRenderer.destroyHardwareResources(mView);
@@ -1974,6 +1995,7 @@
final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets);
final boolean surfaceSizeChanged = (relayoutResult
& WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
+ surfaceChanged |= surfaceSizeChanged;
final boolean alwaysConsumeNavBarChanged =
mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar;
if (contentInsetsChanged) {
@@ -7258,9 +7280,11 @@
* {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
*/
private void postSendWindowContentChangedCallback(View source, int changeType) {
- getAccessibilityState()
- .getSendWindowContentChangedAccessibilityEvent()
- .runOrPost(source, changeType);
+ if (mSendWindowContentChangedAccessibilityEvent == null) {
+ mSendWindowContentChangedAccessibilityEvent =
+ new SendWindowContentChangedAccessibilityEvent();
+ }
+ mSendWindowContentChangedAccessibilityEvent.runOrPost(source, changeType);
}
/**
@@ -7268,20 +7292,11 @@
* {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
*/
private void removeSendWindowContentChangedCallback() {
- if (mAccessibilityState != null
- && mAccessibilityState.isWindowContentChangedEventSenderInitialized()) {
- ThrottlingAccessibilityEventSender.cancelIfPending(
- mAccessibilityState.getSendWindowContentChangedAccessibilityEvent());
+ if (mSendWindowContentChangedAccessibilityEvent != null) {
+ mHandler.removeCallbacks(mSendWindowContentChangedAccessibilityEvent);
}
}
- AccessibilityViewHierarchyState getAccessibilityState() {
- if (mAccessibilityState == null) {
- mAccessibilityState = new AccessibilityViewHierarchyState();
- }
- return mAccessibilityState;
- }
-
@Override
public boolean showContextMenuForChild(View originalView) {
return false;
@@ -7317,8 +7332,12 @@
return false;
}
- // Send any pending event to prevent reordering
- flushPendingAccessibilityEvents();
+ // Immediately flush pending content changed event (if any) to preserve event order
+ if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
+ && mSendWindowContentChangedAccessibilityEvent != null
+ && mSendWindowContentChangedAccessibilityEvent.mSource != null) {
+ mSendWindowContentChangedAccessibilityEvent.removeCallbacksAndRun();
+ }
// Intercept accessibility focus events fired by virtual nodes to keep
// track of accessibility focus position in such nodes.
@@ -7362,19 +7381,6 @@
return true;
}
- /** @hide */
- public void flushPendingAccessibilityEvents() {
- if (mAccessibilityState != null) {
- if (mAccessibilityState.isScrollEventSenderInitialized()) {
- mAccessibilityState.getSendViewScrolledAccessibilityEvent().sendNowIfPending();
- }
- if (mAccessibilityState.isWindowContentChangedEventSenderInitialized()) {
- mAccessibilityState.getSendWindowContentChangedAccessibilityEvent()
- .sendNowIfPending();
- }
- }
- }
-
/**
* Updates the focused virtual view, when necessary, in response to a
* content changed event.
@@ -7509,6 +7515,39 @@
return View.TEXT_ALIGNMENT_RESOLVED_DEFAULT;
}
+ private View getCommonPredecessor(View first, View second) {
+ if (mTempHashSet == null) {
+ mTempHashSet = new HashSet<View>();
+ }
+ HashSet<View> seen = mTempHashSet;
+ seen.clear();
+ View firstCurrent = first;
+ while (firstCurrent != null) {
+ seen.add(firstCurrent);
+ ViewParent firstCurrentParent = firstCurrent.mParent;
+ if (firstCurrentParent instanceof View) {
+ firstCurrent = (View) firstCurrentParent;
+ } else {
+ firstCurrent = null;
+ }
+ }
+ View secondCurrent = second;
+ while (secondCurrent != null) {
+ if (seen.contains(secondCurrent)) {
+ seen.clear();
+ return secondCurrent;
+ }
+ ViewParent secondCurrentParent = secondCurrent.mParent;
+ if (secondCurrentParent instanceof View) {
+ secondCurrent = (View) secondCurrentParent;
+ } else {
+ secondCurrent = null;
+ }
+ }
+ seen.clear();
+ return null;
+ }
+
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
@@ -8119,6 +8158,80 @@
}
}
+ private class SendWindowContentChangedAccessibilityEvent implements Runnable {
+ private int mChangeTypes = 0;
+
+ public View mSource;
+ public long mLastEventTimeMillis;
+
+ @Override
+ public void run() {
+ // Protect against re-entrant code and attempt to do the right thing in the case that
+ // we're multithreaded.
+ View source = mSource;
+ mSource = null;
+ if (source == null) {
+ Log.e(TAG, "Accessibility content change has no source");
+ return;
+ }
+ // The accessibility may be turned off while we were waiting so check again.
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ mLastEventTimeMillis = SystemClock.uptimeMillis();
+ AccessibilityEvent event = AccessibilityEvent.obtain();
+ event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ event.setContentChangeTypes(mChangeTypes);
+ source.sendAccessibilityEventUnchecked(event);
+ } else {
+ mLastEventTimeMillis = 0;
+ }
+ // In any case reset to initial state.
+ source.resetSubtreeAccessibilityStateChanged();
+ mChangeTypes = 0;
+ }
+
+ public void runOrPost(View source, int changeType) {
+ if (mHandler.getLooper() != Looper.myLooper()) {
+ CalledFromWrongThreadException e = new CalledFromWrongThreadException("Only the "
+ + "original thread that created a view hierarchy can touch its views.");
+ // TODO: Throw the exception
+ Log.e(TAG, "Accessibility content change on non-UI thread. Future Android "
+ + "versions will throw an exception.", e);
+ // Attempt to recover. This code does not eliminate the thread safety issue, but
+ // it should force any issues to happen near the above log.
+ mHandler.removeCallbacks(this);
+ if (mSource != null) {
+ // Dispatch whatever was pending. It's still possible that the runnable started
+ // just before we removed the callbacks, and bad things will happen, but at
+ // least they should happen very close to the logged error.
+ run();
+ }
+ }
+ if (mSource != null) {
+ // If there is no common predecessor, then mSource points to
+ // a removed view, hence in this case always prefer the source.
+ View predecessor = getCommonPredecessor(mSource, source);
+ mSource = (predecessor != null) ? predecessor : source;
+ mChangeTypes |= changeType;
+ return;
+ }
+ mSource = source;
+ mChangeTypes = changeType;
+ final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
+ final long minEventIntevalMillis =
+ ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
+ if (timeSinceLastMillis >= minEventIntevalMillis) {
+ removeCallbacksAndRun();
+ } else {
+ mHandler.postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
+ }
+ }
+
+ public void removeCallbacksAndRun() {
+ mHandler.removeCallbacks(this);
+ run();
+ }
+ }
+
private static class KeyFallbackManager {
// This is used to ensure that key-fallback events are only dispatched once. We attempt
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3bb3a4c..1c5e871 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -98,11 +98,13 @@
int DOCKED_BOTTOM = 4;
/** @hide */
- final static String INPUT_CONSUMER_PIP = "pip_input_consumer";
+ String INPUT_CONSUMER_PIP = "pip_input_consumer";
/** @hide */
- final static String INPUT_CONSUMER_NAVIGATION = "nav_input_consumer";
+ String INPUT_CONSUMER_NAVIGATION = "nav_input_consumer";
/** @hide */
- final static String INPUT_CONSUMER_WALLPAPER = "wallpaper_input_consumer";
+ String INPUT_CONSUMER_WALLPAPER = "wallpaper_input_consumer";
+ /** @hide */
+ String INPUT_CONSUMER_RECENTS_ANIMATION = "recents_animation_input_consumer";
/**
* Not set up for a transition.
diff --git a/core/java/android/view/accessibility/AccessibilityViewHierarchyState.java b/core/java/android/view/accessibility/AccessibilityViewHierarchyState.java
deleted file mode 100644
index 447fafa..0000000
--- a/core/java/android/view/accessibility/AccessibilityViewHierarchyState.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.accessibility;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-/**
- * Accessibility-related state of a {@link android.view.ViewRootImpl}
- *
- * @hide
- */
-public class AccessibilityViewHierarchyState {
- private @Nullable SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
- private @Nullable SendWindowContentChangedAccessibilityEvent
- mSendWindowContentChangedAccessibilityEvent;
-
- /**
- * @return a {@link SendViewScrolledAccessibilityEvent}, creating one if needed
- */
- public @NonNull SendViewScrolledAccessibilityEvent getSendViewScrolledAccessibilityEvent() {
- if (mSendViewScrolledAccessibilityEvent == null) {
- mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
- }
- return mSendViewScrolledAccessibilityEvent;
- }
-
- public boolean isScrollEventSenderInitialized() {
- return mSendViewScrolledAccessibilityEvent != null;
- }
-
- /**
- * @return a {@link SendWindowContentChangedAccessibilityEvent}, creating one if needed
- */
- public @NonNull SendWindowContentChangedAccessibilityEvent
- getSendWindowContentChangedAccessibilityEvent() {
- if (mSendWindowContentChangedAccessibilityEvent == null) {
- mSendWindowContentChangedAccessibilityEvent =
- new SendWindowContentChangedAccessibilityEvent();
- }
- return mSendWindowContentChangedAccessibilityEvent;
- }
-
- public boolean isWindowContentChangedEventSenderInitialized() {
- return mSendWindowContentChangedAccessibilityEvent != null;
- }
-}
diff --git a/core/java/android/view/accessibility/SendViewScrolledAccessibilityEvent.java b/core/java/android/view/accessibility/SendViewScrolledAccessibilityEvent.java
deleted file mode 100644
index 40a1b6a..0000000
--- a/core/java/android/view/accessibility/SendViewScrolledAccessibilityEvent.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.accessibility;
-
-
-import android.annotation.NonNull;
-import android.view.View;
-
-/**
- * Sender for {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
- *
- * @hide
- */
-public class SendViewScrolledAccessibilityEvent extends ThrottlingAccessibilityEventSender {
-
- public int mDeltaX;
- public int mDeltaY;
-
- /**
- * Post a scroll event to be sent for the given view
- */
- public void post(View source, int dx, int dy) {
- if (!isPendingFor(source)) sendNowIfPending();
-
- mDeltaX += dx;
- mDeltaY += dy;
-
- if (!isPendingFor(source)) scheduleFor(source);
- }
-
- @Override
- protected void performSendEvent(@NonNull View source) {
- AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
- event.setScrollDeltaX(mDeltaX);
- event.setScrollDeltaY(mDeltaY);
- source.sendAccessibilityEventUnchecked(event);
- }
-
- @Override
- protected void resetState(@NonNull View source) {
- mDeltaX = 0;
- mDeltaY = 0;
- }
-}
diff --git a/core/java/android/view/accessibility/SendWindowContentChangedAccessibilityEvent.java b/core/java/android/view/accessibility/SendWindowContentChangedAccessibilityEvent.java
deleted file mode 100644
index df38fba..0000000
--- a/core/java/android/view/accessibility/SendWindowContentChangedAccessibilityEvent.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.accessibility;
-
-
-import static com.android.internal.util.ObjectUtils.firstNotNull;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.view.View;
-import android.view.ViewParent;
-
-import java.util.HashSet;
-
-/**
- * @hide
- */
-public class SendWindowContentChangedAccessibilityEvent
- extends ThrottlingAccessibilityEventSender {
-
- private int mChangeTypes = 0;
-
- private HashSet<View> mTempHashSet;
-
- @Override
- protected void performSendEvent(@NonNull View source) {
- AccessibilityEvent event = AccessibilityEvent.obtain();
- event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
- event.setContentChangeTypes(mChangeTypes);
- source.sendAccessibilityEventUnchecked(event);
- }
-
- @Override
- protected void resetState(@Nullable View source) {
- if (source != null) {
- source.resetSubtreeAccessibilityStateChanged();
- }
- mChangeTypes = 0;
- }
-
- /**
- * Post the {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event with the given
- * {@link AccessibilityEvent#getContentChangeTypes change type} for the given view
- */
- public void runOrPost(View source, int changeType) {
- if (source.getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
- sendNowIfPending();
- mChangeTypes = changeType;
- sendNow(source);
- } else {
- mChangeTypes |= changeType;
- scheduleFor(source);
- }
- }
-
- @Override
- protected @Nullable View tryMerge(@NonNull View oldSource, @NonNull View newSource) {
- // If there is no common predecessor, then oldSource points to
- // a removed view, hence in this case always prefer the newSource.
- return firstNotNull(
- getCommonPredecessor(oldSource, newSource),
- newSource);
- }
-
- private View getCommonPredecessor(View first, View second) {
- if (mTempHashSet == null) {
- mTempHashSet = new HashSet<>();
- }
- HashSet<View> seen = mTempHashSet;
- seen.clear();
- View firstCurrent = first;
- while (firstCurrent != null) {
- seen.add(firstCurrent);
- ViewParent firstCurrentParent = firstCurrent.getParent();
- if (firstCurrentParent instanceof View) {
- firstCurrent = (View) firstCurrentParent;
- } else {
- firstCurrent = null;
- }
- }
- View secondCurrent = second;
- while (secondCurrent != null) {
- if (seen.contains(secondCurrent)) {
- seen.clear();
- return secondCurrent;
- }
- ViewParent secondCurrentParent = secondCurrent.getParent();
- if (secondCurrentParent instanceof View) {
- secondCurrent = (View) secondCurrentParent;
- } else {
- secondCurrent = null;
- }
- }
- seen.clear();
- return null;
- }
-}
diff --git a/core/java/android/view/accessibility/ThrottlingAccessibilityEventSender.java b/core/java/android/view/accessibility/ThrottlingAccessibilityEventSender.java
deleted file mode 100644
index 66fa301..0000000
--- a/core/java/android/view/accessibility/ThrottlingAccessibilityEventSender.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.accessibility;
-
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.SystemClock;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewRootImpl;
-import android.view.ViewRootImpl.CalledFromWrongThreadException;
-
-/**
- * A throttling {@link AccessibilityEvent} sender that relies on its currently associated
- * 'source' view's {@link View#postDelayed delayed execution} to delay and possibly
- * {@link #tryMerge merge} together any events that come in less than
- * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval
- * the configured amount of milliseconds} apart.
- *
- * The suggested usage is to create a singleton extending this class, holding any state specific to
- * the particular event type that the subclass represents, and have an 'entrypoint' method that
- * delegates to {@link #scheduleFor(View)}.
- * For example:
- *
- * {@code
- * public void post(View view, String text, int resId) {
- * mText = text;
- * mId = resId;
- * scheduleFor(view);
- * }
- * }
- *
- * @see #scheduleFor(View)
- * @see #tryMerge(View, View)
- * @see #performSendEvent(View)
- * @hide
- */
-public abstract class ThrottlingAccessibilityEventSender {
-
- private static final boolean DEBUG = false;
- private static final String LOG_TAG = "ThrottlingA11ySender";
-
- View mSource;
- private long mLastSendTimeMillis = Long.MIN_VALUE;
- private boolean mIsPending = false;
-
- private final Runnable mWorker = () -> {
- View source = mSource;
- if (DEBUG) Log.d(LOG_TAG, thisClass() + ".run(mSource = " + source + ")");
-
- if (!checkAndResetIsPending() || source == null) {
- resetStateInternal();
- return;
- }
-
- // Accessibility may be turned off while we were waiting
- if (isAccessibilityEnabled(source)) {
- mLastSendTimeMillis = SystemClock.uptimeMillis();
- performSendEvent(source);
- }
- resetStateInternal();
- };
-
- /**
- * Populate and send an {@link AccessibilityEvent} using the given {@code source} view, as well
- * as any extra data from this instance's state.
- *
- * Send the event via {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)} or
- * {@link View#sendAccessibilityEvent(int)} on the provided {@code source} view to allow for
- * overrides of those methods on {@link View} subclasses to take effect, and/or make sure that
- * an {@link View#getAccessibilityDelegate() accessibility delegate} is not ignored if any.
- */
- protected abstract void performSendEvent(@NonNull View source);
-
- /**
- * Perform optional cleanup after {@link #performSendEvent}
- *
- * @param source the view this event was associated with
- */
- protected abstract void resetState(@Nullable View source);
-
- /**
- * Attempt to merge the pending events for source views {@code oldSource} and {@code newSource}
- * into one, with source set to the resulting {@link View}
- *
- * A result of {@code null} means merger is not possible, resulting in the currently pending
- * event being flushed before proceeding.
- */
- protected @Nullable View tryMerge(@NonNull View oldSource, @NonNull View newSource) {
- return null;
- }
-
- /**
- * Schedules a {@link #performSendEvent} with the source {@link View} set to given
- * {@code source}
- *
- * If an event is already scheduled a {@link #tryMerge merge} will be attempted.
- * If merging is not possible (as indicated by the null result from {@link #tryMerge}),
- * the currently scheduled event will be {@link #sendNow sent immediately} and the new one
- * will be scheduled afterwards.
- */
- protected final void scheduleFor(@NonNull View source) {
- if (DEBUG) Log.d(LOG_TAG, thisClass() + ".scheduleFor(source = " + source + ")");
-
- Handler uiHandler = source.getHandler();
- if (uiHandler == null || uiHandler.getLooper() != Looper.myLooper()) {
- CalledFromWrongThreadException e = new CalledFromWrongThreadException(
- "Expected to be called from main thread but was called from "
- + Thread.currentThread());
- // TODO: Throw the exception
- Log.e(LOG_TAG, "Accessibility content change on non-UI thread. Future Android "
- + "versions will throw an exception.", e);
- }
-
- if (!isAccessibilityEnabled(source)) return;
-
- if (mIsPending) {
- View merged = tryMerge(mSource, source);
- if (merged != null) {
- setSource(merged);
- return;
- } else {
- sendNow();
- }
- }
-
- setSource(source);
-
- final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastSendTimeMillis;
- final long minEventIntervalMillis =
- ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
- if (timeSinceLastMillis >= minEventIntervalMillis) {
- sendNow();
- } else {
- mSource.postDelayed(mWorker, minEventIntervalMillis - timeSinceLastMillis);
- }
- }
-
- static boolean isAccessibilityEnabled(@NonNull View contextProvider) {
- return AccessibilityManager.getInstance(contextProvider.getContext()).isEnabled();
- }
-
- protected final void sendNow(View source) {
- setSource(source);
- sendNow();
- }
-
- private void sendNow() {
- mSource.removeCallbacks(mWorker);
- mWorker.run();
- }
-
- /**
- * Flush the event if one is pending
- */
- public void sendNowIfPending() {
- if (mIsPending) sendNow();
- }
-
- /**
- * Cancel the event if one is pending and is for the given view
- */
- public final void cancelIfPendingFor(@NonNull View source) {
- if (isPendingFor(source)) cancelIfPending(this);
- }
-
- /**
- * @return whether an event is currently pending for the given source view
- */
- protected final boolean isPendingFor(@Nullable View source) {
- return mIsPending && mSource == source;
- }
-
- /**
- * Cancel the event if one is not null and pending
- */
- public static void cancelIfPending(@Nullable ThrottlingAccessibilityEventSender sender) {
- if (sender == null || !sender.checkAndResetIsPending()) return;
- sender.mSource.removeCallbacks(sender.mWorker);
- sender.resetStateInternal();
- }
-
- void resetStateInternal() {
- if (DEBUG) Log.d(LOG_TAG, thisClass() + ".resetStateInternal()");
-
- resetState(mSource);
- setSource(null);
- }
-
- boolean checkAndResetIsPending() {
- if (mIsPending) {
- mIsPending = false;
- return true;
- } else {
- return false;
- }
- }
-
- private void setSource(@Nullable View source) {
- if (DEBUG) Log.d(LOG_TAG, thisClass() + ".setSource(" + source + ")");
-
- if (source == null && mIsPending) {
- Log.e(LOG_TAG, "mSource nullified while callback still pending: " + this);
- return;
- }
-
- if (source != null && !mIsPending) {
- // At most one can be pending at any given time
- View oldSource = mSource;
- if (oldSource != null) {
- ViewRootImpl viewRootImpl = oldSource.getViewRootImpl();
- if (viewRootImpl != null) {
- viewRootImpl.flushPendingAccessibilityEvents();
- }
- }
- mIsPending = true;
- }
- mSource = source;
- }
-
- String thisClass() {
- return getClass().getSimpleName();
- }
-
- @Override
- public String toString() {
- return thisClass() + "(" + mSource + ")";
- }
-
-}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 4b24a71..dac1998 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1099,6 +1099,30 @@
}
/**
+ * Gets the id of the {@link UserData} used for
+ * <a href="AutofillService.html#FieldClassification">field classification</a>.
+ *
+ * <p>This method is useful when the service must check the status of the {@link UserData} in
+ * the device without fetching the whole object.
+ *
+ * <p><b>Note:</b> This method should only be called by an app providing an autofill service,
+ * and it's ignored if the caller currently doesn't have an enabled autofill service for
+ * the user.
+ *
+ * @return id of the {@link UserData} previously set by {@link #setUserData(UserData)}
+ * or {@code null} if it was reset or if the caller currently does not have an enabled autofill
+ * service for the user.
+ */
+ @Nullable public String getUserDataId() {
+ try {
+ return mService.getUserDataId();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return null;
+ }
+ }
+
+ /**
* Gets the user data used for
* <a href="AutofillService.html#FieldClassification">field classification</a>.
*
@@ -1119,7 +1143,7 @@
}
/**
- * Sets the user data used for
+ * Sets the {@link UserData} used for
* <a href="AutofillService.html#FieldClassification">field classification</a>
*
* <p><b>Note:</b> This method should only be called by an app providing an autofill service,
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 1a11fbb..0018547 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -56,6 +56,7 @@
boolean isServiceEnabled(int userId, String packageName);
void onPendingSaveUi(int operation, IBinder token);
UserData getUserData();
+ String getUserDataId();
void setUserData(in UserData userData);
boolean isFieldClassificationEnabled();
ComponentName getAutofillServiceComponentName();
diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java
new file mode 100644
index 0000000..af55dcd
--- /dev/null
+++ b/core/java/android/view/textclassifier/SystemTextClassifier.java
@@ -0,0 +1,197 @@
+/*
+ * 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.view.textclassifier;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.content.Context;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.service.textclassifier.ITextClassificationCallback;
+import android.service.textclassifier.ITextClassifierService;
+import android.service.textclassifier.ITextLinksCallback;
+import android.service.textclassifier.ITextSelectionCallback;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Proxy to the system's default TextClassifier.
+ */
+final class SystemTextClassifier implements TextClassifier {
+
+ private static final String LOG_TAG = "SystemTextClassifier";
+
+ private final ITextClassifierService mManagerService;
+ private final TextClassifier mFallback;
+
+ SystemTextClassifier(Context context) throws ServiceManager.ServiceNotFoundException {
+ mManagerService = ITextClassifierService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.TEXT_CLASSIFICATION_SERVICE));
+ mFallback = new TextClassifierImpl(context);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @WorkerThread
+ public TextSelection suggestSelection(
+ @NonNull CharSequence text,
+ @IntRange(from = 0) int selectionStartIndex,
+ @IntRange(from = 0) int selectionEndIndex,
+ @Nullable TextSelection.Options options) {
+ Utils.validate(text, selectionStartIndex, selectionEndIndex, false /* allowInMainThread */);
+ try {
+ final TextSelectionCallback callback = new TextSelectionCallback();
+ mManagerService.onSuggestSelection(
+ text, selectionStartIndex, selectionEndIndex, options, callback);
+ final TextSelection selection = callback.mReceiver.get();
+ if (selection != null) {
+ return selection;
+ }
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ } catch (InterruptedException e) {
+ Log.d(LOG_TAG, e.getMessage());
+ }
+ return mFallback.suggestSelection(text, selectionStartIndex, selectionEndIndex, options);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @WorkerThread
+ public TextClassification classifyText(
+ @NonNull CharSequence text,
+ @IntRange(from = 0) int startIndex,
+ @IntRange(from = 0) int endIndex,
+ @Nullable TextClassification.Options options) {
+ Utils.validate(text, startIndex, endIndex, false /* allowInMainThread */);
+ try {
+ final TextClassificationCallback callback = new TextClassificationCallback();
+ mManagerService.onClassifyText(text, startIndex, endIndex, options, callback);
+ final TextClassification classification = callback.mReceiver.get();
+ if (classification != null) {
+ return classification;
+ }
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ } catch (InterruptedException e) {
+ Log.d(LOG_TAG, e.getMessage());
+ }
+ return mFallback.classifyText(text, startIndex, endIndex, options);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @WorkerThread
+ public TextLinks generateLinks(
+ @NonNull CharSequence text, @Nullable TextLinks.Options options) {
+ Utils.validate(text, false /* allowInMainThread */);
+ try {
+ final TextLinksCallback callback = new TextLinksCallback();
+ mManagerService.onGenerateLinks(text, options, callback);
+ final TextLinks links = callback.mReceiver.get();
+ if (links != null) {
+ return links;
+ }
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ } catch (InterruptedException e) {
+ Log.d(LOG_TAG, e.getMessage());
+ }
+ return mFallback.generateLinks(text, options);
+ }
+
+ private static final class TextSelectionCallback extends ITextSelectionCallback.Stub {
+
+ final ResponseReceiver<TextSelection> mReceiver = new ResponseReceiver<>();
+
+ @Override
+ public void onSuccess(TextSelection selection) {
+ mReceiver.onSuccess(selection);
+ }
+
+ @Override
+ public void onFailure() {
+ mReceiver.onFailure();
+ }
+ }
+
+ private static final class TextClassificationCallback extends ITextClassificationCallback.Stub {
+
+ final ResponseReceiver<TextClassification> mReceiver = new ResponseReceiver<>();
+
+ @Override
+ public void onSuccess(TextClassification classification) {
+ mReceiver.onSuccess(classification);
+ }
+
+ @Override
+ public void onFailure() {
+ mReceiver.onFailure();
+ }
+ }
+
+ private static final class TextLinksCallback extends ITextLinksCallback.Stub {
+
+ final ResponseReceiver<TextLinks> mReceiver = new ResponseReceiver<>();
+
+ @Override
+ public void onSuccess(TextLinks links) {
+ mReceiver.onSuccess(links);
+ }
+
+ @Override
+ public void onFailure() {
+ mReceiver.onFailure();
+ }
+ }
+
+ private static final class ResponseReceiver<T> {
+
+ private final CountDownLatch mLatch = new CountDownLatch(1);
+
+ private T mResponse;
+
+ public void onSuccess(T response) {
+ mResponse = response;
+ mLatch.countDown();
+ }
+
+ public void onFailure() {
+ Log.e(LOG_TAG, "Request failed.", null);
+ mLatch.countDown();
+ }
+
+ @Nullable
+ public T get() throws InterruptedException {
+ // If this is running on the main thread, do not block for a response.
+ // The response will unfortunately be null and the TextClassifier should depend on its
+ // fallback.
+ // NOTE that TextClassifier calls should preferably always be called on a worker thread.
+ if (Looper.myLooper() != Looper.getMainLooper()) {
+ mLatch.await(2, TimeUnit.SECONDS);
+ }
+ return mResponse;
+ }
+ }
+}
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl b/core/java/android/view/textclassifier/TextClassification.aidl
similarity index 77%
copy from telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
copy to core/java/android/view/textclassifier/TextClassification.aidl
index d648a35..9fefe5d 100644
--- a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
+++ b/core/java/android/view/textclassifier/TextClassification.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -14,6 +14,7 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.view.textclassifier;
-parcelable ImsStreamMediaProfile;
+parcelable TextClassification;
+parcelable TextClassification.Options;
\ No newline at end of file
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index 54e93d5..a6a2a94 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -97,7 +97,7 @@
* });
* }</pre>
*/
-public final class TextClassification {
+public final class TextClassification implements Parcelable {
/**
* @hide
@@ -310,42 +310,6 @@
mSignature);
}
- /** Helper for parceling via #ParcelableWrapper. */
- private void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mText);
- final Bitmap primaryIconBitmap = drawableToBitmap(mPrimaryIcon, MAX_PRIMARY_ICON_SIZE);
- dest.writeInt(primaryIconBitmap != null ? 1 : 0);
- if (primaryIconBitmap != null) {
- primaryIconBitmap.writeToParcel(dest, flags);
- }
- dest.writeString(mPrimaryLabel);
- dest.writeInt(mPrimaryIntent != null ? 1 : 0);
- if (mPrimaryIntent != null) {
- mPrimaryIntent.writeToParcel(dest, flags);
- }
- // mPrimaryOnClickListener is not parcelable.
- dest.writeTypedList(drawablesToBitmaps(mSecondaryIcons, MAX_SECONDARY_ICON_SIZE));
- dest.writeStringList(mSecondaryLabels);
- dest.writeTypedList(mSecondaryIntents);
- mEntityConfidence.writeToParcel(dest, flags);
- dest.writeString(mSignature);
- }
-
- /** Helper for unparceling via #ParcelableWrapper. */
- private TextClassification(Parcel in) {
- mText = in.readString();
- mPrimaryIcon = in.readInt() == 0
- ? null : new BitmapDrawable(null, Bitmap.CREATOR.createFromParcel(in));
- mPrimaryLabel = in.readString();
- mPrimaryIntent = in.readInt() == 0 ? null : Intent.CREATOR.createFromParcel(in);
- mPrimaryOnClickListener = null; // not parcelable
- mSecondaryIcons = bitmapsToDrawables(in.createTypedArrayList(Bitmap.CREATOR));
- mSecondaryLabels = in.createStringArrayList();
- mSecondaryIntents = in.createTypedArrayList(Intent.CREATOR);
- mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
- mSignature = in.readString();
- }
-
/**
* Creates an OnClickListener that starts an activity with the specified intent.
*
@@ -675,46 +639,56 @@
}
}
- /**
- * Parcelable wrapper for TextClassification objects.
- * @hide
- */
- public static final class ParcelableWrapper implements Parcelable {
+ @Override
+ public int describeContents() {
+ return 0;
+ }
- @NonNull private TextClassification mTextClassification;
-
- public ParcelableWrapper(@NonNull TextClassification textClassification) {
- Preconditions.checkNotNull(textClassification);
- mTextClassification = textClassification;
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mText);
+ final Bitmap primaryIconBitmap = drawableToBitmap(mPrimaryIcon, MAX_PRIMARY_ICON_SIZE);
+ dest.writeInt(primaryIconBitmap != null ? 1 : 0);
+ if (primaryIconBitmap != null) {
+ primaryIconBitmap.writeToParcel(dest, flags);
}
-
- @NonNull
- public TextClassification getTextClassification() {
- return mTextClassification;
+ dest.writeString(mPrimaryLabel);
+ dest.writeInt(mPrimaryIntent != null ? 1 : 0);
+ if (mPrimaryIntent != null) {
+ mPrimaryIntent.writeToParcel(dest, flags);
}
+ // mPrimaryOnClickListener is not parcelable.
+ dest.writeTypedList(drawablesToBitmaps(mSecondaryIcons, MAX_SECONDARY_ICON_SIZE));
+ dest.writeStringList(mSecondaryLabels);
+ dest.writeTypedList(mSecondaryIntents);
+ mEntityConfidence.writeToParcel(dest, flags);
+ dest.writeString(mSignature);
+ }
- @Override
- public int describeContents() {
- return 0;
- }
+ public static final Parcelable.Creator<TextClassification> CREATOR =
+ new Parcelable.Creator<TextClassification>() {
+ @Override
+ public TextClassification createFromParcel(Parcel in) {
+ return new TextClassification(in);
+ }
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- mTextClassification.writeToParcel(dest, flags);
- }
+ @Override
+ public TextClassification[] newArray(int size) {
+ return new TextClassification[size];
+ }
+ };
- public static final Parcelable.Creator<ParcelableWrapper> CREATOR =
- new Parcelable.Creator<ParcelableWrapper>() {
- @Override
- public ParcelableWrapper createFromParcel(Parcel in) {
- return new ParcelableWrapper(new TextClassification(in));
- }
-
- @Override
- public ParcelableWrapper[] newArray(int size) {
- return new ParcelableWrapper[size];
- }
- };
-
+ private TextClassification(Parcel in) {
+ mText = in.readString();
+ mPrimaryIcon = in.readInt() == 0
+ ? null : new BitmapDrawable(null, Bitmap.CREATOR.createFromParcel(in));
+ mPrimaryLabel = in.readString();
+ mPrimaryIntent = in.readInt() == 0 ? null : Intent.CREATOR.createFromParcel(in);
+ mPrimaryOnClickListener = null; // not parcelable
+ mSecondaryIcons = bitmapsToDrawables(in.createTypedArrayList(Bitmap.CREATOR));
+ mSecondaryLabels = in.createStringArrayList();
+ mSecondaryIntents = in.createTypedArrayList(Intent.CREATOR);
+ mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
+ mSignature = in.readString();
}
}
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index d7b0776..300aef2 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -19,6 +19,8 @@
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.content.Context;
+import android.os.ServiceManager;
+import android.service.textclassifier.TextClassifierService;
import com.android.internal.util.Preconditions;
@@ -28,10 +30,16 @@
@SystemService(Context.TEXT_CLASSIFICATION_SERVICE)
public final class TextClassificationManager {
- private final Object mTextClassifierLock = new Object();
+ // TODO: Make this a configurable flag.
+ private static final boolean SYSTEM_TEXT_CLASSIFIER_ENABLED = true;
+
+ private static final String LOG_TAG = "TextClassificationManager";
+
+ private final Object mLock = new Object();
private final Context mContext;
private TextClassifier mTextClassifier;
+ private TextClassifier mSystemTextClassifier;
/** @hide */
public TextClassificationManager(Context context) {
@@ -39,12 +47,39 @@
}
/**
+ * Returns the system's default TextClassifier.
+ * @hide
+ */
+ // TODO: Unhide when this is ready.
+ public TextClassifier getSystemDefaultTextClassifier() {
+ synchronized (mLock) {
+ if (mSystemTextClassifier == null && isSystemTextClassifierEnabled()) {
+ try {
+ Log.d(LOG_TAG, "Initialized SystemTextClassifier");
+ mSystemTextClassifier = new SystemTextClassifier(mContext);
+ } catch (ServiceManager.ServiceNotFoundException e) {
+ Log.e(LOG_TAG, "Could not initialize SystemTextClassifier", e);
+ }
+ }
+ if (mSystemTextClassifier == null) {
+ Log.d(LOG_TAG, "Using an in-process TextClassifier as the system default");
+ mSystemTextClassifier = new TextClassifierImpl(mContext);
+ }
+ }
+ return mSystemTextClassifier;
+ }
+
+ /**
* Returns the text classifier.
*/
public TextClassifier getTextClassifier() {
- synchronized (mTextClassifierLock) {
+ synchronized (mLock) {
if (mTextClassifier == null) {
- mTextClassifier = new TextClassifierImpl(mContext);
+ if (isSystemTextClassifierEnabled()) {
+ mTextClassifier = getSystemDefaultTextClassifier();
+ } else {
+ mTextClassifier = new TextClassifierImpl(mContext);
+ }
}
return mTextClassifier;
}
@@ -56,8 +91,13 @@
* Set to {@link TextClassifier#NO_OP} to disable text classifier features.
*/
public void setTextClassifier(@Nullable TextClassifier textClassifier) {
- synchronized (mTextClassifierLock) {
+ synchronized (mLock) {
mTextClassifier = textClassifier;
}
}
+
+ private boolean isSystemTextClassifierEnabled() {
+ return SYSTEM_TEXT_CLASSIFIER_ENABLED
+ && TextClassifierService.getServiceComponentName(mContext) != null;
+ }
}
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 04ab447..9f75c4a 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -23,9 +23,12 @@
import android.annotation.StringDef;
import android.annotation.WorkerThread;
import android.os.LocaleList;
+import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
+import android.util.Slog;
+import android.view.textclassifier.logging.Logger;
import com.android.internal.util.Preconditions;
@@ -39,8 +42,8 @@
/**
* Interface for providing text classification related features.
*
- * <p>Unless otherwise stated, methods of this interface are blocking operations.
- * Avoid calling them on the UI thread.
+ * <p><strong>NOTE: </strong>Unless otherwise stated, methods of this interface are blocking
+ * operations. Call on a worker thread.
*/
public interface TextClassifier {
@@ -107,6 +110,8 @@
* Returns suggested text selection start and end indices, recognized entity types, and their
* associated confidence scores. The entity types are ordered from highest to lowest scoring.
*
+ * <p><strong>NOTE: </strong>Call on a worker thread.
+ *
* @param text text providing context for the selected text (which is specified
* by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex)
* @param selectionStartIndex start index of the selected part of text
@@ -125,7 +130,7 @@
@IntRange(from = 0) int selectionStartIndex,
@IntRange(from = 0) int selectionEndIndex,
@Nullable TextSelection.Options options) {
- Utils.validateInput(text, selectionStartIndex, selectionEndIndex);
+ Utils.validate(text, selectionStartIndex, selectionEndIndex, false);
return new TextSelection.Builder(selectionStartIndex, selectionEndIndex).build();
}
@@ -137,6 +142,8 @@
* {@link #suggestSelection(CharSequence, int, int, TextSelection.Options)}. If that method
* calls this method, a stack overflow error will happen.
*
+ * <p><strong>NOTE: </strong>Call on a worker thread.
+ *
* @param text text providing context for the selected text (which is specified
* by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex)
* @param selectionStartIndex start index of the selected part of text
@@ -161,6 +168,8 @@
* See {@link #suggestSelection(CharSequence, int, int)} or
* {@link #suggestSelection(CharSequence, int, int, TextSelection.Options)}.
*
+ * <p><strong>NOTE: </strong>Call on a worker thread.
+ *
* <p><b>NOTE:</b> Do not implement. The default implementation of this method calls
* {@link #suggestSelection(CharSequence, int, int, TextSelection.Options)}. If that method
* calls this method, a stack overflow error will happen.
@@ -182,6 +191,8 @@
* Classifies the specified text and returns a {@link TextClassification} object that can be
* used to generate a widget for handling the classified text.
*
+ * <p><strong>NOTE: </strong>Call on a worker thread.
+ *
* @param text text providing context for the text to classify (which is specified
* by the sub sequence starting at startIndex and ending at endIndex)
* @param startIndex start index of the text to classify
@@ -200,7 +211,7 @@
@IntRange(from = 0) int startIndex,
@IntRange(from = 0) int endIndex,
@Nullable TextClassification.Options options) {
- Utils.validateInput(text, startIndex, endIndex);
+ Utils.validate(text, startIndex, endIndex, false);
return TextClassification.EMPTY;
}
@@ -208,6 +219,8 @@
* Classifies the specified text and returns a {@link TextClassification} object that can be
* used to generate a widget for handling the classified text.
*
+ * <p><strong>NOTE: </strong>Call on a worker thread.
+ *
* <p><b>NOTE:</b> Do not implement. The default implementation of this method calls
* {@link #classifyText(CharSequence, int, int, TextClassification.Options)}. If that method
* calls this method, a stack overflow error will happen.
@@ -235,6 +248,8 @@
* See {@link #classifyText(CharSequence, int, int, TextClassification.Options)} or
* {@link #classifyText(CharSequence, int, int)}.
*
+ * <p><strong>NOTE: </strong>Call on a worker thread.
+ *
* <p><b>NOTE:</b> Do not implement. The default implementation of this method calls
* {@link #classifyText(CharSequence, int, int, TextClassification.Options)}. If that method
* calls this method, a stack overflow error will happen.
@@ -253,10 +268,10 @@
}
/**
- * Returns a {@link TextLinks} that may be applied to the text to annotate it with links
- * information.
+ * Generates and returns a {@link TextLinks} that may be applied to the text to annotate it with
+ * links information.
*
- * If no options are supplied, default values will be used, determined by the TextClassifier.
+ * <p><strong>NOTE: </strong>Call on a worker thread.
*
* @param text the text to generate annotations for
* @param options configuration for link generation
@@ -268,13 +283,15 @@
@WorkerThread
default TextLinks generateLinks(
@NonNull CharSequence text, @Nullable TextLinks.Options options) {
- Utils.validateInput(text);
+ Utils.validate(text, false);
return new TextLinks.Builder(text.toString()).build();
}
/**
- * Returns a {@link TextLinks} that may be applied to the text to annotate it with links
- * information.
+ * Generates and returns a {@link TextLinks} that may be applied to the text to annotate it with
+ * links information.
+ *
+ * <p><strong>NOTE: </strong>Call on a worker thread.
*
* <p><b>NOTE:</b> Do not implement. The default implementation of this method calls
* {@link #generateLinks(CharSequence, TextLinks.Options)}. If that method calls this method,
@@ -296,20 +313,22 @@
*
* @see #ENTITY_PRESET_ALL
* @see #ENTITY_PRESET_NONE
+ * @see #ENTITY_PRESET_BASE
*/
default Collection<String> getEntitiesForPreset(@EntityPreset int entityPreset) {
return Collections.EMPTY_LIST;
}
/**
- * Logs a TextClassifier event.
+ * Returns a helper for logging TextClassifier related events.
*
- * @param source the text classifier used to generate this event
- * @param event the text classifier related event
- * @hide
+ * @param config logger configuration
*/
@WorkerThread
- default void logEvent(String source, String event) {}
+ default Logger getLogger(@NonNull Logger.Config config) {
+ Preconditions.checkNotNull(config);
+ return Logger.DISABLED;
+ }
/**
* Returns this TextClassifier's settings.
@@ -424,19 +443,28 @@
* endIndex is greater than text.length() or is not greater than startIndex;
* options is null
*/
- static void validateInput(
- @NonNull CharSequence text, int startIndex, int endIndex) {
+ public static void validate(
+ @NonNull CharSequence text, int startIndex, int endIndex,
+ boolean allowInMainThread) {
Preconditions.checkArgument(text != null);
Preconditions.checkArgument(startIndex >= 0);
Preconditions.checkArgument(endIndex <= text.length());
Preconditions.checkArgument(endIndex > startIndex);
+ checkMainThread(allowInMainThread);
}
/**
* @throws IllegalArgumentException if text is null or options is null
*/
- static void validateInput(@NonNull CharSequence text) {
+ public static void validate(@NonNull CharSequence text, boolean allowInMainThread) {
Preconditions.checkArgument(text != null);
+ checkMainThread(allowInMainThread);
+ }
+
+ private static void checkMainThread(boolean allowInMainThread) {
+ if (!allowInMainThread && Looper.myLooper() == Looper.getMainLooper()) {
+ Slog.w(DEFAULT_LOG_TAG, "TextClassifier called on main thread");
+ }
}
}
}
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index f434452..9f389ba 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -35,6 +35,8 @@
import android.provider.Settings;
import android.text.util.Linkify;
import android.util.Patterns;
+import android.view.textclassifier.logging.DefaultLogger;
+import android.view.textclassifier.logging.Logger;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
@@ -43,6 +45,7 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -66,13 +69,13 @@
*
* @hide
*/
-final class TextClassifierImpl implements TextClassifier {
+public final class TextClassifierImpl implements TextClassifier {
private static final String LOG_TAG = DEFAULT_LOG_TAG;
private static final String MODEL_DIR = "/etc/textclassifier/";
- private static final String MODEL_FILE_REGEX = "textclassifier\\.smartselection\\.(.*)\\.model";
+ private static final String MODEL_FILE_REGEX = "textclassifier\\.(.*)\\.model";
private static final String UPDATED_MODEL_FILE_PATH =
- "/data/misc/textclassifier/textclassifier.smartselection.model";
+ "/data/misc/textclassifier/textclassifier.model";
private static final List<String> ENTITY_TYPES_ALL =
Collections.unmodifiableList(Arrays.asList(
TextClassifier.TYPE_ADDRESS,
@@ -90,38 +93,48 @@
TextClassifier.TYPE_URL));
private final Context mContext;
+ private final TextClassifier mFallback;
private final MetricsLogger mMetricsLogger = new MetricsLogger();
- private final Object mSmartSelectionLock = new Object();
- @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
+ private final Object mLock = new Object();
+ @GuardedBy("mLock") // Do not access outside this lock.
private Map<Locale, String> mModelFilePaths;
- @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
+ @GuardedBy("mLock") // Do not access outside this lock.
private Locale mLocale;
- @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
+ @GuardedBy("mLock") // Do not access outside this lock.
private int mVersion;
- @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
+ @GuardedBy("mLock") // Do not access outside this lock.
private SmartSelection mSmartSelection;
+ private final Object mLoggerLock = new Object();
+ @GuardedBy("mLoggerLock") // Do not access outside this lock.
+ private WeakReference<Logger.Config> mLoggerConfig = new WeakReference<>(null);
+ @GuardedBy("mLoggerLock") // Do not access outside this lock.
+ private Logger mLogger; // Should never be null if mLoggerConfig.get() is not null.
+
private TextClassifierConstants mSettings;
- TextClassifierImpl(Context context) {
+ public TextClassifierImpl(Context context) {
mContext = Preconditions.checkNotNull(context);
+ mFallback = TextClassifier.NO_OP;
}
+ /** @inheritDoc */
@Override
public TextSelection suggestSelection(
@NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex,
- @NonNull TextSelection.Options options) {
- Utils.validateInput(text, selectionStartIndex, selectionEndIndex);
+ @Nullable TextSelection.Options options) {
+ Utils.validate(text, selectionStartIndex, selectionEndIndex, false /* allowInMainThread */);
try {
if (text.length() > 0) {
final LocaleList locales = (options == null) ? null : options.getDefaultLocales();
+ final boolean darkLaunchAllowed = options != null && options.isDarkLaunchAllowed();
final SmartSelection smartSelection = getSmartSelection(locales);
final String string = text.toString();
final int start;
final int end;
- if (getSettings().isDarkLaunch() && !options.isDarkLaunchAllowed()) {
+ if (getSettings().isDarkLaunch() && !darkLaunchAllowed) {
start = selectionStartIndex;
end = selectionEndIndex;
} else {
@@ -130,7 +143,7 @@
start = startEnd[0];
end = startEnd[1];
}
- if (start <= end
+ if (start < end
&& start >= 0 && end <= string.length()
&& start <= selectionStartIndex && end >= selectionEndIndex) {
final TextSelection.Builder tsBuilder = new TextSelection.Builder(start, end);
@@ -158,25 +171,27 @@
t);
}
// Getting here means something went wrong, return a NO_OP result.
- return TextClassifier.NO_OP.suggestSelection(
+ return mFallback.suggestSelection(
text, selectionStartIndex, selectionEndIndex, options);
}
+ /** @inheritDoc */
@Override
public TextClassification classifyText(
@NonNull CharSequence text, int startIndex, int endIndex,
- @NonNull TextClassification.Options options) {
- Utils.validateInput(text, startIndex, endIndex);
+ @Nullable TextClassification.Options options) {
+ Utils.validate(text, startIndex, endIndex, false /* allowInMainThread */);
try {
if (text.length() > 0) {
final String string = text.toString();
final LocaleList locales = (options == null) ? null : options.getDefaultLocales();
+ final Calendar refTime = (options == null) ? null : options.getReferenceTime();
final SmartSelection.ClassificationResult[] results = getSmartSelection(locales)
.classifyText(string, startIndex, endIndex,
getHintFlags(string, startIndex, endIndex));
if (results.length > 0) {
return createClassificationResult(
- results, string, startIndex, endIndex, options.getReferenceTime());
+ results, string, startIndex, endIndex, refTime);
}
}
} catch (Throwable t) {
@@ -184,13 +199,14 @@
Log.e(LOG_TAG, "Error getting text classification info.", t);
}
// Getting here means something went wrong, return a NO_OP result.
- return TextClassifier.NO_OP.classifyText(text, startIndex, endIndex, options);
+ return mFallback.classifyText(text, startIndex, endIndex, options);
}
+ /** @inheritDoc */
@Override
public TextLinks generateLinks(
@NonNull CharSequence text, @Nullable TextLinks.Options options) {
- Utils.validateInput(text);
+ Utils.validate(text, false /* allowInMainThread */);
final String textString = text.toString();
final TextLinks.Builder builder = new TextLinks.Builder(textString);
@@ -214,14 +230,14 @@
for (int i = 0; i < results.length; i++) {
entityScores.put(results[i].mCollection, results[i].mScore);
}
- builder.addLink(new TextLinks.TextLink(
- textString, span.getStartIndex(), span.getEndIndex(), entityScores));
+ builder.addLink(span.getStartIndex(), span.getEndIndex(), entityScores);
}
+ return builder.build();
} catch (Throwable t) {
// Avoid throwing from this method. Log the error.
Log.e(LOG_TAG, "Error getting links info.", t);
}
- return builder.build();
+ return mFallback.generateLinks(text, options);
}
@Override
@@ -239,12 +255,18 @@
}
@Override
- public void logEvent(String source, String event) {
- if (LOG_TAG.equals(source)) {
- mMetricsLogger.count(event, 1);
+ public Logger getLogger(@NonNull Logger.Config config) {
+ Preconditions.checkNotNull(config);
+ synchronized (mLoggerLock) {
+ if (mLoggerConfig.get() == null || !mLoggerConfig.get().equals(config)) {
+ mLoggerConfig = new WeakReference<>(config);
+ mLogger = new DefaultLogger(config);
+ }
+ return mLogger;
}
}
+ /** @hide */
@Override
public TextClassifierConstants getSettings() {
if (mSettings == null) {
@@ -255,7 +277,7 @@
}
private SmartSelection getSmartSelection(LocaleList localeList) throws FileNotFoundException {
- synchronized (mSmartSelectionLock) {
+ synchronized (mLock) {
localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList;
final Locale locale = findBestSupportedLocaleLocked(localeList);
if (locale == null) {
@@ -275,16 +297,12 @@
}
private String getSignature(String text, int start, int end) {
- synchronized (mSmartSelectionLock) {
- final String versionInfo = (mLocale != null)
- ? String.format(Locale.US, "%s_v%d", mLocale.toLanguageTag(), mVersion)
- : "";
- final int hash = Objects.hash(text, start, end, mContext.getPackageName());
- return String.format(Locale.US, "%s|%s|%d", LOG_TAG, versionInfo, hash);
+ synchronized (mLock) {
+ return DefaultLogger.createSignature(text, start, end, mContext, mVersion, mLocale);
}
}
- @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+ @GuardedBy("mLock") // Do not call outside this lock.
private ParcelFileDescriptor getFdLocked(Locale locale) throws FileNotFoundException {
ParcelFileDescriptor updateFd;
int updateVersion = -1;
@@ -319,7 +337,7 @@
return factoryFd;
} else {
throw new FileNotFoundException(
- String.format("No model file found for %s", locale));
+ String.format(Locale.US, "No model file found for %s", locale));
}
}
@@ -333,7 +351,7 @@
} else {
closeAndLogError(updateFd);
throw new FileNotFoundException(
- String.format("No model file found for %s", locale));
+ String.format(Locale.US, "No model file found for %s", locale));
}
}
@@ -351,7 +369,7 @@
}
}
- @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+ @GuardedBy("mLock") // Do not call outside this lock.
private void destroySmartSelectionIfExistsLocked() {
if (mSmartSelection != null) {
mSmartSelection.close();
@@ -359,7 +377,7 @@
}
}
- @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+ @GuardedBy("mLock") // Do not call outside this lock.
@Nullable
private Locale findBestSupportedLocaleLocked(LocaleList localeList) {
// Specified localeList takes priority over the system default, so it is listed first.
@@ -377,7 +395,7 @@
return Locale.lookup(languageRangeList, supportedLocales);
}
- @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+ @GuardedBy("mLock") // Do not call outside this lock.
private Map<Locale, String> getFactoryModelFilePathsLocked() {
if (mModelFilePaths == null) {
final Map<Locale, String> modelFilePaths = new HashMap<>();
@@ -641,13 +659,12 @@
case Intent.ACTION_DIAL:
return context.getString(com.android.internal.R.string.dial);
case Intent.ACTION_SENDTO:
- switch (intent.getScheme()) {
- case "mailto":
- return context.getString(com.android.internal.R.string.email);
- case "smsto":
- return context.getString(com.android.internal.R.string.sms);
- default:
- return null;
+ if ("mailto".equals(intent.getScheme())) {
+ return context.getString(com.android.internal.R.string.email);
+ } else if ("smsto".equals(intent.getScheme())) {
+ return context.getString(com.android.internal.R.string.sms);
+ } else {
+ return null;
}
case Intent.ACTION_INSERT:
if (CalendarContract.AUTHORITY.equals(authority)) {
@@ -655,24 +672,22 @@
}
return null;
case Intent.ACTION_INSERT_OR_EDIT:
- switch (intent.getDataString()) {
- case ContactsContract.Contacts.CONTENT_ITEM_TYPE:
- return context.getString(com.android.internal.R.string.add_contact);
- default:
- return null;
+ if (ContactsContract.Contacts.CONTENT_ITEM_TYPE.equals(
+ intent.getType())) {
+ return context.getString(com.android.internal.R.string.add_contact);
+ } else {
+ return null;
}
case Intent.ACTION_VIEW:
if (CalendarContract.AUTHORITY.equals(authority)) {
return context.getString(com.android.internal.R.string.view_calendar);
- }
- switch (intent.getScheme()) {
- case "geo":
- return context.getString(com.android.internal.R.string.map);
- case "http": // fall through
- case "https":
- return context.getString(com.android.internal.R.string.browse);
- default:
- return null;
+ } else if ("geo".equals(intent.getScheme())) {
+ return context.getString(com.android.internal.R.string.map);
+ } else if ("http".equals(intent.getScheme())
+ || "https".equals(intent.getScheme())) {
+ return context.getString(com.android.internal.R.string.browse);
+ } else {
+ return null;
}
case Intent.ACTION_WEB_SEARCH:
return context.getString(com.android.internal.R.string.view_flight);
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl b/core/java/android/view/textclassifier/TextLinks.aidl
similarity index 79%
copy from telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
copy to core/java/android/view/textclassifier/TextLinks.aidl
index d648a35..1bbb798 100644
--- a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
+++ b/core/java/android/view/textclassifier/TextLinks.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -14,6 +14,7 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.view.textclassifier;
-parcelable ImsStreamMediaProfile;
+parcelable TextLinks;
+parcelable TextLinks.Options;
\ No newline at end of file
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index ba854e0..ede5211 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -17,18 +17,24 @@
package android.view.textclassifier;
import android.annotation.FloatRange;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
-import android.text.SpannableString;
+import android.text.Spannable;
import android.text.style.ClickableSpan;
+import android.text.util.Linkify;
+import android.text.util.Linkify.LinkifyMask;
import android.view.View;
+import android.view.textclassifier.TextClassifier.EntityType;
import android.widget.TextView;
import com.android.internal.util.Preconditions;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -41,12 +47,51 @@
* address, url, etc) they may be.
*/
public final class TextLinks implements Parcelable {
+
+ /**
+ * Return status of an attempt to apply TextLinks to text.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({STATUS_LINKS_APPLIED, STATUS_NO_LINKS_FOUND, STATUS_NO_LINKS_APPLIED,
+ STATUS_DIFFERENT_TEXT})
+ public @interface Status {}
+
+ /** Links were successfully applied to the text. */
+ public static final int STATUS_LINKS_APPLIED = 0;
+
+ /** No links exist to apply to text. Links count is zero. */
+ public static final int STATUS_NO_LINKS_FOUND = 1;
+
+ /** No links applied to text. The links were filtered out. */
+ public static final int STATUS_NO_LINKS_APPLIED = 2;
+
+ /** The specified text does not match the text used to generate the links. */
+ public static final int STATUS_DIFFERENT_TEXT = 3;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({APPLY_STRATEGY_IGNORE, APPLY_STRATEGY_REPLACE})
+ public @interface ApplyStrategy {}
+
+ /**
+ * Do not replace {@link ClickableSpan}s that exist where the {@link TextLinkSpan} needs to
+ * be applied to. Do not apply the TextLinkSpan.
+ */
+ public static final int APPLY_STRATEGY_IGNORE = 0;
+
+ /**
+ * Replace any {@link ClickableSpan}s that exist where the {@link TextLinkSpan} needs to be
+ * applied to.
+ */
+ public static final int APPLY_STRATEGY_REPLACE = 1;
+
private final String mFullText;
private final List<TextLink> mLinks;
- private TextLinks(String fullText, Collection<TextLink> links) {
+ private TextLinks(String fullText, ArrayList<TextLink> links) {
mFullText = fullText;
- mLinks = Collections.unmodifiableList(new ArrayList<>(links));
+ mLinks = Collections.unmodifiableList(links);
}
/**
@@ -60,29 +105,57 @@
* Annotates the given text with the generated links. It will fail if the provided text doesn't
* match the original text used to crete the TextLinks.
*
- * @param text the text to apply the links to. Must match the original text.
- * @param spanFactory a factory to generate spans from TextLinks. Will use a default if null.
+ * @param text the text to apply the links to. Must match the original text
+ * @param applyStrategy strategy for resolving link conflicts
+ * @param spanFactory a factory to generate spans from TextLinks. Will use a default if null
*
- * @return Success or failure.
+ * @return a status code indicating whether or not the links were successfully applied
+ *
+ * @hide
*/
- public boolean apply(
- @NonNull SpannableString text,
- @Nullable Function<TextLink, ClickableSpan> spanFactory) {
+ @Status
+ public int apply(
+ @NonNull Spannable text,
+ @ApplyStrategy int applyStrategy,
+ @Nullable Function<TextLink, TextLinkSpan> spanFactory) {
Preconditions.checkNotNull(text);
+ checkValidApplyStrategy(applyStrategy);
if (!mFullText.equals(text.toString())) {
- return false;
+ return STATUS_DIFFERENT_TEXT;
+ }
+ if (mLinks.isEmpty()) {
+ return STATUS_NO_LINKS_FOUND;
}
if (spanFactory == null) {
spanFactory = DEFAULT_SPAN_FACTORY;
}
+ int applyCount = 0;
for (TextLink link : mLinks) {
- final ClickableSpan span = spanFactory.apply(link);
+ final TextLinkSpan span = spanFactory.apply(link);
if (span != null) {
- text.setSpan(span, link.getStart(), link.getEnd(), 0);
+ final ClickableSpan[] existingSpans = text.getSpans(
+ link.getStart(), link.getEnd(), ClickableSpan.class);
+ if (existingSpans.length > 0) {
+ if (applyStrategy == APPLY_STRATEGY_REPLACE) {
+ for (ClickableSpan existingSpan : existingSpans) {
+ text.removeSpan(existingSpan);
+ }
+ text.setSpan(span, link.getStart(), link.getEnd(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ applyCount++;
+ }
+ } else {
+ text.setSpan(span, link.getStart(), link.getEnd(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ applyCount++;
+ }
}
}
- return true;
+ if (applyCount == 0) {
+ return STATUS_NO_LINKS_APPLIED;
+ }
+ return STATUS_LINKS_APPLIED;
}
@Override
@@ -119,7 +192,6 @@
*/
public static final class TextLink implements Parcelable {
private final EntityConfidence mEntityScores;
- private final String mOriginalText;
private final int mStart;
private final int mEnd;
@@ -128,12 +200,10 @@
*
* @throws IllegalArgumentException if entityScores is null or empty.
*/
- public TextLink(String originalText, int start, int end, Map<String, Float> entityScores) {
- Preconditions.checkNotNull(originalText);
+ TextLink(int start, int end, Map<String, Float> entityScores) {
Preconditions.checkNotNull(entityScores);
Preconditions.checkArgument(!entityScores.isEmpty());
Preconditions.checkArgument(start <= end);
- mOriginalText = originalText;
mStart = start;
mEnd = end;
mEntityScores = new EntityConfidence(entityScores);
@@ -171,7 +241,7 @@
*
* @return the entity type at the provided index.
*/
- @NonNull public @TextClassifier.EntityType String getEntity(int index) {
+ @NonNull public @EntityType String getEntity(int index) {
return mEntityScores.getEntities().get(index);
}
@@ -181,7 +251,7 @@
* @param entityType the entity type.
*/
public @FloatRange(from = 0.0, to = 1.0) float getConfidenceScore(
- @TextClassifier.EntityType String entityType) {
+ @EntityType String entityType) {
return mEntityScores.getConfidenceScore(entityType);
}
@@ -193,7 +263,6 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
mEntityScores.writeToParcel(dest, flags);
- dest.writeString(mOriginalText);
dest.writeInt(mStart);
dest.writeInt(mEnd);
}
@@ -213,7 +282,6 @@
private TextLink(Parcel in) {
mEntityScores = EntityConfidence.CREATOR.createFromParcel(in);
- mOriginalText = in.readString();
mStart = in.readInt();
mEnd = in.readInt();
}
@@ -227,6 +295,32 @@
private LocaleList mDefaultLocales;
private TextClassifier.EntityConfig mEntityConfig;
+ private @ApplyStrategy int mApplyStrategy;
+ private Function<TextLink, TextLinkSpan> mSpanFactory;
+
+ /**
+ * Returns a new options object based on the specified link mask.
+ */
+ public static Options fromLinkMask(@LinkifyMask int mask) {
+ final TextClassifier.EntityConfig entityConfig =
+ new TextClassifier.EntityConfig(TextClassifier.ENTITY_PRESET_NONE);
+
+ if ((mask & Linkify.WEB_URLS) != 0) {
+ entityConfig.includeEntities(TextClassifier.TYPE_URL);
+ }
+ if ((mask & Linkify.EMAIL_ADDRESSES) != 0) {
+ entityConfig.includeEntities(TextClassifier.TYPE_EMAIL);
+ }
+ if ((mask & Linkify.PHONE_NUMBERS) != 0) {
+ entityConfig.includeEntities(TextClassifier.TYPE_PHONE);
+ }
+ if ((mask & Linkify.MAP_ADDRESSES) != 0) {
+ entityConfig.includeEntities(TextClassifier.TYPE_ADDRESS);
+ }
+
+ return new Options().setEntityConfig(entityConfig);
+ }
+
public Options() {}
/**
@@ -251,6 +345,31 @@
}
/**
+ * Sets a strategy for resolving conflicts when applying generated links to text that
+ * already have links.
+ *
+ * @throws IllegalArgumentException if applyStrategy is not valid
+ *
+ * @see #APPLY_STRATEGY_IGNORE
+ * @see #APPLY_STRATEGY_REPLACE
+ */
+ public Options setApplyStrategy(@ApplyStrategy int applyStrategy) {
+ checkValidApplyStrategy(applyStrategy);
+ mApplyStrategy = applyStrategy;
+ return this;
+ }
+
+ /**
+ * Sets a factory for converting a TextLink to a TextLinkSpan.
+ *
+ * <p><strong>Note: </strong>This is not parceled over IPC.
+ */
+ public Options setSpanFactory(@Nullable Function<TextLink, TextLinkSpan> spanFactory) {
+ mSpanFactory = spanFactory;
+ return this;
+ }
+
+ /**
* @return ordered list of locale preferences that can be used to disambiguate
* the provided text.
*/
@@ -260,7 +379,7 @@
}
/**
- * @return The config representing the set of entities to look for.
+ * @return The config representing the set of entities to look for
* @see #setEntityConfig(TextClassifier.EntityConfig)
*/
@Nullable
@@ -268,6 +387,29 @@
return mEntityConfig;
}
+ /**
+ * @return the strategy for resolving conflictswhen applying generated links to text that
+ * already have links.
+ *
+ * @see #APPLY_STRATEGY_IGNORE
+ * @see #APPLY_STRATEGY_REPLACE
+ */
+ @ApplyStrategy
+ public int getApplyStrategy() {
+ return mApplyStrategy;
+ }
+
+ /**
+ * Returns a factory for converting a TextLink to a TextLinkSpan.
+ *
+ * <p><strong>Note: </strong>This is not parcelable and will always return null if read
+ * from a parcel
+ */
+ @Nullable
+ public Function<TextLink, TextLinkSpan> getSpanFactory() {
+ return mSpanFactory;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -283,6 +425,7 @@
if (mEntityConfig != null) {
mEntityConfig.writeToParcel(dest, flags);
}
+ dest.writeInt(mApplyStrategy);
}
public static final Parcelable.Creator<Options> CREATOR =
@@ -305,39 +448,53 @@
if (in.readInt() > 0) {
mEntityConfig = TextClassifier.EntityConfig.CREATOR.createFromParcel(in);
}
+ mApplyStrategy = in.readInt();
}
}
/**
* A function to create spans from TextLinks.
- *
- * Applies only to TextViews.
- * We can hide this until we are convinced we want it to be part of the public API.
- *
- * @hide
*/
- public static final Function<TextLink, ClickableSpan> DEFAULT_SPAN_FACTORY =
- textLink -> new ClickableSpan() {
- @Override
- public void onClick(View widget) {
- if (widget instanceof TextView) {
- final TextView textView = (TextView) widget;
- textView.requestActionMode(textLink);
- }
- }
- };
+ private static final Function<TextLink, TextLinkSpan> DEFAULT_SPAN_FACTORY =
+ textLink -> new TextLinkSpan(textLink);
+
+ /**
+ * A ClickableSpan for a TextLink.
+ *
+ * <p>Applies only to TextViews.
+ */
+ public static class TextLinkSpan extends ClickableSpan {
+
+ private final TextLink mTextLink;
+
+ public TextLinkSpan(@Nullable TextLink textLink) {
+ mTextLink = textLink;
+ }
+
+ @Override
+ public void onClick(View widget) {
+ if (widget instanceof TextView) {
+ final TextView textView = (TextView) widget;
+ textView.requestActionMode(mTextLink);
+ }
+ }
+
+ public final TextLink getTextLink() {
+ return mTextLink;
+ }
+ }
/**
* A builder to construct a TextLinks instance.
*/
public static final class Builder {
private final String mFullText;
- private final Collection<TextLink> mLinks;
+ private final ArrayList<TextLink> mLinks;
/**
* Create a new TextLinks.Builder.
*
- * @param fullText The full text that links will be added to.
+ * @param fullText The full text to annotate with links.
*/
public Builder(@NonNull String fullText) {
mFullText = Preconditions.checkNotNull(fullText);
@@ -348,10 +505,19 @@
* Adds a TextLink.
*
* @return this instance.
+ *
+ * @throws IllegalArgumentException if entityScores is null or empty.
*/
- public Builder addLink(TextLink link) {
- Preconditions.checkNotNull(link);
- mLinks.add(link);
+ public Builder addLink(int start, int end, Map<String, Float> entityScores) {
+ mLinks.add(new TextLink(start, end, entityScores));
+ return this;
+ }
+
+ /**
+ * Removes all {@link TextLink}s.
+ */
+ public Builder clearTextLinks() {
+ mLinks.clear();
return this;
}
@@ -364,4 +530,14 @@
return new TextLinks(mFullText, mLinks);
}
}
+
+ /**
+ * @throws IllegalArgumentException if the value is invalid
+ */
+ private static void checkValidApplyStrategy(int applyStrategy) {
+ if (applyStrategy != APPLY_STRATEGY_IGNORE && applyStrategy != APPLY_STRATEGY_REPLACE) {
+ throw new IllegalArgumentException(
+ "Invalid apply strategy. See TextLinks.ApplyStrategy for options.");
+ }
+ }
}
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl b/core/java/android/view/textclassifier/TextSelection.aidl
similarity index 78%
copy from telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
copy to core/java/android/view/textclassifier/TextSelection.aidl
index d648a35..dab1aef 100644
--- a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
+++ b/core/java/android/view/textclassifier/TextSelection.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -14,6 +14,7 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.view.textclassifier;
-parcelable ImsStreamMediaProfile;
+parcelable TextSelection;
+parcelable TextSelection.Options;
\ No newline at end of file
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 774d42d..1c93be7 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -34,7 +34,7 @@
/**
* Information about where text selection should be.
*/
-public final class TextSelection {
+public final class TextSelection implements Parcelable {
private final int mStartIndex;
private final int mEndIndex;
@@ -112,22 +112,6 @@
mStartIndex, mEndIndex, mEntityConfidence, mSignature);
}
- /** Helper for parceling via #ParcelableWrapper. */
- private void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mStartIndex);
- dest.writeInt(mEndIndex);
- mEntityConfidence.writeToParcel(dest, flags);
- dest.writeString(mSignature);
- }
-
- /** Helper for unparceling via #ParcelableWrapper. */
- private TextSelection(Parcel in) {
- mStartIndex = in.readInt();
- mEndIndex = in.readInt();
- mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
- mSignature = in.readString();
- }
-
/**
* Builder used to build {@link TextSelection} objects.
*/
@@ -272,46 +256,36 @@
}
}
- /**
- * Parcelable wrapper for TextSelection objects.
- * @hide
- */
- public static final class ParcelableWrapper implements Parcelable {
+ @Override
+ public int describeContents() {
+ return 0;
+ }
- @NonNull private TextSelection mTextSelection;
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mStartIndex);
+ dest.writeInt(mEndIndex);
+ mEntityConfidence.writeToParcel(dest, flags);
+ dest.writeString(mSignature);
+ }
- public ParcelableWrapper(@NonNull TextSelection textSelection) {
- Preconditions.checkNotNull(textSelection);
- mTextSelection = textSelection;
- }
+ public static final Parcelable.Creator<TextSelection> CREATOR =
+ new Parcelable.Creator<TextSelection>() {
+ @Override
+ public TextSelection createFromParcel(Parcel in) {
+ return new TextSelection(in);
+ }
- @NonNull
- public TextSelection getTextSelection() {
- return mTextSelection;
- }
+ @Override
+ public TextSelection[] newArray(int size) {
+ return new TextSelection[size];
+ }
+ };
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- mTextSelection.writeToParcel(dest, flags);
- }
-
- public static final Parcelable.Creator<ParcelableWrapper> CREATOR =
- new Parcelable.Creator<ParcelableWrapper>() {
- @Override
- public ParcelableWrapper createFromParcel(Parcel in) {
- return new ParcelableWrapper(new TextSelection(in));
- }
-
- @Override
- public ParcelableWrapper[] newArray(int size) {
- return new ParcelableWrapper[size];
- }
- };
-
+ private TextSelection(Parcel in) {
+ mStartIndex = in.readInt();
+ mEndIndex = in.readInt();
+ mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
+ mSignature = in.readString();
}
}
diff --git a/core/java/android/view/textclassifier/logging/DefaultLogger.java b/core/java/android/view/textclassifier/logging/DefaultLogger.java
new file mode 100644
index 0000000..6b84835
--- /dev/null
+++ b/core/java/android/view/textclassifier/logging/DefaultLogger.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.textclassifier.logging;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.metrics.LogMaker;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.util.Preconditions;
+
+import java.util.Locale;
+import java.util.Objects;
+
+/**
+ * Default Logger.
+ * Used internally by TextClassifierImpl.
+ * @hide
+ */
+public final class DefaultLogger extends Logger {
+
+ private static final String LOG_TAG = "DefaultLogger";
+ private static final String CLASSIFIER_ID = "androidtc";
+
+ private static final int START_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_START;
+ private static final int PREV_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_PREVIOUS;
+ private static final int INDEX = MetricsEvent.FIELD_SELECTION_SESSION_INDEX;
+ private static final int WIDGET_TYPE = MetricsEvent.FIELD_SELECTION_WIDGET_TYPE;
+ private static final int WIDGET_VERSION = MetricsEvent.FIELD_SELECTION_WIDGET_VERSION;
+ private static final int MODEL_NAME = MetricsEvent.FIELD_TEXTCLASSIFIER_MODEL;
+ private static final int ENTITY_TYPE = MetricsEvent.FIELD_SELECTION_ENTITY_TYPE;
+ private static final int SMART_START = MetricsEvent.FIELD_SELECTION_SMART_RANGE_START;
+ private static final int SMART_END = MetricsEvent.FIELD_SELECTION_SMART_RANGE_END;
+ private static final int EVENT_START = MetricsEvent.FIELD_SELECTION_RANGE_START;
+ private static final int EVENT_END = MetricsEvent.FIELD_SELECTION_RANGE_END;
+ private static final int SESSION_ID = MetricsEvent.FIELD_SELECTION_SESSION_ID;
+
+ private static final String ZERO = "0";
+ private static final String UNKNOWN = "unknown";
+
+ private final MetricsLogger mMetricsLogger;
+
+ public DefaultLogger(@NonNull Config config) {
+ super(config);
+ mMetricsLogger = new MetricsLogger();
+ }
+
+ @VisibleForTesting
+ public DefaultLogger(@NonNull Config config, @NonNull MetricsLogger metricsLogger) {
+ super(config);
+ mMetricsLogger = Preconditions.checkNotNull(metricsLogger);
+ }
+
+ @Override
+ public boolean isSmartSelection(@NonNull String signature) {
+ return CLASSIFIER_ID.equals(SignatureParser.getClassifierId(signature));
+ }
+
+ @Override
+ public void writeEvent(@NonNull SelectionEvent event) {
+ Preconditions.checkNotNull(event);
+ final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION)
+ .setType(getLogType(event))
+ .setSubtype(MetricsEvent.TEXT_SELECTION_INVOCATION_MANUAL)
+ .setPackageName(event.getPackageName())
+ .addTaggedData(START_EVENT_DELTA, event.getDurationSinceSessionStart())
+ .addTaggedData(PREV_EVENT_DELTA, event.getDurationSincePreviousEvent())
+ .addTaggedData(INDEX, event.getEventIndex())
+ .addTaggedData(WIDGET_TYPE, event.getWidgetType())
+ .addTaggedData(WIDGET_VERSION, event.getWidgetVersion())
+ .addTaggedData(MODEL_NAME, SignatureParser.getModelName(event.getSignature()))
+ .addTaggedData(ENTITY_TYPE, event.getEntityType())
+ .addTaggedData(SMART_START, event.getSmartStart())
+ .addTaggedData(SMART_END, event.getSmartEnd())
+ .addTaggedData(EVENT_START, event.getStart())
+ .addTaggedData(EVENT_END, event.getEnd())
+ .addTaggedData(SESSION_ID, event.getSessionId());
+ mMetricsLogger.write(log);
+ debugLog(log);
+ }
+
+ private static int getLogType(SelectionEvent event) {
+ switch (event.getEventType()) {
+ case SelectionEvent.ACTION_OVERTYPE:
+ return MetricsEvent.ACTION_TEXT_SELECTION_OVERTYPE;
+ case SelectionEvent.ACTION_COPY:
+ return MetricsEvent.ACTION_TEXT_SELECTION_COPY;
+ case SelectionEvent.ACTION_PASTE:
+ return MetricsEvent.ACTION_TEXT_SELECTION_PASTE;
+ case SelectionEvent.ACTION_CUT:
+ return MetricsEvent.ACTION_TEXT_SELECTION_CUT;
+ case SelectionEvent.ACTION_SHARE:
+ return MetricsEvent.ACTION_TEXT_SELECTION_SHARE;
+ case SelectionEvent.ACTION_SMART_SHARE:
+ return MetricsEvent.ACTION_TEXT_SELECTION_SMART_SHARE;
+ case SelectionEvent.ACTION_DRAG:
+ return MetricsEvent.ACTION_TEXT_SELECTION_DRAG;
+ case SelectionEvent.ACTION_ABANDON:
+ return MetricsEvent.ACTION_TEXT_SELECTION_ABANDON;
+ case SelectionEvent.ACTION_OTHER:
+ return MetricsEvent.ACTION_TEXT_SELECTION_OTHER;
+ case SelectionEvent.ACTION_SELECT_ALL:
+ return MetricsEvent.ACTION_TEXT_SELECTION_SELECT_ALL;
+ case SelectionEvent.ACTION_RESET:
+ return MetricsEvent.ACTION_TEXT_SELECTION_RESET;
+ case SelectionEvent.EVENT_SELECTION_STARTED:
+ return MetricsEvent.ACTION_TEXT_SELECTION_START;
+ case SelectionEvent.EVENT_SELECTION_MODIFIED:
+ return MetricsEvent.ACTION_TEXT_SELECTION_MODIFY;
+ case SelectionEvent.EVENT_SMART_SELECTION_SINGLE:
+ return MetricsEvent.ACTION_TEXT_SELECTION_SMART_SINGLE;
+ case SelectionEvent.EVENT_SMART_SELECTION_MULTI:
+ return MetricsEvent.ACTION_TEXT_SELECTION_SMART_MULTI;
+ case SelectionEvent.EVENT_AUTO_SELECTION:
+ return MetricsEvent.ACTION_TEXT_SELECTION_AUTO;
+ default:
+ return MetricsEvent.VIEW_UNKNOWN;
+ }
+ }
+
+ private static String getLogTypeString(int logType) {
+ switch (logType) {
+ case MetricsEvent.ACTION_TEXT_SELECTION_OVERTYPE:
+ return "OVERTYPE";
+ case MetricsEvent.ACTION_TEXT_SELECTION_COPY:
+ return "COPY";
+ case MetricsEvent.ACTION_TEXT_SELECTION_PASTE:
+ return "PASTE";
+ case MetricsEvent.ACTION_TEXT_SELECTION_CUT:
+ return "CUT";
+ case MetricsEvent.ACTION_TEXT_SELECTION_SHARE:
+ return "SHARE";
+ case MetricsEvent.ACTION_TEXT_SELECTION_SMART_SHARE:
+ return "SMART_SHARE";
+ case MetricsEvent.ACTION_TEXT_SELECTION_DRAG:
+ return "DRAG";
+ case MetricsEvent.ACTION_TEXT_SELECTION_ABANDON:
+ return "ABANDON";
+ case MetricsEvent.ACTION_TEXT_SELECTION_OTHER:
+ return "OTHER";
+ case MetricsEvent.ACTION_TEXT_SELECTION_SELECT_ALL:
+ return "SELECT_ALL";
+ case MetricsEvent.ACTION_TEXT_SELECTION_RESET:
+ return "RESET";
+ case MetricsEvent.ACTION_TEXT_SELECTION_START:
+ return "SELECTION_STARTED";
+ case MetricsEvent.ACTION_TEXT_SELECTION_MODIFY:
+ return "SELECTION_MODIFIED";
+ case MetricsEvent.ACTION_TEXT_SELECTION_SMART_SINGLE:
+ return "SMART_SELECTION_SINGLE";
+ case MetricsEvent.ACTION_TEXT_SELECTION_SMART_MULTI:
+ return "SMART_SELECTION_MULTI";
+ case MetricsEvent.ACTION_TEXT_SELECTION_AUTO:
+ return "AUTO_SELECTION";
+ default:
+ return UNKNOWN;
+ }
+ }
+
+ private static void debugLog(LogMaker log) {
+ if (!DEBUG_LOG_ENABLED) return;
+
+ final String widgetType = Objects.toString(log.getTaggedData(WIDGET_TYPE), UNKNOWN);
+ final String widgetVersion = Objects.toString(log.getTaggedData(WIDGET_VERSION), "");
+ final String widget = widgetVersion.isEmpty()
+ ? widgetType : widgetType + "-" + widgetVersion;
+ final int index = Integer.parseInt(Objects.toString(log.getTaggedData(INDEX), ZERO));
+ if (log.getType() == MetricsEvent.ACTION_TEXT_SELECTION_START) {
+ String sessionId = Objects.toString(log.getTaggedData(SESSION_ID), "");
+ sessionId = sessionId.substring(sessionId.lastIndexOf("-") + 1);
+ Log.d(LOG_TAG, String.format("New selection session: %s (%s)", widget, sessionId));
+ }
+
+ final String model = Objects.toString(log.getTaggedData(MODEL_NAME), UNKNOWN);
+ final String entity = Objects.toString(log.getTaggedData(ENTITY_TYPE), UNKNOWN);
+ final String type = getLogTypeString(log.getType());
+ final int smartStart = Integer.parseInt(
+ Objects.toString(log.getTaggedData(SMART_START), ZERO));
+ final int smartEnd = Integer.parseInt(
+ Objects.toString(log.getTaggedData(SMART_END), ZERO));
+ final int eventStart = Integer.parseInt(
+ Objects.toString(log.getTaggedData(EVENT_START), ZERO));
+ final int eventEnd = Integer.parseInt(
+ Objects.toString(log.getTaggedData(EVENT_END), ZERO));
+
+ Log.d(LOG_TAG, String.format("%2d: %s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)",
+ index, type, entity, eventStart, eventEnd, smartStart, smartEnd, widget, model));
+ }
+
+ /**
+ * Creates a signature string that may be used to tag TextClassifier results.
+ */
+ public static String createSignature(
+ String text, int start, int end, Context context, int modelVersion,
+ @Nullable Locale locale) {
+ Preconditions.checkNotNull(text);
+ Preconditions.checkNotNull(context);
+ final String modelName = (locale != null)
+ ? String.format(Locale.US, "%s_v%d", locale.toLanguageTag(), modelVersion)
+ : "";
+ final int hash = Objects.hash(text, start, end, context.getPackageName());
+ return SignatureParser.createSignature(CLASSIFIER_ID, modelName, hash);
+ }
+
+ /**
+ * Helper for creating and parsing signature strings for
+ * {@link android.view.textclassifier.TextClassifierImpl}.
+ */
+ @VisibleForTesting
+ public static final class SignatureParser {
+
+ static String createSignature(String classifierId, String modelName, int hash) {
+ return String.format(Locale.US, "%s|%s|%d", classifierId, modelName, hash);
+ }
+
+ static String getClassifierId(String signature) {
+ Preconditions.checkNotNull(signature);
+ final int end = signature.indexOf("|");
+ if (end >= 0) {
+ return signature.substring(0, end);
+ }
+ return "";
+ }
+
+ static String getModelName(String signature) {
+ Preconditions.checkNotNull(signature);
+ final int start = signature.indexOf("|");
+ final int end = signature.indexOf("|", start);
+ if (start >= 0 && end >= start) {
+ return signature.substring(start, end);
+ }
+ return "";
+ }
+
+ static int getHash(String signature) {
+ Preconditions.checkNotNull(signature);
+ final int index1 = signature.indexOf("|");
+ final int index2 = signature.indexOf("|", index1);
+ if (index2 > 0) {
+ return Integer.parseInt(signature.substring(index2));
+ }
+ return 0;
+ }
+ }
+}
diff --git a/core/java/android/view/textclassifier/logging/Logger.java b/core/java/android/view/textclassifier/logging/Logger.java
new file mode 100644
index 0000000..40e4d8c
--- /dev/null
+++ b/core/java/android/view/textclassifier/logging/Logger.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.textclassifier.logging;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.content.Context;
+import android.util.Log;
+import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextSelection;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.text.BreakIterator;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * A helper for logging TextClassifier related events.
+ */
+public abstract class Logger {
+
+ /**
+ * Use this to specify an indeterminate positive index.
+ */
+ public static final int OUT_OF_BOUNDS = Integer.MAX_VALUE;
+
+ /**
+ * Use this to specify an indeterminate negative index.
+ */
+ public static final int OUT_OF_BOUNDS_NEGATIVE = Integer.MIN_VALUE;
+
+ private static final String LOG_TAG = "Logger";
+ /* package */ static final boolean DEBUG_LOG_ENABLED = true;
+
+ private static final String NO_SIGNATURE = "";
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @StringDef({WIDGET_TEXTVIEW, WIDGET_WEBVIEW, WIDGET_EDITTEXT,
+ WIDGET_EDIT_WEBVIEW, WIDGET_CUSTOM_TEXTVIEW, WIDGET_CUSTOM_EDITTEXT,
+ WIDGET_CUSTOM_UNSELECTABLE_TEXTVIEW, WIDGET_UNKNOWN})
+ public @interface WidgetType {}
+
+ public static final String WIDGET_TEXTVIEW = "textview";
+ public static final String WIDGET_EDITTEXT = "edittext";
+ public static final String WIDGET_UNSELECTABLE_TEXTVIEW = "nosel-textview";
+ public static final String WIDGET_WEBVIEW = "webview";
+ public static final String WIDGET_EDIT_WEBVIEW = "edit-webview";
+ public static final String WIDGET_CUSTOM_TEXTVIEW = "customview";
+ public static final String WIDGET_CUSTOM_EDITTEXT = "customedit";
+ public static final String WIDGET_CUSTOM_UNSELECTABLE_TEXTVIEW = "nosel-customview";
+ public static final String WIDGET_UNKNOWN = "unknown";
+
+ private SelectionEvent mPrevEvent;
+ private SelectionEvent mSmartEvent;
+ private SelectionEvent mStartEvent;
+
+ /**
+ * Logger that does not log anything.
+ * @hide
+ */
+ public static final Logger DISABLED = new Logger() {
+ @Override
+ public void writeEvent(SelectionEvent event) {}
+ };
+
+ @Nullable
+ private final Config mConfig;
+
+ public Logger(Config config) {
+ mConfig = Preconditions.checkNotNull(config);
+ }
+
+ private Logger() {
+ mConfig = null;
+ }
+
+ /**
+ * Writes the selection event.
+ *
+ * <p><strong>NOTE: </strong>This method is designed for subclasses.
+ * Apps should not call it directly.
+ */
+ public abstract void writeEvent(@NonNull SelectionEvent event);
+
+ /**
+ * Returns true if the signature matches that of a smart selection event (i.e.
+ * {@link SelectionEvent#EVENT_SMART_SELECTION_SINGLE} or
+ * {@link SelectionEvent#EVENT_SMART_SELECTION_MULTI}).
+ * Returns false otherwise.
+ */
+ public boolean isSmartSelection(@NonNull String signature) {
+ return false;
+ }
+
+
+ /**
+ * Returns a token iterator for tokenizing text for logging purposes.
+ */
+ public BreakIterator getTokenIterator(@NonNull Locale locale) {
+ return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale));
+ }
+
+ /**
+ * Logs a "selection started" event.
+ *
+ * @param start the token index of the selected token
+ */
+ public final void logSelectionStartedEvent(int start) {
+ if (mConfig == null) {
+ return;
+ }
+
+ logEvent(new SelectionEvent(
+ start, start + 1, SelectionEvent.EVENT_SELECTION_STARTED,
+ TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig));
+ }
+
+ /**
+ * Logs a "selection modified" event.
+ * Use when the user modifies the selection.
+ *
+ * @param start the start token (inclusive) index of the selection
+ * @param end the end token (exclusive) index of the selection
+ */
+ public final void logSelectionModifiedEvent(int start, int end) {
+ Preconditions.checkArgument(end >= start, "end cannot be less than start");
+
+ if (mConfig == null) {
+ return;
+ }
+
+ logEvent(new SelectionEvent(
+ start, end, SelectionEvent.EVENT_SELECTION_MODIFIED,
+ TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig));
+ }
+
+ /**
+ * Logs a "selection modified" event.
+ * Use when the user modifies the selection and the selection's entity type is known.
+ *
+ * @param start the start token (inclusive) index of the selection
+ * @param end the end token (exclusive) index of the selection
+ * @param classification the TextClassification object returned by the TextClassifier that
+ * classified the selected text
+ */
+ public final void logSelectionModifiedEvent(
+ int start, int end, @NonNull TextClassification classification) {
+ Preconditions.checkArgument(end >= start, "end cannot be less than start");
+ Preconditions.checkNotNull(classification);
+
+ if (mConfig == null) {
+ return;
+ }
+
+ final String entityType = classification.getEntityCount() > 0
+ ? classification.getEntity(0)
+ : TextClassifier.TYPE_UNKNOWN;
+ final String signature = classification.getSignature();
+ logEvent(new SelectionEvent(
+ start, end, SelectionEvent.EVENT_SELECTION_MODIFIED,
+ entityType, signature, mConfig));
+ }
+
+ /**
+ * Logs a "selection modified" event.
+ * Use when a TextClassifier modifies the selection.
+ *
+ * @param start the start token (inclusive) index of the selection
+ * @param end the end token (exclusive) index of the selection
+ * @param selection the TextSelection object returned by the TextClassifier for the
+ * specified selection
+ */
+ public final void logSelectionModifiedEvent(
+ int start, int end, @NonNull TextSelection selection) {
+ Preconditions.checkArgument(end >= start, "end cannot be less than start");
+ Preconditions.checkNotNull(selection);
+
+ if (mConfig == null) {
+ return;
+ }
+
+ final int eventType;
+ if (isSmartSelection(selection.getSignature())) {
+ eventType = end - start > 1
+ ? SelectionEvent.EVENT_SMART_SELECTION_MULTI
+ : SelectionEvent.EVENT_SMART_SELECTION_SINGLE;
+
+ } else {
+ eventType = SelectionEvent.EVENT_AUTO_SELECTION;
+ }
+ final String entityType = selection.getEntityCount() > 0
+ ? selection.getEntity(0)
+ : TextClassifier.TYPE_UNKNOWN;
+ final String signature = selection.getSignature();
+ logEvent(new SelectionEvent(start, end, eventType, entityType, signature, mConfig));
+ }
+
+ /**
+ * Logs an event specifying an action taken on a selection.
+ * Use when the user clicks on an action to act on the selected text.
+ *
+ * @param start the start token (inclusive) index of the selection
+ * @param end the end token (exclusive) index of the selection
+ * @param actionType the action that was performed on the selection
+ */
+ public final void logSelectionActionEvent(
+ int start, int end, @SelectionEvent.ActionType int actionType) {
+ Preconditions.checkArgument(end >= start, "end cannot be less than start");
+ checkActionType(actionType);
+
+ if (mConfig == null) {
+ return;
+ }
+
+ logEvent(new SelectionEvent(
+ start, end, actionType, TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig));
+ }
+
+ /**
+ * Logs an event specifying an action taken on a selection.
+ * Use when the user clicks on an action to act on the selected text and the selection's
+ * entity type is known.
+ *
+ * @param start the start token (inclusive) index of the selection
+ * @param end the end token (exclusive) index of the selection
+ * @param actionType the action that was performed on the selection
+ * @param classification the TextClassification object returned by the TextClassifier that
+ * classified the selected text
+ *
+ * @throws IllegalArgumentException If actionType is not a valid SelectionEvent actionType
+ */
+ public final void logSelectionActionEvent(
+ int start, int end, @SelectionEvent.ActionType int actionType,
+ @NonNull TextClassification classification) {
+ Preconditions.checkArgument(end >= start, "end cannot be less than start");
+ Preconditions.checkNotNull(classification);
+ checkActionType(actionType);
+
+ if (mConfig == null) {
+ return;
+ }
+
+ final String entityType = classification.getEntityCount() > 0
+ ? classification.getEntity(0)
+ : TextClassifier.TYPE_UNKNOWN;
+ final String signature = classification.getSignature();
+ logEvent(new SelectionEvent(start, end, actionType, entityType, signature, mConfig));
+ }
+
+ private void logEvent(@NonNull SelectionEvent event) {
+ Preconditions.checkNotNull(event);
+
+ if (event.getEventType() != SelectionEvent.EVENT_SELECTION_STARTED
+ && mStartEvent == null) {
+ if (DEBUG_LOG_ENABLED) {
+ Log.d(LOG_TAG, "Selection session not yet started. Ignoring event");
+ }
+ return;
+ }
+
+ final long now = System.currentTimeMillis();
+ switch (event.getEventType()) {
+ case SelectionEvent.EVENT_SELECTION_STARTED:
+ Preconditions.checkArgument(event.getAbsoluteEnd() == event.getAbsoluteStart() + 1);
+ event.setSessionId(startNewSession());
+ mStartEvent = event;
+ break;
+ case SelectionEvent.EVENT_SMART_SELECTION_SINGLE: // fall through
+ case SelectionEvent.EVENT_SMART_SELECTION_MULTI:
+ mSmartEvent = event;
+ break;
+ case SelectionEvent.EVENT_SELECTION_MODIFIED: // fall through
+ case SelectionEvent.EVENT_AUTO_SELECTION:
+ if (mPrevEvent != null
+ && mPrevEvent.getAbsoluteStart() == event.getAbsoluteStart()
+ && mPrevEvent.getAbsoluteEnd() == event.getAbsoluteEnd()) {
+ // Selection did not change. Ignore event.
+ return;
+ }
+ }
+
+ event.setEventTime(now);
+ if (mStartEvent != null) {
+ event.setSessionId(mStartEvent.getSessionId())
+ .setDurationSinceSessionStart(now - mStartEvent.getEventTime())
+ .setStart(event.getAbsoluteStart() - mStartEvent.getAbsoluteStart())
+ .setEnd(event.getAbsoluteEnd() - mStartEvent.getAbsoluteStart());
+ }
+ if (mSmartEvent != null) {
+ event.setSignature(mSmartEvent.getSignature())
+ .setSmartStart(mSmartEvent.getAbsoluteStart() - mStartEvent.getAbsoluteStart())
+ .setSmartEnd(mSmartEvent.getAbsoluteEnd() - mStartEvent.getAbsoluteStart());
+ }
+ if (mPrevEvent != null) {
+ event.setDurationSincePreviousEvent(now - mPrevEvent.getEventTime())
+ .setEventIndex(mPrevEvent.getEventIndex() + 1);
+ }
+ writeEvent(event);
+ mPrevEvent = event;
+
+ if (event.isTerminal()) {
+ endSession();
+ }
+ }
+
+ private String startNewSession() {
+ endSession();
+ return UUID.randomUUID().toString();
+ }
+
+ private void endSession() {
+ mPrevEvent = null;
+ mSmartEvent = null;
+ mStartEvent = null;
+ }
+
+ /**
+ * @throws IllegalArgumentException If eventType is not an {@link SelectionEvent.ActionType}
+ */
+ private static void checkActionType(@SelectionEvent.EventType int eventType)
+ throws IllegalArgumentException {
+ switch (eventType) {
+ case SelectionEvent.ACTION_OVERTYPE: // fall through
+ case SelectionEvent.ACTION_COPY: // fall through
+ case SelectionEvent.ACTION_PASTE: // fall through
+ case SelectionEvent.ACTION_CUT: // fall through
+ case SelectionEvent.ACTION_SHARE: // fall through
+ case SelectionEvent.ACTION_SMART_SHARE: // fall through
+ case SelectionEvent.ACTION_DRAG: // fall through
+ case SelectionEvent.ACTION_ABANDON: // fall through
+ case SelectionEvent.ACTION_SELECT_ALL: // fall through
+ case SelectionEvent.ACTION_RESET: // fall through
+ return;
+ default:
+ throw new IllegalArgumentException(
+ String.format(Locale.US, "%d is not an eventType", eventType));
+ }
+ }
+
+
+ /**
+ * A Logger config.
+ */
+ public static final class Config {
+
+ private final String mPackageName;
+ private final String mWidgetType;
+ @Nullable private final String mWidgetVersion;
+
+ /**
+ * @param context Context of the widget the logger logs for
+ * @param widgetType a name for the widget being logged for. e.g.
+ * {@link #WIDGET_TEXTVIEW}
+ * @param widgetVersion a string version info for the widget the logger logs for
+ */
+ public Config(
+ @NonNull Context context,
+ @WidgetType String widgetType,
+ @Nullable String widgetVersion) {
+ mPackageName = Preconditions.checkNotNull(context).getPackageName();
+ mWidgetType = widgetType;
+ mWidgetVersion = widgetVersion;
+ }
+
+ /**
+ * Returns the package name of the application the logger logs for.
+ */
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * Returns the name for the widget being logged for. e.g. {@link #WIDGET_TEXTVIEW}.
+ */
+ public String getWidgetType() {
+ return mWidgetType;
+ }
+
+ /**
+ * Returns string version info for the logger. This is specific to the text classifier.
+ */
+ @Nullable
+ public String getWidgetVersion() {
+ return mWidgetVersion;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPackageName, mWidgetType, mWidgetVersion);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (!(obj instanceof Config)) {
+ return false;
+ }
+
+ final Config other = (Config) obj;
+ return Objects.equals(mPackageName, other.mPackageName)
+ && Objects.equals(mWidgetType, other.mWidgetType)
+ && Objects.equals(mWidgetVersion, other.mWidgetType);
+ }
+ }
+}
diff --git a/core/java/android/view/textclassifier/logging/SelectionEvent.java b/core/java/android/view/textclassifier/logging/SelectionEvent.java
new file mode 100644
index 0000000..f40b655
--- /dev/null
+++ b/core/java/android/view/textclassifier/logging/SelectionEvent.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.textclassifier.logging;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.view.textclassifier.TextClassifier.EntityType;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Locale;
+
+/**
+ * A selection event.
+ * Specify index parameters as word token indices.
+ */
+public final class SelectionEvent {
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ACTION_OVERTYPE, ACTION_COPY, ACTION_PASTE, ACTION_CUT,
+ ACTION_SHARE, ACTION_SMART_SHARE, ACTION_DRAG, ACTION_ABANDON,
+ ACTION_OTHER, ACTION_SELECT_ALL, ACTION_RESET})
+ // NOTE: ActionType values should not be lower than 100 to avoid colliding with the other
+ // EventTypes declared below.
+ public @interface ActionType {
+ /*
+ * Terminal event types range: [100,200).
+ * Non-terminal event types range: [200,300).
+ */
+ }
+
+ /** User typed over the selection. */
+ public static final int ACTION_OVERTYPE = 100;
+ /** User copied the selection. */
+ public static final int ACTION_COPY = 101;
+ /** User pasted over the selection. */
+ public static final int ACTION_PASTE = 102;
+ /** User cut the selection. */
+ public static final int ACTION_CUT = 103;
+ /** User shared the selection. */
+ public static final int ACTION_SHARE = 104;
+ /** User clicked the textAssist menu item. */
+ public static final int ACTION_SMART_SHARE = 105;
+ /** User dragged+dropped the selection. */
+ public static final int ACTION_DRAG = 106;
+ /** User abandoned the selection. */
+ public static final int ACTION_ABANDON = 107;
+ /** User performed an action on the selection. */
+ public static final int ACTION_OTHER = 108;
+
+ // Non-terminal actions.
+ /** User activated Select All */
+ public static final int ACTION_SELECT_ALL = 200;
+ /** User reset the smart selection. */
+ public static final int ACTION_RESET = 201;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ACTION_OVERTYPE, ACTION_COPY, ACTION_PASTE, ACTION_CUT,
+ ACTION_SHARE, ACTION_SMART_SHARE, ACTION_DRAG, ACTION_ABANDON,
+ ACTION_OTHER, ACTION_SELECT_ALL, ACTION_RESET,
+ EVENT_SELECTION_STARTED, EVENT_SELECTION_MODIFIED,
+ EVENT_SMART_SELECTION_SINGLE, EVENT_SMART_SELECTION_MULTI,
+ EVENT_AUTO_SELECTION})
+ // NOTE: EventTypes declared here must be less than 100 to avoid colliding with the
+ // ActionTypes declared above.
+ public @interface EventType {
+ /*
+ * Range: 1 -> 99.
+ */
+ }
+
+ /** User started a new selection. */
+ public static final int EVENT_SELECTION_STARTED = 1;
+ /** User modified an existing selection. */
+ public static final int EVENT_SELECTION_MODIFIED = 2;
+ /** Smart selection triggered for a single token (word). */
+ public static final int EVENT_SMART_SELECTION_SINGLE = 3;
+ /** Smart selection triggered spanning multiple tokens (words). */
+ public static final int EVENT_SMART_SELECTION_MULTI = 4;
+ /** Something else other than User or the default TextClassifier triggered a selection. */
+ public static final int EVENT_AUTO_SELECTION = 5;
+
+ private final int mAbsoluteStart;
+ private final int mAbsoluteEnd;
+ private final @EventType int mEventType;
+ private final @EntityType String mEntityType;
+ @Nullable private final String mWidgetVersion;
+ private final String mPackageName;
+ private final String mWidgetType;
+
+ // These fields should only be set by creator of a SelectionEvent.
+ private String mSignature;
+ private long mEventTime;
+ private long mDurationSinceSessionStart;
+ private long mDurationSinceLastEvent;
+ private int mEventIndex;
+ private String mSessionId;
+ private int mStart;
+ private int mEnd;
+ private int mSmartStart;
+ private int mSmartEnd;
+
+ SelectionEvent(
+ int start, int end,
+ @EventType int eventType, @EntityType String entityType,
+ String signature, Logger.Config config) {
+ Preconditions.checkArgument(end >= start, "end cannot be less than start");
+ mAbsoluteStart = start;
+ mAbsoluteEnd = end;
+ mEventType = eventType;
+ mEntityType = Preconditions.checkNotNull(entityType);
+ mSignature = Preconditions.checkNotNull(signature);
+ Preconditions.checkNotNull(config);
+ mWidgetVersion = config.getWidgetVersion();
+ mPackageName = Preconditions.checkNotNull(config.getPackageName());
+ mWidgetType = Preconditions.checkNotNull(config.getWidgetType());
+ }
+
+ int getAbsoluteStart() {
+ return mAbsoluteStart;
+ }
+
+ int getAbsoluteEnd() {
+ return mAbsoluteEnd;
+ }
+
+ /**
+ * Returns the type of event that was triggered. e.g. {@link #ACTION_COPY}.
+ */
+ public int getEventType() {
+ return mEventType;
+ }
+
+ /**
+ * Returns the type of entity that is associated with this event. e.g.
+ * {@link android.view.textclassifier.TextClassifier#TYPE_EMAIL}.
+ */
+ @EntityType
+ public String getEntityType() {
+ return mEntityType;
+ }
+
+ /**
+ * Returns the package name of the app that this event originated in.
+ */
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * Returns the type of widget that was involved in triggering this event.
+ */
+ public String getWidgetType() {
+ return mWidgetType;
+ }
+
+ /**
+ * Returns a string version info for the widget this event was triggered in.
+ */
+ public String getWidgetVersion() {
+ return mWidgetVersion;
+ }
+
+ /**
+ * Returns the signature of the text classifier result associated with this event.
+ */
+ public String getSignature() {
+ return mSignature;
+ }
+
+ SelectionEvent setSignature(String signature) {
+ mSignature = Preconditions.checkNotNull(signature);
+ return this;
+ }
+
+ /**
+ * Returns the time this event was triggered.
+ */
+ public long getEventTime() {
+ return mEventTime;
+ }
+
+ SelectionEvent setEventTime(long timeMs) {
+ mEventTime = timeMs;
+ return this;
+ }
+
+ /**
+ * Returns the duration in ms between when this event was triggered and when the first event in
+ * the selection session was triggered.
+ */
+ public long getDurationSinceSessionStart() {
+ return mDurationSinceSessionStart;
+ }
+
+ SelectionEvent setDurationSinceSessionStart(long durationMs) {
+ mDurationSinceSessionStart = durationMs;
+ return this;
+ }
+
+ /**
+ * Returns the duration in ms between when this event was triggered and when the previous event
+ * in the selection session was triggered.
+ */
+ public long getDurationSincePreviousEvent() {
+ return mDurationSinceLastEvent;
+ }
+
+ SelectionEvent setDurationSincePreviousEvent(long durationMs) {
+ this.mDurationSinceLastEvent = durationMs;
+ return this;
+ }
+
+ /**
+ * Returns the index (e.g. 1st event, 2nd event, etc.) of this event in the selection session.
+ */
+ public int getEventIndex() {
+ return mEventIndex;
+ }
+
+ SelectionEvent setEventIndex(int index) {
+ mEventIndex = index;
+ return this;
+ }
+
+ /**
+ * Returns the selection session id.
+ */
+ public String getSessionId() {
+ return mSessionId;
+ }
+
+ SelectionEvent setSessionId(String id) {
+ mSessionId = id;
+ return this;
+ }
+
+ /**
+ * Returns the start index of this events token relative to the index of the start selection
+ * event in the selection session.
+ */
+ public int getStart() {
+ return mStart;
+ }
+
+ SelectionEvent setStart(int start) {
+ mStart = start;
+ return this;
+ }
+
+ /**
+ * Returns the end index of this events token relative to the index of the start selection
+ * event in the selection session.
+ */
+ public int getEnd() {
+ return mEnd;
+ }
+
+ SelectionEvent setEnd(int end) {
+ mEnd = end;
+ return this;
+ }
+
+ /**
+ * Returns the start index of this events token relative to the index of the smart selection
+ * event in the selection session.
+ */
+ public int getSmartStart() {
+ return mSmartStart;
+ }
+
+ SelectionEvent setSmartStart(int start) {
+ this.mSmartStart = start;
+ return this;
+ }
+
+ /**
+ * Returns the end index of this events token relative to the index of the smart selection
+ * event in the selection session.
+ */
+ public int getSmartEnd() {
+ return mSmartEnd;
+ }
+
+ SelectionEvent setSmartEnd(int end) {
+ mSmartEnd = end;
+ return this;
+ }
+
+ boolean isTerminal() {
+ switch (mEventType) {
+ case ACTION_OVERTYPE: // fall through
+ case ACTION_COPY: // fall through
+ case ACTION_PASTE: // fall through
+ case ACTION_CUT: // fall through
+ case ACTION_SHARE: // fall through
+ case ACTION_SMART_SHARE: // fall through
+ case ACTION_DRAG: // fall through
+ case ACTION_ABANDON: // fall through
+ case ACTION_OTHER: // fall through
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format(Locale.US,
+ "SelectionEvent {absoluteStart=%d, absoluteEnd=%d, eventType=%d, entityType=%s, "
+ + "widgetVersion=%s, packageName=%s, widgetType=%s, signature=%s, "
+ + "eventTime=%d, durationSinceSessionStart=%d, durationSinceLastEvent=%d, "
+ + "eventIndex=%d, sessionId=%s, start=%d, end=%d, smartStart=%d, smartEnd=%d}",
+ mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
+ mWidgetVersion, mPackageName, mWidgetType, mSignature,
+ mEventTime, mDurationSinceSessionStart, mDurationSinceLastEvent,
+ mEventIndex, mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
+ }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index d2cb70e..65deb3b 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2106,6 +2106,18 @@
* the default directory, and other processes must call this API to define
* a unique suffix.
* <p>
+ * This means that different processes in the same application cannot directly
+ * share WebView-related data, since the data directories must be distinct.
+ * Applications that use this API may have to explicitly pass data between
+ * processes. For example, login cookies may have to be copied from one
+ * process's cookie jar to the other using {@link CookieManager} if both
+ * processes' WebViews are intended to be logged in.
+ * <p>
+ * Most applications should simply ensure that all components of the app
+ * that rely on WebView are in the same process, to avoid needing multiple
+ * data directories. The {@link #disableWebView} method can be used to ensure
+ * that the other processes do not use WebView by accident in this case.
+ * <p>
* This API must be called before any instances of WebView are created in
* this process and before any other methods in the android.webkit package
* are called by this process.
@@ -2126,10 +2138,14 @@
* methods in the android.webkit package are used.
* <p>
* Applications with multiple processes may wish to call this in processes
- * which are not intended to use WebView to prevent potential data directory
- * conflicts (see {@link #setDataDirectorySuffix}) and to avoid accidentally
- * incurring the memory usage of initializing WebView in long-lived
- * processes which have no need for it.
+ * that are not intended to use WebView to avoid accidentally incurring
+ * the memory usage of initializing WebView in long-lived processes that
+ * have no need for it, and to prevent potential data directory conflicts
+ * (see {@link #setDataDirectorySuffix}).
+ * <p>
+ * For example, an audio player application with one process for its
+ * activities and another process for its playback service may wish to call
+ * this method in the playback service's {@link android.app.Service#onCreate}.
*
* @throws IllegalStateException if WebView has already been initialized
* in the current process.
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 594d240..a13de75 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -6864,7 +6864,7 @@
// detached and we do not allow detached views to fire accessibility
// events. So we are announcing that the subtree changed giving a chance
// to clients holding on to a view in this subtree to refresh it.
- notifyAccessibilityStateChanged(
+ notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
// Don't scrap views that have transient state.
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 08374cb..6c19256 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -1093,7 +1093,7 @@
checkSelectionChanged();
}
- notifyAccessibilitySubtreeChanged();
+ notifySubtreeAccessibilityStateChangedIfNeeded();
}
/**
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index af01a3e..92bfd56 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -132,7 +132,7 @@
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
- notifyAccessibilityStateChanged(
+ notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index e57f153..0762b15 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -158,7 +158,7 @@
mCheckedFromResource = false;
mChecked = checked;
refreshDrawableState();
- notifyAccessibilityStateChanged(
+ notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
// Avoid infinite recursions if setChecked() is called from a listener
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 310b170..7a4c800 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -18,7 +18,6 @@
import android.annotation.FloatRange;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.UiThread;
import android.content.Context;
import android.graphics.Bitmap;
@@ -30,9 +29,11 @@
import android.view.LayoutInflater;
import android.view.PixelCopy;
import android.view.Surface;
+import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewParent;
+import android.view.ViewRootImpl;
import com.android.internal.util.Preconditions;
@@ -124,7 +125,8 @@
configureCoordinates(xPosInView, yPosInView);
- // Clamp startX value to avoid distorting the rendering of the magnifier content.
+ // Clamp the startX value to avoid magnifying content which does not belong to the magnified
+ // view. This will not take into account overlapping views.
// For this, we compute:
// - zeroScrollXInSurface: this is the start x of mView, where this is not masked by a
// potential scrolling container. For example, if mView is a
@@ -180,8 +182,6 @@
/**
* Forces the magnifier to update its content. It uses the previous coordinates passed to
* {@link #show(float, float)}. This only happens if the magnifier is currently showing.
- *
- * @hide
*/
public void update() {
if (mWindow.isShowing()) {
@@ -190,57 +190,79 @@
}
}
- private void configureCoordinates(float xPosInView, float yPosInView) {
- final float posX;
- final float posY;
-
+ private void configureCoordinates(final float xPosInView, final float yPosInView) {
+ // Compute the coordinates of the center of the content going to be displayed in the
+ // magnifier. These are relative to the surface the content is copied from.
+ final float contentPosX;
+ final float contentPosY;
if (mView instanceof SurfaceView) {
// No offset required if the backing Surface matches the size of the SurfaceView.
- posX = xPosInView;
- posY = yPosInView;
+ contentPosX = xPosInView;
+ contentPosY = yPosInView;
} else {
mView.getLocationInSurface(mViewCoordinatesInSurface);
- posX = xPosInView + mViewCoordinatesInSurface[0];
- posY = yPosInView + mViewCoordinatesInSurface[1];
+ contentPosX = xPosInView + mViewCoordinatesInSurface[0];
+ contentPosY = yPosInView + mViewCoordinatesInSurface[1];
}
+ mCenterZoomCoords.x = Math.round(contentPosX);
+ mCenterZoomCoords.y = Math.round(contentPosY);
- mCenterZoomCoords.x = Math.round(posX);
- mCenterZoomCoords.y = Math.round(posY);
-
- final int verticalMagnifierOffset = mView.getContext().getResources().getDimensionPixelSize(
+ // Compute the position of the magnifier window. These have to be relative to the window
+ // of the view the magnifier is attached to, as the magnifier popup is a panel window
+ // attached to that window.
+ final int[] viewCoordinatesInWindow = new int[2];
+ mView.getLocationInWindow(viewCoordinatesInWindow);
+ final int verticalOffset = mView.getContext().getResources().getDimensionPixelSize(
com.android.internal.R.dimen.magnifier_offset);
- mWindowCoords.x = mCenterZoomCoords.x - mWindowWidth / 2;
- mWindowCoords.y = mCenterZoomCoords.y - mWindowHeight / 2 - verticalMagnifierOffset;
+ final float magnifierPosX = xPosInView + viewCoordinatesInWindow[0];
+ final float magnifierPosY = yPosInView + viewCoordinatesInWindow[1] - verticalOffset;
+ mWindowCoords.x = Math.round(magnifierPosX - mWindowWidth / 2);
+ mWindowCoords.y = Math.round(magnifierPosY - mWindowHeight / 2);
}
private void performPixelCopy(final int startXInSurface, final int startYInSurface) {
- final Surface surface = getValidViewSurface();
- if (surface != null) {
- mPixelCopyRequestRect.set(startXInSurface, startYInSurface,
- startXInSurface + mBitmap.getWidth(), startYInSurface + mBitmap.getHeight());
-
- PixelCopy.request(surface, mPixelCopyRequestRect, mBitmap,
- result -> {
- getImageView().invalidate();
- mPrevStartCoordsInSurface.x = startXInSurface;
- mPrevStartCoordsInSurface.y = startYInSurface;
- },
- mPixelCopyHandler);
- }
- }
-
- @Nullable
- private Surface getValidViewSurface() {
+ // Get the view surface where the content will be copied from.
final Surface surface;
+ final int surfaceWidth;
+ final int surfaceHeight;
if (mView instanceof SurfaceView) {
- surface = ((SurfaceView) mView).getHolder().getSurface();
+ final SurfaceHolder surfaceHolder = ((SurfaceView) mView).getHolder();
+ surface = surfaceHolder.getSurface();
+ surfaceWidth = surfaceHolder.getSurfaceFrame().right;
+ surfaceHeight = surfaceHolder.getSurfaceFrame().bottom;
} else if (mView.getViewRootImpl() != null) {
- surface = mView.getViewRootImpl().mSurface;
+ final ViewRootImpl viewRootImpl = mView.getViewRootImpl();
+ surface = viewRootImpl.mSurface;
+ surfaceWidth = viewRootImpl.getWidth();
+ surfaceHeight = viewRootImpl.getHeight();
} else {
surface = null;
+ surfaceWidth = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
+ surfaceHeight = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
}
- return (surface != null && surface.isValid()) ? surface : null;
+ if (surface == null || !surface.isValid()) {
+ return;
+ }
+
+ // Clamp copy coordinates inside the surface to avoid displaying distorted content.
+ final int clampedStartXInSurface = Math.max(0,
+ Math.min(startXInSurface, surfaceWidth - mWindowWidth));
+ final int clampedStartYInSurface = Math.max(0,
+ Math.min(startYInSurface, surfaceHeight - mWindowHeight));
+
+ // Perform the pixel copy.
+ mPixelCopyRequestRect.set(clampedStartXInSurface,
+ clampedStartYInSurface,
+ clampedStartXInSurface + mBitmap.getWidth(),
+ clampedStartYInSurface + mBitmap.getHeight());
+ PixelCopy.request(surface, mPixelCopyRequestRect, mBitmap,
+ result -> {
+ getImageView().invalidate();
+ mPrevStartCoordsInSurface.x = startXInSurface;
+ mPrevStartCoordsInSurface.y = startYInSurface;
+ },
+ mPixelCopyHandler);
}
private ImageView getImageView() {
diff --git a/core/java/android/widget/MediaControlView2.java b/core/java/android/widget/MediaControlView2.java
index f1d633a..2e4cccf 100644
--- a/core/java/android/widget/MediaControlView2.java
+++ b/core/java/android/widget/MediaControlView2.java
@@ -19,18 +19,17 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.content.Context;
import android.media.session.MediaController;
import android.media.update.ApiLoader;
+import android.media.update.FrameLayoutHelper;
import android.media.update.MediaControlView2Provider;
-import android.media.update.ViewProvider;
import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+
/**
* A View that contains the controls for MediaPlayer2.
* It provides a wide range of UI including buttons such as "Play/Pause", "Rewind", "Fast Forward",
@@ -42,15 +41,28 @@
* adds it to the view.
* 2) Initialize MediaControlView2 programmatically and add it to a ViewGroup instance.
*
- * In the first option, VideoView2 automatically connects MediaControlView2 to MediaController2,
+ * In the first option, VideoView2 automatically connects MediaControlView2 to MediaController,
* which is necessary to communicate with MediaSession2. In the second option, however, the
- * developer needs to manually retrieve a MediaController2 instance and set it to MediaControlView2
- * by calling setController(MediaController2 controller).
+ * developer needs to manually retrieve a MediaController instance and set it to MediaControlView2
+ * by calling setController(MediaController controller).
+ *
+ * <p>
+ * There is no separate method that handles the show/hide behavior for MediaControlView2. Instead,
+ * one can directly change the visibility of this view by calling View.setVisibility(int). The
+ * values supported are View.VISIBLE and View.GONE.
+ * In addition, the following customizations are supported:
+ * 1. Modify default timeout value of 2 seconds by calling setTimeout(long).
+ * 2. Set focus to the play/pause button by calling requestPlayButtonFocus().
+ *
+ * <p>
+ * It is also possible to add custom buttons with custom icons and actions inside MediaControlView2.
+ * Those buttons will be shown when the overflow button is clicked.
+ * See {@link VideoView2#setCustomActions} for more details on how to add.
*
* TODO PUBLIC API
* @hide
*/
-public class MediaControlView2 extends FrameLayout {
+public class MediaControlView2 extends FrameLayoutHelper<MediaControlView2Provider> {
/** @hide */
@IntDef({
BUTTON_PLAY_PAUSE,
@@ -68,19 +80,66 @@
@Retention(RetentionPolicy.SOURCE)
public @interface Button {}
+ /**
+ * MediaControlView2 button value for playing and pausing media.
+ */
public static final int BUTTON_PLAY_PAUSE = 1;
+ /**
+ * MediaControlView2 button value for jumping 30 seconds forward.
+ */
public static final int BUTTON_FFWD = 2;
+ /**
+ * MediaControlView2 button value for jumping 10 seconds backward.
+ */
public static final int BUTTON_REW = 3;
+ /**
+ * MediaControlView2 button value for jumping to next media.
+ */
public static final int BUTTON_NEXT = 4;
+ /**
+ * MediaControlView2 button value for jumping to previous media.
+ */
public static final int BUTTON_PREV = 5;
+ /**
+ * MediaControlView2 button value for showing/hiding subtitle track.
+ */
public static final int BUTTON_SUBTITLE = 6;
+ /**
+ * MediaControlView2 button value for toggling full screen.
+ */
public static final int BUTTON_FULL_SCREEN = 7;
+ /**
+ * MediaControlView2 button value for showing/hiding overflow buttons.
+ */
public static final int BUTTON_OVERFLOW = 8;
+ /**
+ * MediaControlView2 button value for muting audio.
+ */
public static final int BUTTON_MUTE = 9;
+ /**
+ * MediaControlView2 button value for adjusting aspect ratio of view.
+ */
public static final int BUTTON_ASPECT_RATIO = 10;
+ /**
+ * MediaControlView2 button value for showing/hiding settings page.
+ */
public static final int BUTTON_SETTINGS = 11;
- private final MediaControlView2Provider mProvider;
+ /**
+ * String for receiving command to show subtitle from MediaSession. Can be checked by
+ * implementing {@link android.media.session.MediaSession.Callback#onCommand}
+ */
+ public static final String COMMAND_SHOW_SUBTITLE = "showSubtitle";
+ /**
+ * String for receiving command to hide subtitle from MediaSession. Can be checked by
+ * implementing {@link android.media.session.MediaSession.Callback#onCommand}
+ */
+ public static final String COMMAND_HIDE_SUBTITLE = "hideSubtitle";
+ /**
+ * String for receiving command to set fullscreen from MediaSession. Can be checked by
+ * implementing {@link android.media.session.MediaSession.Callback#onCommand}
+ */
+ public static final String COMMAND_SET_FULLSCREEN = "setFullscreen";
public MediaControlView2(@NonNull Context context) {
this(context, null);
@@ -91,49 +150,34 @@
}
public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs,
- int defStyleAttr) {
+ int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
-
- mProvider = ApiLoader.getProvider(context)
- .createMediaControlView2(this, new SuperProvider());
+ int defStyleAttr, int defStyleRes) {
+ super((instance, superProvider) ->
+ ApiLoader.getProvider(context).createMediaControlView2(
+ (MediaControlView2) instance, superProvider),
+ context, attrs, defStyleAttr, defStyleRes);
}
/**
* @hide
*/
+ @SystemApi
public MediaControlView2Provider getProvider() {
return mProvider;
}
/**
- * Sets MediaController2 instance to control corresponding MediaSession2.
+ * Sets MediaController instance to control corresponding MediaSession.
*/
public void setController(MediaController controller) {
mProvider.setController_impl(controller);
}
/**
- * Shows the control view on screen. It will disappear automatically after 3 seconds of
- * inactivity.
- */
- public void show() {
- mProvider.show_impl();
- }
-
- /**
- * Shows the control view on screen. It will disappear automatically after {@code timeout}
- * milliseconds of inactivity.
- */
- public void show(int timeout) {
- mProvider.show_impl(timeout);
- }
-
- /**
* Returns whether the control view is currently shown or hidden.
*/
public boolean isShowing() {
@@ -141,139 +185,56 @@
}
/**
- * Hide the control view from the screen.
- */
- public void hide() {
- mProvider.hide_impl();
- }
-
- /**
- * If the media selected has a subtitle track, calling this method will display the subtitle at
- * the bottom of the view. If a media has multiple subtitle tracks, this method will select the
- * first one of them.
- */
- public void showSubtitle() {
- mProvider.showSubtitle_impl();
- }
-
- /**
- * Hides the currently displayed subtitle.
- */
- public void hideSubtitle() {
- mProvider.hideSubtitle_impl();
- }
-
- /**
- * Set listeners for previous and next buttons to customize the behavior of clicking them.
- * The UI for these buttons are provided as default and will be automatically displayed when
- * this method is called.
+ * Changes the visibility state of an individual button. Default value is View.Visible.
*
- * @param next Listener for clicking next button
- * @param prev Listener for clicking previous button
+ * @param button the {@code Button} assigned to individual buttons
+ * <ul>
+ * <li>{@link #BUTTON_PLAY_PAUSE}
+ * <li>{@link #BUTTON_FFWD}
+ * <li>{@link #BUTTON_REW}
+ * <li>{@link #BUTTON_NEXT}
+ * <li>{@link #BUTTON_PREV}
+ * <li>{@link #BUTTON_SUBTITLE}
+ * <li>{@link #BUTTON_FULL_SCREEN}
+ * <li>{@link #BUTTON_MUTE}
+ * <li>{@link #BUTTON_OVERFLOW}
+ * <li>{@link #BUTTON_ASPECT_RATIO}
+ * <li>{@link #BUTTON_SETTINGS}
+ * </ul>
+ * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
*/
- public void setPrevNextListeners(View.OnClickListener next, View.OnClickListener prev) {
- mProvider.setPrevNextListeners_impl(next, prev);
+ public void setButtonVisibility(@Button int button, @Visibility int visibility) {
+ mProvider.setButtonVisibility_impl(button, visibility);
}
/**
- * Hides the specified button from view.
- *
- * @param button the constant integer assigned to individual buttons
- * @param visible whether the button should be visible or not
+ * Requests focus for the play/pause button.
*/
- public void setButtonVisibility(int button, boolean visible) {
- mProvider.setButtonVisibility_impl(button, visible);
+ public void requestPlayButtonFocus() {
+ mProvider.requestPlayButtonFocus_impl();
+ }
+
+ /**
+ * Sets a new timeout value (in milliseconds) for showing MediaControlView2. The default value
+ * is set as 2 seconds.
+ * @param timeout the
+ */
+ public void setTimeout(long timeout) {
+ mProvider.setTimeout_impl(timeout);
+ }
+
+ /**
+ * Retrieves current timeout value (in milliseconds) for showing MediaControlView2. The default
+ * value is set as 2 seconds.
+ */
+ public long getTimeout() {
+ return mProvider.getTimeout_impl();
}
@Override
- protected void onAttachedToWindow() {
- mProvider.onAttachedToWindow_impl();
- }
+ // TODO Move this method to ViewProvider
+ public void onVisibilityAggregated(boolean isVisible) {
- @Override
- protected void onDetachedFromWindow() {
- mProvider.onDetachedFromWindow_impl();
- }
-
- @Override
- public CharSequence getAccessibilityClassName() {
- return mProvider.getAccessibilityClassName_impl();
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- return mProvider.onTouchEvent_impl(ev);
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent ev) {
- return mProvider.onTrackballEvent_impl(ev);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return mProvider.onKeyDown_impl(keyCode, event);
- }
-
- @Override
- public void onFinishInflate() {
- mProvider.onFinishInflate_impl();
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- return mProvider.dispatchKeyEvent_impl(event);
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- mProvider.setEnabled_impl(enabled);
- }
-
- private class SuperProvider implements ViewProvider {
- @Override
- public void onAttachedToWindow_impl() {
- MediaControlView2.super.onAttachedToWindow();
- }
-
- @Override
- public void onDetachedFromWindow_impl() {
- MediaControlView2.super.onDetachedFromWindow();
- }
-
- @Override
- public CharSequence getAccessibilityClassName_impl() {
- return MediaControlView2.super.getAccessibilityClassName();
- }
-
- @Override
- public boolean onTouchEvent_impl(MotionEvent ev) {
- return MediaControlView2.super.onTouchEvent(ev);
- }
-
- @Override
- public boolean onTrackballEvent_impl(MotionEvent ev) {
- return MediaControlView2.super.onTrackballEvent(ev);
- }
-
- @Override
- public boolean onKeyDown_impl(int keyCode, KeyEvent event) {
- return MediaControlView2.super.onKeyDown(keyCode, event);
- }
-
- @Override
- public void onFinishInflate_impl() {
- MediaControlView2.super.onFinishInflate();
- }
-
- @Override
- public boolean dispatchKeyEvent_impl(KeyEvent event) {
- return MediaControlView2.super.dispatchKeyEvent(event);
- }
-
- @Override
- public void setEnabled_impl(boolean enabled) {
- MediaControlView2.super.setEnabled(enabled);
- }
+ mProvider.onVisibilityAggregated_impl(isVisible);
}
}
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 3bfa520..2e354c1 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -37,8 +37,8 @@
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextLinks;
import android.view.textclassifier.TextSelection;
-import android.view.textclassifier.logging.SmartSelectionEventTracker;
-import android.view.textclassifier.logging.SmartSelectionEventTracker.SelectionEvent;
+import android.view.textclassifier.logging.Logger;
+import android.view.textclassifier.logging.SelectionEvent;
import android.widget.Editor.SelectionModifierCursorController;
import com.android.internal.annotations.VisibleForTesting;
@@ -65,6 +65,7 @@
private static final String LOG_TAG = "SelectActionModeHelper";
+ // TODO: Make this a configurable flag.
private static final boolean SMART_SELECT_ANIMATION_ENABLED = true;
private final Editor mEditor;
@@ -172,7 +173,7 @@
public void onSelectionDrag() {
mSelectionTracker.onSelectionAction(
mTextView.getSelectionStart(), mTextView.getSelectionEnd(),
- SelectionEvent.ActionType.DRAG, mTextClassification);
+ SelectionEvent.ACTION_DRAG, mTextClassification);
}
public void onTextChanged(int start, int end) {
@@ -574,7 +575,7 @@
mSelectionEnd = editor.getTextView().getSelectionEnd();
mLogger.logSelectionAction(
textView.getSelectionStart(), textView.getSelectionEnd(),
- SelectionEvent.ActionType.RESET, null /* classification */);
+ SelectionEvent.ACTION_RESET, null /* classification */);
}
return selected;
}
@@ -583,7 +584,7 @@
public void onTextChanged(int start, int end, TextClassification classification) {
if (isSelectionStarted() && start == mSelectionStart && end == mSelectionEnd) {
- onSelectionAction(start, end, SelectionEvent.ActionType.OVERTYPE, classification);
+ onSelectionAction(start, end, SelectionEvent.ACTION_OVERTYPE, classification);
}
}
@@ -622,7 +623,7 @@
if (mIsPending) {
mLogger.logSelectionAction(
mSelectionStart, mSelectionEnd,
- SelectionEvent.ActionType.ABANDON, null /* classification */);
+ SelectionEvent.ACTION_ABANDON, null /* classification */);
mSelectionStart = mSelectionEnd = -1;
mIsPending = false;
}
@@ -649,22 +650,29 @@
private static final String LOG_TAG = "SelectionMetricsLogger";
private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+");
- private final SmartSelectionEventTracker mDelegate;
+ private final Logger mLogger;
private final boolean mEditTextLogger;
- private final BreakIterator mWordIterator;
+ private final BreakIterator mTokenIterator;
private int mStartIndex;
private String mText;
SelectionMetricsLogger(TextView textView) {
Preconditions.checkNotNull(textView);
- final @SmartSelectionEventTracker.WidgetType int widgetType = textView.isTextEditable()
- ? SmartSelectionEventTracker.WidgetType.EDITTEXT
- : (textView.isTextSelectable()
- ? SmartSelectionEventTracker.WidgetType.TEXTVIEW
- : SmartSelectionEventTracker.WidgetType.UNSELECTABLE_TEXTVIEW);
- mDelegate = new SmartSelectionEventTracker(textView.getContext(), widgetType);
+ mLogger = textView.getTextClassifier().getLogger(
+ new Logger.Config(textView.getContext(), getWidetType(textView), null));
mEditTextLogger = textView.isTextEditable();
- mWordIterator = BreakIterator.getWordInstance(textView.getTextLocale());
+ mTokenIterator = mLogger.getTokenIterator(textView.getTextLocale());
+ }
+
+ @Logger.WidgetType
+ private static String getWidetType(TextView textView) {
+ if (textView.isTextEditable()) {
+ return Logger.WIDGET_EDITTEXT;
+ }
+ if (textView.isTextSelectable()) {
+ return Logger.WIDGET_TEXTVIEW;
+ }
+ return Logger.WIDGET_UNSELECTABLE_TEXTVIEW;
}
public void logSelectionStarted(CharSequence text, int index) {
@@ -674,9 +682,9 @@
if (mText == null || !mText.contentEquals(text)) {
mText = text.toString();
}
- mWordIterator.setText(mText);
+ mTokenIterator.setText(mText);
mStartIndex = index;
- mDelegate.logEvent(SelectionEvent.selectionStarted(0));
+ mLogger.logSelectionStartedEvent(0);
} catch (Exception e) {
// Avoid crashes due to logging.
Log.d(LOG_TAG, e.getMessage());
@@ -690,14 +698,14 @@
Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
int[] wordIndices = getWordDelta(start, end);
if (selection != null) {
- mDelegate.logEvent(SelectionEvent.selectionModified(
- wordIndices[0], wordIndices[1], selection));
+ mLogger.logSelectionModifiedEvent(
+ wordIndices[0], wordIndices[1], selection);
} else if (classification != null) {
- mDelegate.logEvent(SelectionEvent.selectionModified(
- wordIndices[0], wordIndices[1], classification));
+ mLogger.logSelectionModifiedEvent(
+ wordIndices[0], wordIndices[1], classification);
} else {
- mDelegate.logEvent(SelectionEvent.selectionModified(
- wordIndices[0], wordIndices[1]));
+ mLogger.logSelectionModifiedEvent(
+ wordIndices[0], wordIndices[1]);
}
} catch (Exception e) {
// Avoid crashes due to logging.
@@ -714,11 +722,11 @@
Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
int[] wordIndices = getWordDelta(start, end);
if (classification != null) {
- mDelegate.logEvent(SelectionEvent.selectionAction(
- wordIndices[0], wordIndices[1], action, classification));
+ mLogger.logSelectionActionEvent(
+ wordIndices[0], wordIndices[1], action, classification);
} else {
- mDelegate.logEvent(SelectionEvent.selectionAction(
- wordIndices[0], wordIndices[1], action));
+ mLogger.logSelectionActionEvent(
+ wordIndices[0], wordIndices[1], action);
}
} catch (Exception e) {
// Avoid crashes due to logging.
@@ -741,10 +749,10 @@
wordIndices[0] = countWordsBackward(start);
// For the selection start index, avoid counting a partial word backwards.
- if (!mWordIterator.isBoundary(start)
+ if (!mTokenIterator.isBoundary(start)
&& !isWhitespace(
- mWordIterator.preceding(start),
- mWordIterator.following(start))) {
+ mTokenIterator.preceding(start),
+ mTokenIterator.following(start))) {
// We counted a partial word. Remove it.
wordIndices[0]--;
}
@@ -766,7 +774,7 @@
int wordCount = 0;
int offset = from;
while (offset > mStartIndex) {
- int start = mWordIterator.preceding(offset);
+ int start = mTokenIterator.preceding(offset);
if (!isWhitespace(start, offset)) {
wordCount++;
}
@@ -780,7 +788,7 @@
int wordCount = 0;
int offset = from;
while (offset < mStartIndex) {
- int end = mWordIterator.following(offset);
+ int end = mTokenIterator.following(offset);
if (!isWhitespace(offset, end)) {
wordCount++;
}
@@ -1021,20 +1029,20 @@
private static int getActionType(int menuItemId) {
switch (menuItemId) {
case TextView.ID_SELECT_ALL:
- return SelectionEvent.ActionType.SELECT_ALL;
+ return SelectionEvent.ACTION_SELECT_ALL;
case TextView.ID_CUT:
- return SelectionEvent.ActionType.CUT;
+ return SelectionEvent.ACTION_CUT;
case TextView.ID_COPY:
- return SelectionEvent.ActionType.COPY;
+ return SelectionEvent.ACTION_COPY;
case TextView.ID_PASTE: // fall through
case TextView.ID_PASTE_AS_PLAIN_TEXT:
- return SelectionEvent.ActionType.PASTE;
+ return SelectionEvent.ACTION_PASTE;
case TextView.ID_SHARE:
- return SelectionEvent.ActionType.SHARE;
+ return SelectionEvent.ACTION_SHARE;
case TextView.ID_ASSIST:
- return SelectionEvent.ActionType.SMART_SHARE;
+ return SelectionEvent.ACTION_SMART_SHARE;
default:
- return SelectionEvent.ActionType.OTHER;
+ return SelectionEvent.ACTION_OTHER;
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7d3fcf4..5710db3 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2397,7 +2397,7 @@
setText(mText);
if (hasPasswordTransformationMethod()) {
- notifyAccessibilityStateChanged(
+ notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
@@ -5152,7 +5152,8 @@
public void setAccessibilityHeading(boolean isHeading) {
if (isHeading != mIsAccessibilityHeading) {
mIsAccessibilityHeading = isHeading;
- notifyAccessibilityStateChanged(AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
}
@@ -5659,7 +5660,7 @@
sendOnTextChanged(text, 0, oldlen, textLength);
onTextChanged(text, 0, oldlen, textLength);
- notifyAccessibilityStateChanged(AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT);
+ notifyViewAccessibilityStateChangedIfNeeded(AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT);
if (needEditableForNotification) {
sendAfterTextChanged((Editable) text);
@@ -6393,7 +6394,7 @@
public void setError(CharSequence error, Drawable icon) {
createEditorIfNeeded();
mEditor.setError(error, icon);
- notifyAccessibilityStateChanged(
+ notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 706b0ce..77670b3 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -50,6 +50,7 @@
import com.android.internal.widget.NumericTextView;
import com.android.internal.widget.NumericTextView.OnValueChangedListener;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Calendar;
@@ -804,20 +805,56 @@
private void updateHeaderSeparator() {
final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mLocale,
(mIs24Hour) ? "Hm" : "hm");
- final String separatorText;
- // See http://www.unicode.org/reports/tr35/tr35-dates.html for hour formats
- final char[] hourFormats = {'H', 'h', 'K', 'k'};
- int hIndex = lastIndexOfAny(bestDateTimePattern, hourFormats);
- if (hIndex == -1) {
- // Default case
- separatorText = ":";
- } else {
- separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1));
- }
+ final String separatorText = getHourMinSeparatorFromPattern(bestDateTimePattern);
mSeparatorView.setText(separatorText);
mTextInputPickerView.updateSeparator(separatorText);
}
+ /**
+ * This helper method extracts the time separator from the {@code datetimePattern}.
+ *
+ * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":".
+ *
+ * See http://unicode.org/cldr/trac/browser/trunk/common/main
+ *
+ * @return Separator string. This is the character or set of quoted characters just after the
+ * hour marker in {@code dateTimePattern}. Returns a colon (:) if it can't locate the
+ * separator.
+ *
+ * @hide
+ */
+ private static String getHourMinSeparatorFromPattern(String dateTimePattern) {
+ final String defaultSeparator = ":";
+ boolean foundHourPattern = false;
+ for (int i = 0; i < dateTimePattern.length(); i++) {
+ switch (dateTimePattern.charAt(i)) {
+ // See http://www.unicode.org/reports/tr35/tr35-dates.html for hour formats.
+ case 'H':
+ case 'h':
+ case 'K':
+ case 'k':
+ foundHourPattern = true;
+ continue;
+ case ' ': // skip spaces
+ continue;
+ case '\'':
+ if (!foundHourPattern) {
+ continue;
+ }
+ SpannableStringBuilder quotedSubstring = new SpannableStringBuilder(
+ dateTimePattern.substring(i));
+ int quotedTextLength = DateFormat.appendQuotedText(quotedSubstring, 0);
+ return quotedSubstring.subSequence(0, quotedTextLength).toString();
+ default:
+ if (!foundHourPattern) {
+ continue;
+ }
+ return Character.toString(dateTimePattern.charAt(i));
+ }
+ }
+ return defaultSeparator;
+ }
+
static private int lastIndexOfAny(String str, char[] any) {
final int lengthAny = any.length;
if (lengthAny > 0) {
diff --git a/core/java/android/widget/VideoView2.java b/core/java/android/widget/VideoView2.java
index 7f0c086..78ca011 100644
--- a/core/java/android/widget/VideoView2.java
+++ b/core/java/android/widget/VideoView2.java
@@ -22,31 +22,32 @@
import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
-import android.media.MediaPlayerBase;
+import android.media.MediaPlayerInterface;
import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.PlaybackState;
import android.media.update.ApiLoader;
+import android.media.update.FrameLayoutHelper;
import android.media.update.VideoView2Provider;
-import android.media.update.ViewProvider;
import android.net.Uri;
+import android.os.Bundle;
import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
+import android.view.View;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executor;
-// TODO: Use @link tag to refer MediaPlayer2 in docs once MediaPlayer2.java is submitted. Same to
-// MediaSession2.
-// TODO: change the reference from MediaPlayer to MediaPlayer2.
+// TODO: Replace MediaSession wtih MediaSession2 once MediaSession2 is submitted.
/**
* Displays a video file. VideoView2 class is a View class which is wrapping MediaPlayer2 so that
* developers can easily implement a video rendering application.
*
* <p>
* <em> Data sources that VideoView2 supports : </em>
- * VideoView2 can play video files and audio-only fiels as
+ * VideoView2 can play video files and audio-only files as
* well. It can load from various sources such as resources or content providers. The supported
* media file formats are the same as MediaPlayer2.
*
@@ -100,7 +101,7 @@
*
* @hide
*/
-public class VideoView2 extends FrameLayout {
+public class VideoView2 extends FrameLayoutHelper<VideoView2Provider> {
/** @hide */
@IntDef({
VIEW_TYPE_TEXTUREVIEW,
@@ -109,10 +110,19 @@
@Retention(RetentionPolicy.SOURCE)
public @interface ViewType {}
+ /**
+ * Indicates video is rendering on SurfaceView.
+ *
+ * @see #setViewType
+ */
public static final int VIEW_TYPE_SURFACEVIEW = 1;
- public static final int VIEW_TYPE_TEXTUREVIEW = 2;
- private final VideoView2Provider mProvider;
+ /**
+ * Indicates video is rendering on TextureView.
+ *
+ * @see #setViewType
+ */
+ public static final int VIEW_TYPE_TEXTUREVIEW = 2;
public VideoView2(@NonNull Context context) {
this(context, null);
@@ -129,17 +139,10 @@
public VideoView2(
@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
-
- mProvider = ApiLoader.getProvider(context).createVideoView2(this, new SuperProvider(),
- attrs, defStyleAttr, defStyleRes);
- }
-
- /**
- * @hide
- */
- public VideoView2Provider getProvider() {
- return mProvider;
+ super((instance, superProvider) ->
+ ApiLoader.getProvider(context).createVideoView2(
+ (VideoView2) instance, superProvider, attrs, defStyleAttr, defStyleRes),
+ context, attrs, defStyleAttr, defStyleRes);
}
/**
@@ -175,32 +178,12 @@
}
/**
- * Returns the audio session ID.
+ * Shows or hides closed caption or subtitles if there is any.
+ * The first subtitle track will be chosen by default if there multiple subtitle tracks exist.
+ * @param show shows closed caption or subtitles if this value is true, or hides.
*/
- public int getAudioSessionId() {
- return mProvider.getAudioSessionId_impl();
- }
-
- /**
- * Starts rendering closed caption or subtitles if there is any. The first subtitle track will
- * be chosen by default if there multiple subtitle tracks exist.
- */
- public void showSubtitle() {
- mProvider.showSubtitle_impl();
- }
-
- /**
- * Stops showing closed captions or subtitles.
- */
- public void hideSubtitle() {
- mProvider.hideSubtitle_impl();
- }
-
- /**
- * Sets full screen mode.
- */
- public void setFullScreen(boolean fullScreen) {
- mProvider.setFullScreen_impl(fullScreen);
+ public void showSubtitle(boolean show) {
+ mProvider.showSubtitle_impl(show);
}
/**
@@ -251,16 +234,34 @@
*
* @param routeCategories the list of media control categories in
* {@link android.support.v7.media.MediaControlIntent}
- * @param player the player to handle the selected route. If null, a default
- * route player will be used.
+ * @param player the player to handle playback of the selected route.
+ * If null, a default route player will be used.
* @throws IllegalStateException if MediaControlView2 is not set.
+ * @hide
*/
public void setRouteAttributes(@NonNull List<String> routeCategories,
- @Nullable MediaPlayerBase player) {
+ @Nullable MediaPlayerInterface player) {
mProvider.setRouteAttributes_impl(routeCategories, player);
}
/**
+ * Sets a remote player for handling playback of the selected route from MediaControlView2.
+ * If this is not called, MediaCotrolView2 will not show the route button.
+ *
+ * @param routeCategories the list of media control categories in
+ * {@link android.support.v7.media.MediaControlIntent}
+ * @param sessionPlayer the player to handle playback of the selected route.
+ * If null, a default route player will be used.
+ * @throws IllegalStateException if MediaControlView2 is not set.
+ * @hide
+ */
+ // TODO: Use MediaPlayerBase once MediaSession2 APIs are ready.
+ public void setRouteAttributes(@NonNull List<String> routeCategories,
+ @Nullable MediaSession.Callback sessionPlayer) {
+ mProvider.setRouteAttributes_impl(routeCategories, sessionPlayer);
+ }
+
+ /**
* Sets video path.
*
* @param path the path of the video.
@@ -274,8 +275,8 @@
*
* @param uri the URI of the video.
*/
- public void setVideoURI(Uri uri) {
- mProvider.setVideoURI_impl(uri);
+ public void setVideoUri(Uri uri) {
+ mProvider.setVideoUri_impl(uri);
}
/**
@@ -288,8 +289,8 @@
* "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
* to disallow or allow cross domain redirection.
*/
- public void setVideoURI(Uri uri, Map<String, String> headers) {
- mProvider.setVideoURI_impl(uri, headers);
+ public void setVideoUri(Uri uri, Map<String, String> headers) {
+ mProvider.setVideoUri_impl(uri, headers);
}
/**
@@ -316,22 +317,38 @@
}
/**
+ * Sets custom actions which will be shown as custom buttons in {@link MediaControlView2}.
+ *
+ * @param actionList A list of {@link PlaybackState.CustomAction}. The return value of
+ * {@link PlaybackState.CustomAction#getIcon()} will be used to draw buttons
+ * in {@link MediaControlView2}.
+ * @param executor executor to run callbacks on.
+ * @param listener A listener to be called when a custom button is clicked.
+ */
+ public void setCustomActions(List<PlaybackState.CustomAction> actionList,
+ Executor executor, OnCustomActionListener listener) {
+ mProvider.setCustomActions_impl(actionList, executor, listener);
+ }
+
+ /**
* Registers a callback to be invoked when the media file is loaded and ready to go.
*
+ * @param executor executor to run callbacks on.
* @param l the callback that will be run.
*/
- public void setOnPreparedListener(OnPreparedListener l) {
- mProvider.setOnPreparedListener_impl(l);
+ public void setOnPreparedListener(Executor executor, OnPreparedListener l) {
+ mProvider.setOnPreparedListener_impl(executor, l);
}
/**
* Registers a callback to be invoked when the end of a media file has been reached during
* playback.
*
+ * @param executor executor to run callbacks on.
* @param l the callback that will be run.
*/
- public void setOnCompletionListener(OnCompletionListener l) {
- mProvider.setOnCompletionListener_impl(l);
+ public void setOnCompletionListener(Executor executor, OnCompletionListener l) {
+ mProvider.setOnCompletionListener_impl(executor, l);
}
/**
@@ -339,52 +356,58 @@
* listener is specified, or if the listener returned false, VideoView2 will inform the user of
* any errors.
*
+ * @param executor executor to run callbacks on.
* @param l The callback that will be run
*/
- public void setOnErrorListener(OnErrorListener l) {
- mProvider.setOnErrorListener_impl(l);
+ public void setOnErrorListener(Executor executor, OnErrorListener l) {
+ mProvider.setOnErrorListener_impl(executor, l);
}
/**
* Registers a callback to be invoked when an informational event occurs during playback or
* setup.
*
+ * @param executor executor to run callbacks on.
* @param l The callback that will be run
*/
- public void setOnInfoListener(OnInfoListener l) {
- mProvider.setOnInfoListener_impl(l);
+ public void setOnInfoListener(Executor executor, OnInfoListener l) {
+ mProvider.setOnInfoListener_impl(executor, l);
}
/**
* Registers a callback to be invoked when a view type change is done.
* {@see #setViewType(int)}
+ * @param executor executor to run callbacks on.
* @param l The callback that will be run
*/
- public void setOnViewTypeChangedListener(OnViewTypeChangedListener l) {
- mProvider.setOnViewTypeChangedListener_impl(l);
+ public void setOnViewTypeChangedListener(Executor executor, OnViewTypeChangedListener l) {
+ mProvider.setOnViewTypeChangedListener_impl(executor, l);
}
/**
* Registers a callback to be invoked when the fullscreen mode should be changed.
+ * @param executor executor to run callbacks on.
+ * @param l The callback that will be run
*/
- public void setFullScreenChangedListener(OnFullScreenChangedListener l) {
- mProvider.setFullScreenChangedListener_impl(l);
+ public void setFullScreenRequestListener(Executor executor, OnFullScreenRequestListener l) {
+ mProvider.setFullScreenRequestListener_impl(executor, l);
}
/**
- * Interface definition of a callback to be invoked when the viw type has been changed.
+ * Interface definition of a callback to be invoked when the view type has been changed.
*/
public interface OnViewTypeChangedListener {
/**
* Called when the view type has been changed.
* @see #setViewType(int)
+ * @param view the View whose view type is changed
* @param viewType
* <ul>
* <li>{@link #VIEW_TYPE_SURFACEVIEW}
* <li>{@link #VIEW_TYPE_TEXTUREVIEW}
* </ul>
*/
- void onViewTypeChanged(@ViewType int viewType);
+ void onViewTypeChanged(View view, @ViewType int viewType);
}
/**
@@ -394,7 +417,7 @@
/**
* Called when the media file is ready for playback.
*/
- void onPrepared();
+ void onPrepared(View view);
}
/**
@@ -405,7 +428,7 @@
/**
* Called when the end of a media source is reached during playback.
*/
- void onCompletion();
+ void onCompletion(View view);
}
/**
@@ -421,7 +444,7 @@
* @return true if the method handled the error, false if it didn't.
* @see MediaPlayer#OnErrorListener
*/
- boolean onError(int what, int extra);
+ boolean onError(View view, int what, int extra);
}
/**
@@ -436,108 +459,32 @@
*
* @see MediaPlayer#OnInfoListener
*/
- void onInfo(int what, int extra);
+ void onInfo(View view, int what, int extra);
}
/**
* Interface definition of a callback to be invoked to inform the fullscreen mode is changed.
+ * Application should handle the fullscreen mode accordingly.
*/
- public interface OnFullScreenChangedListener {
+ public interface OnFullScreenRequestListener {
/**
* Called to indicate a fullscreen mode change.
*/
- void onFullScreenChanged(boolean fullScreen);
+ void onFullScreenRequest(View view, boolean fullScreen);
}
- @Override
- protected void onAttachedToWindow() {
- mProvider.onAttachedToWindow_impl();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- mProvider.onDetachedFromWindow_impl();
- }
-
- @Override
- public CharSequence getAccessibilityClassName() {
- return mProvider.getAccessibilityClassName_impl();
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- return mProvider.onTouchEvent_impl(ev);
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent ev) {
- return mProvider.onTrackballEvent_impl(ev);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return mProvider.onKeyDown_impl(keyCode, event);
- }
-
- @Override
- public void onFinishInflate() {
- mProvider.onFinishInflate_impl();
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- return mProvider.dispatchKeyEvent_impl(event);
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- mProvider.setEnabled_impl(enabled);
- }
-
- private class SuperProvider implements ViewProvider {
- @Override
- public void onAttachedToWindow_impl() {
- VideoView2.super.onAttachedToWindow();
- }
-
- @Override
- public void onDetachedFromWindow_impl() {
- VideoView2.super.onDetachedFromWindow();
- }
-
- @Override
- public CharSequence getAccessibilityClassName_impl() {
- return VideoView2.super.getAccessibilityClassName();
- }
-
- @Override
- public boolean onTouchEvent_impl(MotionEvent ev) {
- return VideoView2.super.onTouchEvent(ev);
- }
-
- @Override
- public boolean onTrackballEvent_impl(MotionEvent ev) {
- return VideoView2.super.onTrackballEvent(ev);
- }
-
- @Override
- public boolean onKeyDown_impl(int keyCode, KeyEvent event) {
- return VideoView2.super.onKeyDown(keyCode, event);
- }
-
- @Override
- public void onFinishInflate_impl() {
- VideoView2.super.onFinishInflate();
- }
-
- @Override
- public boolean dispatchKeyEvent_impl(KeyEvent event) {
- return VideoView2.super.dispatchKeyEvent(event);
- }
-
- @Override
- public void setEnabled_impl(boolean enabled) {
- VideoView2.super.setEnabled(enabled);
- }
+ /**
+ * Interface definition of a callback to be invoked to inform that a custom action is performed.
+ */
+ // TODO: When MediaSession2 is ready, modify the method to match the signature.
+ public interface OnCustomActionListener {
+ /**
+ * Called to indicate that a custom action is performed.
+ *
+ * @param action The action that was originally sent in the
+ * {@link PlaybackState.CustomAction}.
+ * @param extras Optional extras.
+ */
+ void onCustomAction(String action, Bundle extras);
}
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 997d47f..6e0ba341 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -841,7 +841,7 @@
}
@Override
- public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
+ public boolean startAsCaller(Activity activity, Bundle options, int userId) {
final Intent intent = getBaseIntentToSend();
if (intent == null) {
return false;
@@ -860,7 +860,8 @@
final boolean ignoreTargetSecurity = mSourceInfo != null
&& mSourceInfo.getResolvedComponentName().getPackageName()
.equals(mChooserTarget.getComponentName().getPackageName());
- return activity.startAsCallerImpl(intent, options, ignoreTargetSecurity, userId);
+ activity.startActivityAsCaller(intent, options, ignoreTargetSecurity, userId);
+ return true;
}
@Override
diff --git a/core/java/com/android/internal/app/EventLogTags.logtags b/core/java/com/android/internal/app/EventLogTags.logtags
new file mode 100644
index 0000000..d681a8d
--- /dev/null
+++ b/core/java/com/android/internal/app/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.internal.app;
+
+53000 harmful_app_warning_uninstall (package_name|3)
+53001 harmful_app_warning_launch_anyway (package_name|3)
\ No newline at end of file
diff --git a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
index 042da36..9966626 100644
--- a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
+++ b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
@@ -20,8 +20,12 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
import com.android.internal.R;
/**
@@ -31,7 +35,7 @@
*/
public class HarmfulAppWarningActivity extends AlertActivity implements
DialogInterface.OnClickListener {
- private static final String TAG = "HarmfulAppWarningActivity";
+ private static final String TAG = HarmfulAppWarningActivity.class.getSimpleName();
private static final String EXTRA_HARMFUL_APP_WARNING = "harmful_app_warning";
@@ -39,13 +43,11 @@
private String mHarmfulAppWarning;
private IntentSender mTarget;
- // [b/63909431] STOPSHIP replace placeholder UI with final Harmful App Warning UI
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Intent intent = getIntent();
+ final Intent intent = getIntent();
mPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
mTarget = intent.getParcelableExtra(Intent.EXTRA_INTENT);
mHarmfulAppWarning = intent.getStringExtra(EXTRA_HARMFUL_APP_WARNING);
@@ -55,33 +57,56 @@
finish();
}
- AlertController.AlertParams p = mAlertParams;
+ final ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = getPackageManager().getApplicationInfo(mPackageName, 0 /*flags*/);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Could not show warning because package does not exist ", e);
+ finish();
+ return;
+ }
+
+ final AlertController.AlertParams p = mAlertParams;
p.mTitle = getString(R.string.harmful_app_warning_title);
- p.mMessage = mHarmfulAppWarning;
- p.mPositiveButtonText = getString(R.string.harmful_app_warning_launch_anyway);
+ p.mView = createView(applicationInfo);
+
+ p.mPositiveButtonText = getString(R.string.harmful_app_warning_uninstall);
p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(R.string.harmful_app_warning_uninstall);
+ p.mNegativeButtonText = getString(R.string.harmful_app_warning_open_anyway);
p.mNegativeButtonListener = this;
mAlert.installContent(mAlertParams);
}
+ private View createView(ApplicationInfo applicationInfo) {
+ final View view = getLayoutInflater().inflate(R.layout.harmful_app_warning_dialog,
+ null /*root*/);
+ ((TextView) view.findViewById(R.id.app_name_text))
+ .setText(applicationInfo.loadSafeLabel(getPackageManager()));
+ ((TextView) view.findViewById(R.id.message))
+ .setText(mHarmfulAppWarning);
+ return view;
+ }
+
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
- getPackageManager().setHarmfulAppWarning(mPackageName, null);
-
- IntentSender target = getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
- try {
- startIntentSenderForResult(target, -1, null, 0, 0, 0);
- } catch (IntentSender.SendIntentException e) {
- // ignore..
- }
+ getPackageManager().deletePackage(mPackageName, null /*observer*/, 0 /*flags*/);
+ EventLogTags.writeHarmfulAppWarningUninstall(mPackageName);
finish();
break;
case DialogInterface.BUTTON_NEGATIVE:
- getPackageManager().deletePackage(mPackageName, null, 0);
+ getPackageManager().setHarmfulAppWarning(mPackageName, null /*warning*/);
+
+ final IntentSender target = getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
+ try {
+ startIntentSenderForResult(target, -1 /*requestCode*/, null /*fillInIntent*/,
+ 0 /*flagsMask*/, 0 /*flagsValue*/, 0 /*extraFlags*/);
+ } catch (IntentSender.SendIntentException e) {
+ Log.e(TAG, "Error while starting intent sender", e);
+ }
+ EventLogTags.writeHarmfulAppWarningLaunchAnyway(mPackageName);
finish();
break;
}
@@ -89,7 +114,7 @@
public static Intent createHarmfulAppWarningIntent(Context context, String targetPackageName,
IntentSender target, CharSequence harmfulAppWarning) {
- Intent intent = new Intent();
+ final Intent intent = new Intent();
intent.setClass(context, HarmfulAppWarningActivity.class);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, targetPackageName);
intent.putExtra(Intent.EXTRA_INTENT, target);
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 86731bc..398d087 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -107,7 +107,7 @@
|| ChooserActivity.class.getName().equals(ri.activityInfo.name));
try {
- startActivityAsCaller(newIntent, null, null, false, targetUserId);
+ startActivityAsCaller(newIntent, null, false, targetUserId);
} catch (RuntimeException e) {
int launchedFromUid = -1;
String launchedFromPackage = "?";
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index d6d4490..ceb06f5 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -43,7 +43,6 @@
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
-import android.os.IBinder;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.StrictMode;
@@ -858,36 +857,6 @@
}
}
- public boolean startAsCallerImpl(Intent intent, Bundle options, boolean ignoreTargetSecurity,
- int userId) {
- // Pass intent to delegate chooser activity with permission token.
- // TODO: This should move to a trampoline Activity in the system when the ChooserActivity
- // moves into systemui
- try {
- // TODO: Once this is a small springboard activity, it can move off the UI process
- // and we can move the request method to ActivityManagerInternal.
- IBinder permissionToken = ActivityManager.getService()
- .requestStartActivityPermissionToken(getActivityToken());
- final Intent chooserIntent = new Intent();
- final ComponentName delegateActivity = ComponentName.unflattenFromString(
- Resources.getSystem().getString(R.string.config_chooserActivity));
- chooserIntent.setClassName(delegateActivity.getPackageName(),
- delegateActivity.getClassName());
- chooserIntent.putExtra(ActivityManager.EXTRA_PERMISSION_TOKEN, permissionToken);
-
- // TODO: These extras will change as chooser activity moves into systemui
- chooserIntent.putExtra(Intent.EXTRA_INTENT, intent);
- chooserIntent.putExtra(ActivityManager.EXTRA_OPTIONS, options);
- chooserIntent.putExtra(ActivityManager.EXTRA_IGNORE_TARGET_SECURITY,
- ignoreTargetSecurity);
- chooserIntent.putExtra(Intent.EXTRA_USER_ID, userId);
- startActivity(chooserIntent);
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
- return true;
- }
-
public void onActivityStarted(TargetInfo cti) {
// Do nothing
}
@@ -1212,8 +1181,9 @@
}
@Override
- public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
- return activity.startAsCallerImpl(mResolvedIntent, options, false, userId);
+ public boolean startAsCaller(Activity activity, Bundle options, int userId) {
+ activity.startActivityAsCaller(mResolvedIntent, options, false, userId);
+ return true;
}
@Override
@@ -1272,7 +1242,7 @@
* @param userId userId to start as or {@link UserHandle#USER_NULL} for activity's caller
* @return true if the start completed successfully
*/
- boolean startAsCaller(ResolverActivity activity, Bundle options, int userId);
+ boolean startAsCaller(Activity activity, Bundle options, int userId);
/**
* Start the activity referenced by this target as a given user.
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 2ab2d20..1dfff5e 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -103,11 +103,14 @@
List<ResolverActivity.ResolvedComponentInfo> resolvedComponents = null;
for (int i = 0, N = intents.size(); i < N; i++) {
final Intent intent = intents.get(i);
- final List<ResolveInfo> infos = mpm.queryIntentActivities(intent,
- PackageManager.MATCH_DEFAULT_ONLY
- | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
- | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0)
- | PackageManager.MATCH_INSTANT);
+ int flags = PackageManager.MATCH_DEFAULT_ONLY
+ | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
+ | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0);
+ if (intent.isBrowsableWebIntent()
+ || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
+ flags |= PackageManager.MATCH_INSTANT;
+ }
+ final List<ResolveInfo> infos = mpm.queryIntentActivities(intent, flags);
// Remove any activities that are not exported.
int totalSize = infos.size();
for (int j = totalSize - 1; j >= 0 ; j--) {
diff --git a/core/java/com/android/internal/app/procstats/DumpUtils.java b/core/java/com/android/internal/app/procstats/DumpUtils.java
index 0bc8c483..e38a844 100644
--- a/core/java/com/android/internal/app/procstats/DumpUtils.java
+++ b/core/java/com/android/internal/app/procstats/DumpUtils.java
@@ -21,6 +21,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.service.procstats.ProcessStatsProto;
import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -46,12 +47,77 @@
* Utilities for dumping.
*/
public final class DumpUtils {
- public static final String[] STATE_NAMES = new String[] {
- "Persist", "Top ", "ImpFg ", "ImpBg ",
- "Backup ", "HeavyWt", "Service", "ServRst",
- "Receivr", "Home ",
- "LastAct", "CchAct ", "CchCAct", "CchEmty"
- };
+ public static final String[] STATE_NAMES;
+ public static final String[] STATE_NAMES_CSV;
+ static final String[] STATE_TAGS;
+ static final int[] STATE_PROTO_ENUMS;
+
+ // Make the mapping easy to update.
+ static {
+ STATE_NAMES = new String[STATE_COUNT];
+ STATE_NAMES[STATE_PERSISTENT] = "Persist";
+ STATE_NAMES[STATE_TOP] = "Top";
+ STATE_NAMES[STATE_IMPORTANT_FOREGROUND] = "ImpFg";
+ STATE_NAMES[STATE_IMPORTANT_BACKGROUND] = "ImpBg";
+ STATE_NAMES[STATE_BACKUP] = "Backup";
+ STATE_NAMES[STATE_SERVICE] = "Service";
+ STATE_NAMES[STATE_SERVICE_RESTARTING] = "ServRst";
+ STATE_NAMES[STATE_RECEIVER] = "Receivr";
+ STATE_NAMES[STATE_HEAVY_WEIGHT] = "HeavyWt";
+ STATE_NAMES[STATE_HOME] = "Home";
+ STATE_NAMES[STATE_LAST_ACTIVITY] = "LastAct";
+ STATE_NAMES[STATE_CACHED_ACTIVITY] = "CchAct";
+ STATE_NAMES[STATE_CACHED_ACTIVITY_CLIENT] = "CchCAct";
+ STATE_NAMES[STATE_CACHED_EMPTY] = "CchEmty";
+
+ STATE_NAMES_CSV = new String[STATE_COUNT];
+ STATE_NAMES_CSV[STATE_PERSISTENT] = "pers";
+ STATE_NAMES_CSV[STATE_TOP] = "top";
+ STATE_NAMES_CSV[STATE_IMPORTANT_FOREGROUND] = "impfg";
+ STATE_NAMES_CSV[STATE_IMPORTANT_BACKGROUND] = "impbg";
+ STATE_NAMES_CSV[STATE_BACKUP] = "backup";
+ STATE_NAMES_CSV[STATE_SERVICE] = "service";
+ STATE_NAMES_CSV[STATE_SERVICE_RESTARTING] = "service-rs";
+ STATE_NAMES_CSV[STATE_RECEIVER] = "receiver";
+ STATE_NAMES_CSV[STATE_HEAVY_WEIGHT] = "heavy";
+ STATE_NAMES_CSV[STATE_HOME] = "home";
+ STATE_NAMES_CSV[STATE_LAST_ACTIVITY] = "lastact";
+ STATE_NAMES_CSV[STATE_CACHED_ACTIVITY] = "cch-activity";
+ STATE_NAMES_CSV[STATE_CACHED_ACTIVITY_CLIENT] = "cch-aclient";
+ STATE_NAMES_CSV[STATE_CACHED_EMPTY] = "cch-empty";
+
+ STATE_TAGS = new String[STATE_COUNT];
+ STATE_TAGS[STATE_PERSISTENT] = "p";
+ STATE_TAGS[STATE_TOP] = "t";
+ STATE_TAGS[STATE_IMPORTANT_FOREGROUND] = "f";
+ STATE_TAGS[STATE_IMPORTANT_BACKGROUND] = "b";
+ STATE_TAGS[STATE_BACKUP] = "u";
+ STATE_TAGS[STATE_SERVICE] = "s";
+ STATE_TAGS[STATE_SERVICE_RESTARTING] = "x";
+ STATE_TAGS[STATE_RECEIVER] = "r";
+ STATE_TAGS[STATE_HEAVY_WEIGHT] = "w";
+ STATE_TAGS[STATE_HOME] = "h";
+ STATE_TAGS[STATE_LAST_ACTIVITY] = "l";
+ STATE_TAGS[STATE_CACHED_ACTIVITY] = "a";
+ STATE_TAGS[STATE_CACHED_ACTIVITY_CLIENT] = "c";
+ STATE_TAGS[STATE_CACHED_EMPTY] = "e";
+
+ STATE_PROTO_ENUMS = new int[STATE_COUNT];
+ STATE_PROTO_ENUMS[STATE_PERSISTENT] = ProcessStatsProto.State.PERSISTENT;
+ STATE_PROTO_ENUMS[STATE_TOP] = ProcessStatsProto.State.TOP;
+ STATE_PROTO_ENUMS[STATE_IMPORTANT_FOREGROUND] = ProcessStatsProto.State.IMPORTANT_FOREGROUND;
+ STATE_PROTO_ENUMS[STATE_IMPORTANT_BACKGROUND] = ProcessStatsProto.State.IMPORTANT_BACKGROUND;
+ STATE_PROTO_ENUMS[STATE_BACKUP] = ProcessStatsProto.State.BACKUP;
+ STATE_PROTO_ENUMS[STATE_SERVICE] = ProcessStatsProto.State.SERVICE;
+ STATE_PROTO_ENUMS[STATE_SERVICE_RESTARTING] = ProcessStatsProto.State.SERVICE_RESTARTING;
+ STATE_PROTO_ENUMS[STATE_RECEIVER] = ProcessStatsProto.State.RECEIVER;
+ STATE_PROTO_ENUMS[STATE_HEAVY_WEIGHT] = ProcessStatsProto.State.HEAVY_WEIGHT;
+ STATE_PROTO_ENUMS[STATE_HOME] = ProcessStatsProto.State.HOME;
+ STATE_PROTO_ENUMS[STATE_LAST_ACTIVITY] = ProcessStatsProto.State.LAST_ACTIVITY;
+ STATE_PROTO_ENUMS[STATE_CACHED_ACTIVITY] = ProcessStatsProto.State.CACHED_ACTIVITY;
+ STATE_PROTO_ENUMS[STATE_CACHED_ACTIVITY_CLIENT] = ProcessStatsProto.State.CACHED_ACTIVITY_CLIENT;
+ STATE_PROTO_ENUMS[STATE_CACHED_EMPTY] = ProcessStatsProto.State.CACHED_EMPTY;
+ }
public static final String[] ADJ_SCREEN_NAMES_CSV = new String[] {
"off", "on"
@@ -61,25 +127,26 @@
"norm", "mod", "low", "crit"
};
- public static final String[] STATE_NAMES_CSV = new String[] {
- "pers", "top", "impfg", "impbg", "backup", "heavy",
- "service", "service-rs", "receiver", "home", "lastact",
- "cch-activity", "cch-aclient", "cch-empty"
- };
-
// State enum is defined in frameworks/base/core/proto/android/service/procstats.proto
// Update states must sync enum definition as well, the ordering must not be changed.
static final String[] ADJ_SCREEN_TAGS = new String[] {
"0", "1"
};
+ static final int[] ADJ_SCREEN_PROTO_ENUMS = new int[] {
+ ProcessStatsProto.State.OFF,
+ ProcessStatsProto.State.ON
+ };
+
static final String[] ADJ_MEM_TAGS = new String[] {
"n", "m", "l", "c"
};
- static final String[] STATE_TAGS = new String[] {
- "p", "t", "f", "b", "u", "w",
- "s", "x", "r", "h", "l", "a", "c", "e"
+ static final int[] ADJ_MEM_PROTO_ENUMS = new int[] {
+ ProcessStatsProto.State.NORMAL,
+ ProcessStatsProto.State.MODERATE,
+ ProcessStatsProto.State.LOW,
+ ProcessStatsProto.State.CRITICAL
};
static final String CSV_SEP = "\t";
@@ -182,9 +249,10 @@
public static void printProcStateTagProto(ProtoOutputStream proto, long screenId, long memId,
long stateId, int state) {
- state = printProto(proto, screenId, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD * STATE_COUNT);
- state = printProto(proto, memId, ADJ_MEM_TAGS, state, STATE_COUNT);
- printProto(proto, stateId, STATE_TAGS, state, 1);
+ state = printProto(proto, screenId, ADJ_SCREEN_PROTO_ENUMS,
+ state, ADJ_SCREEN_MOD * STATE_COUNT);
+ state = printProto(proto, memId, ADJ_MEM_PROTO_ENUMS, state, STATE_COUNT);
+ printProto(proto, stateId, STATE_PROTO_ENUMS, state, 1);
}
public static void printAdjTag(PrintWriter pw, int state) {
@@ -294,30 +362,6 @@
}
}
- /*
- * Doesn't seem to be used.
- *
- public static void dumpProcessList(PrintWriter pw, String prefix, ArrayList<ProcessState> procs,
- int[] screenStates, int[] memStates, int[] procStates, long now) {
- String innerPrefix = prefix + " ";
- for (int i=procs.size()-1; i>=0; i--) {
- ProcessState proc = procs.get(i);
- pw.print(prefix);
- pw.print(proc.mName);
- pw.print(" / ");
- UserHandle.formatUid(pw, proc.mUid);
- pw.print(" (");
- pw.print(proc.durations.getKeyCount());
- pw.print(" entries)");
- pw.println(":");
- proc.dumpProcessState(pw, innerPrefix, screenStates, memStates, procStates, now);
- if (proc.pssTable.getKeyCount() > 0) {
- proc.dumpPss(pw, innerPrefix, screenStates, memStates, procStates);
- }
- }
- }
- */
-
public static void dumpProcessSummaryLocked(PrintWriter pw, String prefix,
ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates,
long now, long totalTime) {
@@ -362,11 +406,11 @@
return value - index*mod;
}
- public static int printProto(ProtoOutputStream proto, long fieldId, String[] array, int value, int mod) {
+ public static int printProto(ProtoOutputStream proto, long fieldId,
+ int[] enums, int value, int mod) {
int index = value/mod;
- if (index >= 0 && index < array.length) {
- // Valid state enum number starts at 1, 0 stands for unknown.
- proto.write(fieldId, index + 1);
+ if (index >= 0 && index < enums.length) {
+ proto.write(fieldId, enums[index]);
} // else enum default is always zero in proto3
return value - index*mod;
}
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index a0be64b..65bd48f 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -17,25 +17,18 @@
package com.android.internal.app.procstats;
import android.os.Parcel;
-import android.os.Parcelable;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.UserHandle;
-import android.service.pm.PackageProto;
import android.service.procstats.ProcessStatsProto;
-import android.text.format.DateFormat;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;
-import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ProcessStats.PackageState;
import com.android.internal.app.procstats.ProcessStats.ProcessStateHolder;
import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
@@ -43,6 +36,9 @@
import static com.android.internal.app.procstats.ProcessStats.PSS_MINIMUM;
import static com.android.internal.app.procstats.ProcessStats.PSS_AVERAGE;
import static com.android.internal.app.procstats.ProcessStats.PSS_MAXIMUM;
+import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MINIMUM;
+import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_AVERAGE;
+import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MAXIMUM;
import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MINIMUM;
import static com.android.internal.app.procstats.ProcessStats.PSS_USS_AVERAGE;
import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MAXIMUM;
@@ -64,20 +60,10 @@
import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED_EMPTY;
import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT;
-import dalvik.system.VMRuntime;
-import libcore.util.EmptyArray;
-
-import java.io.IOException;
-import java.io.InputStream;
import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import java.util.Objects;
public final class ProcessState {
private static final String TAG = "ProcessStats";
@@ -469,13 +455,21 @@
}
}
- public void addPss(long pss, long uss, boolean always, int type, long duration,
+ public void addPss(long pss, long uss, long rss, boolean always, int type, long duration,
ArrayMap<String, ProcessStateHolder> pkgList) {
ensureNotDead();
switch (type) {
- case ProcessStats.ADD_PSS_INTERNAL:
- mStats.mInternalPssCount++;
- mStats.mInternalPssTime += duration;
+ case ProcessStats.ADD_PSS_INTERNAL_SINGLE:
+ mStats.mInternalSinglePssCount++;
+ mStats.mInternalSinglePssTime += duration;
+ break;
+ case ProcessStats.ADD_PSS_INTERNAL_ALL_MEM:
+ mStats.mInternalAllMemPssCount++;
+ mStats.mInternalAllMemPssTime += duration;
+ break;
+ case ProcessStats.ADD_PSS_INTERNAL_ALL_POLL:
+ mStats.mInternalAllPollPssCount++;
+ mStats.mInternalAllPollPssTime += duration;
break;
case ProcessStats.ADD_PSS_EXTERNAL:
mStats.mExternalPssCount++;
@@ -496,7 +490,8 @@
mLastPssTime = SystemClock.uptimeMillis();
if (mCurState != STATE_NOTHING) {
// First update the common process.
- mCommonProcess.mPssTable.mergeStats(mCurState, 1, pss, pss, pss, uss, uss, uss);
+ mCommonProcess.mPssTable.mergeStats(mCurState, 1, pss, pss, pss, uss, uss, uss,
+ rss, rss, rss);
// If the common process is not multi-package, there is nothing else to do.
if (!mCommonProcess.mMultiPackage) {
@@ -506,7 +501,7 @@
if (pkgList != null) {
for (int ip=pkgList.size()-1; ip>=0; ip--) {
pullFixedProc(pkgList, ip).mPssTable.mergeStats(mCurState, 1,
- pss, pss, pss, uss, uss, uss);
+ pss, pss, pss, uss, uss, uss, rss, rss, rss);
}
}
}
@@ -658,6 +653,18 @@
return mPssTable.getValueForId((byte)state, PSS_USS_MAXIMUM);
}
+ public long getPssRssMinimum(int state) {
+ return mPssTable.getValueForId((byte)state, PSS_RSS_MINIMUM);
+ }
+
+ public long getPssRssAverage(int state) {
+ return mPssTable.getValueForId((byte)state, PSS_RSS_AVERAGE);
+ }
+
+ public long getPssRssMaximum(int state) {
+ return mPssTable.getValueForId((byte)state, PSS_RSS_MAXIMUM);
+ }
+
/**
* Sums up the PSS data and adds it to 'data'.
*
@@ -793,6 +800,8 @@
new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true);
dumpProcessSummaryDetails(pw, prefix, " Receiver: ", screenStates, memStates,
new int[] {STATE_RECEIVER}, now, totalTime, true);
+ dumpProcessSummaryDetails(pw, prefix, " Heavy: ", screenStates, memStates,
+ new int[] {STATE_HOME}, now, totalTime, true);
dumpProcessSummaryDetails(pw, prefix, " (Home): ", screenStates, memStates,
new int[] {STATE_HOME}, now, totalTime, true);
dumpProcessSummaryDetails(pw, prefix, " (Last Act): ", screenStates, memStates,
@@ -897,6 +906,12 @@
DebugUtils.printSizeValue(pw, getPssUssAverage(bucket) * 1024);
pw.print(" ");
DebugUtils.printSizeValue(pw, getPssUssMaximum(bucket) * 1024);
+ pw.print(" / ");
+ DebugUtils.printSizeValue(pw, getPssRssMinimum(bucket) * 1024);
+ pw.print(" ");
+ DebugUtils.printSizeValue(pw, getPssRssAverage(bucket) * 1024);
+ pw.print(" ");
+ DebugUtils.printSizeValue(pw, getPssRssMaximum(bucket) * 1024);
pw.println();
}
}
@@ -969,7 +984,8 @@
public void computeProcessData(ProcessStats.ProcessDataCollection data, long now) {
data.totalTime = 0;
data.numPss = data.minPss = data.avgPss = data.maxPss =
- data.minUss = data.avgUss = data.maxUss = 0;
+ data.minUss = data.avgUss = data.maxUss =
+ data.minRss = data.avgRss = data.maxRss = 0;
for (int is=0; is<data.screenStates.length; is++) {
for (int im=0; im<data.memStates.length; im++) {
for (int ip=0; ip<data.procStates.length; ip++) {
@@ -984,6 +1000,9 @@
long minUss = getPssUssMinimum(bucket);
long avgUss = getPssUssAverage(bucket);
long maxUss = getPssUssMaximum(bucket);
+ long minRss = getPssRssMinimum(bucket);
+ long avgRss = getPssRssAverage(bucket);
+ long maxRss = getPssRssMaximum(bucket);
if (data.numPss == 0) {
data.minPss = minPss;
data.avgPss = avgPss;
@@ -991,6 +1010,9 @@
data.minUss = minUss;
data.avgUss = avgUss;
data.maxUss = maxUss;
+ data.minRss = minRss;
+ data.avgRss = avgRss;
+ data.maxRss = maxRss;
} else {
if (minPss < data.minPss) {
data.minPss = minPss;
@@ -1008,6 +1030,14 @@
if (maxUss > data.maxUss) {
data.maxUss = maxUss;
}
+ if (minRss < data.minRss) {
+ data.minRss = minRss;
+ }
+ data.avgRss = (long)( ((data.avgRss*(double)data.numPss)
+ + (avgRss*(double)samples)) / (data.numPss+samples) );
+ if (maxRss > data.maxRss) {
+ data.maxRss = maxRss;
+ }
}
data.numPss += samples;
}
@@ -1176,6 +1206,12 @@
pw.print(mPssTable.getValue(key, PSS_USS_AVERAGE));
pw.print(':');
pw.print(mPssTable.getValue(key, PSS_USS_MAXIMUM));
+ pw.print(':');
+ pw.print(mPssTable.getValue(key, PSS_RSS_MINIMUM));
+ pw.print(':');
+ pw.print(mPssTable.getValue(key, PSS_RSS_AVERAGE));
+ pw.print(':');
+ pw.print(mPssTable.getValue(key, PSS_RSS_MAXIMUM));
}
}
@@ -1191,7 +1227,9 @@
return sb.toString();
}
- public void toProto(ProtoOutputStream proto, String procName, int uid, long now) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId,
+ String procName, int uid, long now) {
+ final long token = proto.start(fieldId);
proto.write(ProcessStatsProto.PROCESS, procName);
proto.write(ProcessStatsProto.UID, uid);
if (mNumExcessiveCpu > 0 || mNumCachedKill > 0 ) {
@@ -1247,6 +1285,10 @@
mPssTable.getValue(key, PSS_USS_MINIMUM),
mPssTable.getValue(key, PSS_USS_AVERAGE),
mPssTable.getValue(key, PSS_USS_MAXIMUM));
+ ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.RSS,
+ mPssTable.getValue(key, PSS_RSS_MINIMUM),
+ mPssTable.getValue(key, PSS_RSS_AVERAGE),
+ mPssTable.getValue(key, PSS_RSS_MAXIMUM));
proto.end(stateToken);
}
@@ -1261,5 +1303,6 @@
proto.write(ProcessStatsProto.State.DURATION_MS, entry.getValue());
proto.end(stateToken);
}
+ proto.end(token);
}
}
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 35b2dd2..d35bddd 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -27,7 +27,6 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
-import android.util.Log;
import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -35,16 +34,8 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.app.ProcessMap;
-import com.android.internal.app.procstats.DurationsTable;
-import com.android.internal.app.procstats.ProcessState;
-import com.android.internal.app.procstats.PssTable;
-import com.android.internal.app.procstats.ServiceState;
-import com.android.internal.app.procstats.SparseMappingTable;
-import com.android.internal.app.procstats.SysMemUsageTable;
-import com.android.internal.app.procstats.DumpUtils.*;
import dalvik.system.VMRuntime;
-import libcore.util.EmptyArray;
import java.io.BufferedReader;
import java.io.FileReader;
@@ -54,7 +45,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Comparator;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
@@ -99,7 +89,10 @@
public static final int PSS_USS_MINIMUM = 4;
public static final int PSS_USS_AVERAGE = 5;
public static final int PSS_USS_MAXIMUM = 6;
- public static final int PSS_COUNT = PSS_USS_MAXIMUM+1;
+ public static final int PSS_RSS_MINIMUM = 7;
+ public static final int PSS_RSS_AVERAGE = 8;
+ public static final int PSS_RSS_MAXIMUM = 9;
+ public static final int PSS_COUNT = PSS_RSS_MAXIMUM+1;
public static final int SYS_MEM_USAGE_SAMPLE_COUNT = 0;
public static final int SYS_MEM_USAGE_CACHED_MINIMUM = 1;
@@ -134,9 +127,11 @@
public static final int FLAG_SHUTDOWN = 1<<1;
public static final int FLAG_SYSPROPS = 1<<2;
- public static final int ADD_PSS_INTERNAL = 0;
- public static final int ADD_PSS_EXTERNAL = 1;
- public static final int ADD_PSS_EXTERNAL_SLOW = 2;
+ public static final int ADD_PSS_INTERNAL_SINGLE = 0;
+ public static final int ADD_PSS_INTERNAL_ALL_MEM = 1;
+ public static final int ADD_PSS_INTERNAL_ALL_POLL = 2;
+ public static final int ADD_PSS_EXTERNAL = 3;
+ public static final int ADD_PSS_EXTERNAL_SLOW = 4;
public static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL,
ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL };
@@ -162,7 +157,7 @@
};
// Current version of the parcel format.
- private static final int PARCEL_VERSION = 24;
+ private static final int PARCEL_VERSION = 27;
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0x50535454;
@@ -187,9 +182,17 @@
boolean mHasSwappedOutPss;
- // Count and total time expended doing "quick" pss computations for internal use.
- public long mInternalPssCount;
- public long mInternalPssTime;
+ // Count and total time expended doing "quick" single pss computations for internal use.
+ public long mInternalSinglePssCount;
+ public long mInternalSinglePssTime;
+
+ // Count and total time expended doing "quick" all mem pss computations for internal use.
+ public long mInternalAllMemPssCount;
+ public long mInternalAllMemPssTime;
+
+ // Count and total time expended doing "quick" all poll pss computations for internal use.
+ public long mInternalAllPollPssCount;
+ public long mInternalAllPollPssTime;
// Count and total time expended doing "quick" pss computations due to external requests.
public long mExternalPssCount;
@@ -318,8 +321,12 @@
mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime;
mTimePeriodEndUptime += other.mTimePeriodEndUptime - other.mTimePeriodStartUptime;
- mInternalPssCount += other.mInternalPssCount;
- mInternalPssTime += other.mInternalPssTime;
+ mInternalSinglePssCount += other.mInternalSinglePssCount;
+ mInternalSinglePssTime += other.mInternalSinglePssTime;
+ mInternalAllMemPssCount += other.mInternalAllMemPssCount;
+ mInternalAllMemPssTime += other.mInternalAllMemPssTime;
+ mInternalAllPollPssCount += other.mInternalAllPollPssCount;
+ mInternalAllPollPssTime += other.mInternalAllPollPssTime;
mExternalPssCount += other.mExternalPssCount;
mExternalPssTime += other.mExternalPssTime;
mExternalSlowPssCount += other.mExternalSlowPssCount;
@@ -523,8 +530,12 @@
buildTimePeriodStartClockStr();
mTimePeriodStartRealtime = mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
mTimePeriodStartUptime = mTimePeriodEndUptime = SystemClock.uptimeMillis();
- mInternalPssCount = 0;
- mInternalPssTime = 0;
+ mInternalSinglePssCount = 0;
+ mInternalSinglePssTime = 0;
+ mInternalAllMemPssCount = 0;
+ mInternalAllMemPssTime = 0;
+ mInternalAllPollPssCount = 0;
+ mInternalAllPollPssTime = 0;
mExternalPssCount = 0;
mExternalPssTime = 0;
mExternalSlowPssCount = 0;
@@ -789,8 +800,12 @@
out.writeLong(mTimePeriodEndRealtime);
out.writeLong(mTimePeriodStartUptime);
out.writeLong(mTimePeriodEndUptime);
- out.writeLong(mInternalPssCount);
- out.writeLong(mInternalPssTime);
+ out.writeLong(mInternalSinglePssCount);
+ out.writeLong(mInternalSinglePssTime);
+ out.writeLong(mInternalAllMemPssCount);
+ out.writeLong(mInternalAllMemPssTime);
+ out.writeLong(mInternalAllPollPssCount);
+ out.writeLong(mInternalAllPollPssTime);
out.writeLong(mExternalPssCount);
out.writeLong(mExternalPssTime);
out.writeLong(mExternalSlowPssCount);
@@ -963,8 +978,12 @@
mTimePeriodEndRealtime = in.readLong();
mTimePeriodStartUptime = in.readLong();
mTimePeriodEndUptime = in.readLong();
- mInternalPssCount = in.readLong();
- mInternalPssTime = in.readLong();
+ mInternalSinglePssCount = in.readLong();
+ mInternalSinglePssTime = in.readLong();
+ mInternalAllMemPssCount = in.readLong();
+ mInternalAllMemPssTime = in.readLong();
+ mInternalAllPollPssCount = in.readLong();
+ mInternalAllPollPssTime = in.readLong();
mExternalPssCount = in.readLong();
mExternalPssTime = in.readLong();
mExternalSlowPssCount = in.readLong();
@@ -1526,10 +1545,20 @@
totalMem.processStateSamples[STATE_SERVICE_RESTARTING]);
pw.println();
pw.println("PSS collection stats:");
- pw.print(" Internal: ");
- pw.print(mInternalPssCount);
+ pw.print(" Internal Single: ");
+ pw.print(mInternalSinglePssCount);
pw.print("x over ");
- TimeUtils.formatDuration(mInternalPssTime, pw);
+ TimeUtils.formatDuration(mInternalSinglePssTime, pw);
+ pw.println();
+ pw.print(" Internal All Procs (Memory Change): ");
+ pw.print(mInternalAllMemPssCount);
+ pw.print("x over ");
+ TimeUtils.formatDuration(mInternalAllMemPssTime, pw);
+ pw.println();
+ pw.print(" Internal All Procs (Polling): ");
+ pw.print(mInternalAllPollPssCount);
+ pw.print("x over ");
+ TimeUtils.formatDuration(mInternalAllPollPssTime, pw);
pw.println();
pw.print(" External: ");
pw.print(mExternalPssCount);
@@ -1776,10 +1805,11 @@
}
}
- public void toProto(ProtoOutputStream proto, long now) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId, long now) {
final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
mPackages.getMap();
+ final long token = proto.start(fieldId);
proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime);
proto.write(ProcessStatsSectionProto.END_REALTIME_MS,
mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
@@ -1811,11 +1841,10 @@
for (int iu=0; iu<uids.size(); iu++) {
final int uid = uids.keyAt(iu);
final ProcessState procState = uids.valueAt(iu);
- final long processStateToken = proto.start(ProcessStatsSectionProto.PROCESS_STATS);
- procState.toProto(proto, procName, uid, now);
- proto.end(processStateToken);
+ procState.writeToProto(proto, ProcessStatsSectionProto.PROCESS_STATS, procName, uid, now);
}
}
+ proto.end(token);
}
final public static class ProcessStateHolder {
@@ -1854,6 +1883,9 @@
public long minUss;
public long avgUss;
public long maxUss;
+ public long minRss;
+ public long avgRss;
+ public long maxRss;
public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
screenStates = _screenStates;
@@ -1879,6 +1911,12 @@
DebugUtils.printSizeValue(pw, avgUss * 1024);
pw.print("-");
DebugUtils.printSizeValue(pw, maxUss * 1024);
+ pw.print("/");
+ DebugUtils.printSizeValue(pw, minRss * 1024);
+ pw.print("-");
+ DebugUtils.printSizeValue(pw, avgRss * 1024);
+ pw.print("-");
+ DebugUtils.printSizeValue(pw, maxRss * 1024);
if (full) {
pw.print(" over ");
pw.print(numPss);
diff --git a/core/java/com/android/internal/app/procstats/PssTable.java b/core/java/com/android/internal/app/procstats/PssTable.java
index de5f673..1e7c566 100644
--- a/core/java/com/android/internal/app/procstats/PssTable.java
+++ b/core/java/com/android/internal/app/procstats/PssTable.java
@@ -16,6 +16,9 @@
package com.android.internal.app.procstats;
+import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_AVERAGE;
+import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MAXIMUM;
+import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MINIMUM;
import static com.android.internal.app.procstats.ProcessStats.PSS_SAMPLE_COUNT;
import static com.android.internal.app.procstats.ProcessStats.PSS_MINIMUM;
import static com.android.internal.app.procstats.ProcessStats.PSS_AVERAGE;
@@ -51,7 +54,10 @@
that.getValue(key, PSS_MAXIMUM),
that.getValue(key, PSS_USS_MINIMUM),
that.getValue(key, PSS_USS_AVERAGE),
- that.getValue(key, PSS_USS_MAXIMUM));
+ that.getValue(key, PSS_USS_MAXIMUM),
+ that.getValue(key, PSS_RSS_MINIMUM),
+ that.getValue(key, PSS_RSS_AVERAGE),
+ that.getValue(key, PSS_RSS_MAXIMUM));
}
}
@@ -60,7 +66,7 @@
* one and the new one, the average will now incorporate the new average, etc.
*/
public void mergeStats(int state, int inCount, long minPss, long avgPss, long maxPss,
- long minUss, long avgUss, long maxUss) {
+ long minUss, long avgUss, long maxUss, long minRss, long avgRss, long maxRss) {
final int key = getOrAddKey((byte)state, PSS_COUNT);
final long count = getValue(key, PSS_SAMPLE_COUNT);
if (count == 0) {
@@ -71,6 +77,9 @@
setValue(key, PSS_USS_MINIMUM, minUss);
setValue(key, PSS_USS_AVERAGE, avgUss);
setValue(key, PSS_USS_MAXIMUM, maxUss);
+ setValue(key, PSS_RSS_MINIMUM, minRss);
+ setValue(key, PSS_RSS_AVERAGE, avgRss);
+ setValue(key, PSS_RSS_MAXIMUM, maxRss);
} else {
setValue(key, PSS_SAMPLE_COUNT, count + inCount);
@@ -103,6 +112,20 @@
if (val < maxUss) {
setValue(key, PSS_USS_MAXIMUM, maxUss);
}
+
+ val = getValue(key, PSS_RSS_MINIMUM);
+ if (val > minUss) {
+ setValue(key, PSS_RSS_MINIMUM, minUss);
+ }
+
+ val = getValue(key, PSS_RSS_AVERAGE);
+ setValue(key, PSS_RSS_AVERAGE,
+ (long)(((val*(double)count)+(avgUss*(double)inCount)) / (count+inCount)));
+
+ val = getValue(key, PSS_RSS_MAXIMUM);
+ if (val < maxUss) {
+ setValue(key, PSS_RSS_MAXIMUM, maxUss);
+ }
}
}
}
diff --git a/core/java/com/android/internal/logging/EventLogTags.logtags b/core/java/com/android/internal/logging/EventLogTags.logtags
index a440ee4..693bd16 100644
--- a/core/java/com/android/internal/logging/EventLogTags.logtags
+++ b/core/java/com/android/internal/logging/EventLogTags.logtags
@@ -13,3 +13,6 @@
# LatencyTracker.java
# ---------------------------
36070 sysui_latency (action|1|6),(latency|1|3)
+
+# Generic event for logging when we write system files.
+525000 commit_sys_config_file (name|3),(time|2|3)
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index ee3bec8..7def876 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -41,9 +41,11 @@
import android.os.IBatteryPropertiesRegistrar;
import android.os.Looper;
import android.os.Message;
+import android.os.OsProtoEnums;
import android.os.Parcel;
import android.os.ParcelFormatException;
import android.os.Parcelable;
+import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -4252,11 +4254,11 @@
getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
if (wc != null) {
- StatsLog.write(
- StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(), type, name, 1);
+ StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
+ getPowerManagerWakeLockLevel(type), name, 1);
} else {
- StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null, type, name,
- 1);
+ StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
+ getPowerManagerWakeLockLevel(type), name, 1);
}
}
}
@@ -4295,15 +4297,45 @@
getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
if (wc != null) {
- StatsLog.write(
- StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(), type, name, 0);
+ StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(),
+ getPowerManagerWakeLockLevel(type), name, 0);
} else {
- StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null, type, name,
- 0);
+ StatsLog.write_non_chained(StatsLog.WAKELOCK_STATE_CHANGED, uid, null,
+ getPowerManagerWakeLockLevel(type), name, 0);
}
}
}
+ /**
+ * Converts BatteryStats wakelock types back into PowerManager wakelock levels.
+ * This is the inverse map of Notifier.getBatteryStatsWakeLockMonitorType().
+ * These are estimations, since batterystats loses some of the original data.
+ * TODO: Delete this. Instead, StatsLog.write should be called from PowerManager's Notifier.
+ */
+ private int getPowerManagerWakeLockLevel(int battertStatsWakelockType) {
+ switch (battertStatsWakelockType) {
+ // PowerManager.PARTIAL_WAKE_LOCK or PROXIMITY_SCREEN_OFF_WAKE_LOCK
+ case BatteryStats.WAKE_TYPE_PARTIAL:
+ return PowerManager.PARTIAL_WAKE_LOCK;
+
+ // PowerManager.SCREEN_DIM_WAKE_LOCK or SCREEN_BRIGHT_WAKE_LOCK
+ case BatteryStats.WAKE_TYPE_FULL:
+ return PowerManager.FULL_WAKE_LOCK;
+
+ case BatteryStats.WAKE_TYPE_DRAW:
+ return PowerManager.DRAW_WAKE_LOCK;
+
+ // It appears that nothing can ever make a Window and PowerManager lacks an equivalent.
+ case BatteryStats.WAKE_TYPE_WINDOW:
+ Slog.e(TAG, "Illegal window wakelock type observed in batterystats.");
+ return -1;
+
+ default:
+ Slog.e(TAG, "Illegal wakelock type in batterystats: " + battertStatsWakelockType);
+ return -1;
+ }
+ }
+
public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type, boolean unimportantForLogging) {
final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -10137,6 +10169,7 @@
updateDailyDeadlineLocked();
if (hasData) {
+ final long startTime = SystemClock.uptimeMillis();
mDailyItems.add(item);
while (mDailyItems.size() > MAX_DAILY_ITEMS) {
mDailyItems.remove(0);
@@ -10146,10 +10179,12 @@
XmlSerializer out = new FastXmlSerializer();
out.setOutput(memStream, StandardCharsets.UTF_8.name());
writeDailyItemsLocked(out);
+ final long initialTime = SystemClock.uptimeMillis() - startTime;
BackgroundThread.getHandler().post(new Runnable() {
@Override
public void run() {
synchronized (mCheckinFile) {
+ final long startTime2 = SystemClock.uptimeMillis();
FileOutputStream stream = null;
try {
stream = mDailyFile.startWrite();
@@ -10158,6 +10193,9 @@
FileUtils.sync(stream);
stream.close();
mDailyFile.finishWrite(stream);
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "batterystats-daily",
+ initialTime + SystemClock.uptimeMillis() - startTime2);
} catch (IOException e) {
Slog.w("BatteryStats",
"Error writing battery daily items", e);
@@ -10858,7 +10896,7 @@
return null;
}
- /**
+ /**
* Distribute WiFi energy info and network traffic to apps.
* @param info The energy information from the WiFi controller.
*/
@@ -11122,6 +11160,9 @@
}
}
+ private ModemActivityInfo mLastModemActivityInfo =
+ new ModemActivityInfo(0, 0, 0, new int[0], 0, 0);
+
/**
* Distribute Cell radio energy info and network traffic to apps.
*/
@@ -11142,6 +11183,22 @@
}
}
+ int rxTimeMs = 0;
+ int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
+ int idleTimeMs = 0;
+ int sleepTimeMs = 0;
+ if (activityInfo != null) {
+ rxTimeMs = activityInfo.getRxTimeMillis() - mLastModemActivityInfo.getRxTimeMillis();
+ for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
+ txTimeMs[i] = activityInfo.getTxTimeMillis()[i]
+ - mLastModemActivityInfo.getTxTimeMillis()[i];
+ }
+ idleTimeMs =
+ activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis();
+ sleepTimeMs =
+ activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis();
+ }
+
synchronized (this) {
if (!mOnBatteryInternal) {
if (delta != null) {
@@ -11153,11 +11210,11 @@
if (activityInfo != null) {
mHasModemReporting = true;
mModemActivity.getIdleTimeCounter().addCountLocked(
- activityInfo.getIdleTimeMillis());
- mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
+ idleTimeMs);
+ mModemActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
mModemActivity.getTxTimeCounters()[lvl]
- .addCountLocked(activityInfo.getTxTimeMillis()[lvl]);
+ .addCountLocked(txTimeMs[lvl]);
}
// POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
@@ -11165,16 +11222,15 @@
PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
if (opVolt != 0) {
double energyUsed =
- activityInfo.getSleepTimeMillis() *
+ sleepTimeMs *
mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
- + activityInfo.getIdleTimeMillis() *
+ + idleTimeMs *
mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
- + activityInfo.getRxTimeMillis() *
+ + rxTimeMs *
mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
- int[] txCurrentMa = activityInfo.getTxTimeMillis();
- for (int i = 0; i < Math.min(txCurrentMa.length,
+ for (int i = 0; i < Math.min(txTimeMs.length,
SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
- energyUsed += txCurrentMa[i] * mPowerProfile.getAveragePower(
+ energyUsed += txTimeMs[i] * mPowerProfile.getAveragePower(
PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
}
@@ -11255,7 +11311,7 @@
ControllerActivityCounterImpl activityCounter =
u.getOrCreateModemControllerActivityLocked();
if (totalRxPackets > 0 && entry.rxPackets > 0) {
- final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
+ final long rxMs = (entry.rxPackets * rxTimeMs)
/ totalRxPackets;
activityCounter.getRxTimeCounter().addCountLocked(rxMs);
}
@@ -11263,7 +11319,7 @@
if (totalTxPackets > 0 && entry.txPackets > 0) {
for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
long txMs =
- entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
+ entry.txPackets * txTimeMs[lvl];
txMs /= totalTxPackets;
activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
}
@@ -11284,6 +11340,10 @@
}
}
+ // Cache last value for comparison.
+ private BluetoothActivityEnergyInfo mLastBluetoothActivityEnergyInfo =
+ new BluetoothActivityEnergyInfo(0, 0, 0, 0, 0, 0);
+
/**
* Distribute Bluetooth energy info and network traffic to apps.
* @param info The energy information from the bluetooth controller.
@@ -11300,14 +11360,17 @@
mHasBluetoothReporting = true;
final long elapsedRealtimeMs = mClocks.elapsedRealtime();
- final long rxTimeMs = info.getControllerRxTimeMillis();
- final long txTimeMs = info.getControllerTxTimeMillis();
-
+ final long rxTimeMs = info.getControllerRxTimeMillis() -
+ mLastBluetoothActivityEnergyInfo.getControllerRxTimeMillis();
+ final long txTimeMs = info.getControllerTxTimeMillis() -
+ mLastBluetoothActivityEnergyInfo.getControllerTxTimeMillis();
+ final long idleTimeMs = info.getControllerIdleTimeMillis() -
+ mLastBluetoothActivityEnergyInfo.getControllerIdleTimeMillis();
if (DEBUG_ENERGY) {
Slog.d(TAG, "------ BEGIN BLE power blaming ------");
Slog.d(TAG, " Tx Time: " + txTimeMs + " ms");
Slog.d(TAG, " Rx Time: " + rxTimeMs + " ms");
- Slog.d(TAG, " Idle Time: " + info.getControllerIdleTimeMillis() + " ms");
+ Slog.d(TAG, " Idle Time: " + idleTimeMs + " ms");
}
long totalScanTimeMs = 0;
@@ -11386,9 +11449,25 @@
long totalRxBytes = 0;
final UidTraffic[] uidTraffic = info.getUidTraffic();
- final int numUids = uidTraffic != null ? uidTraffic.length : 0;
- for (int i = 0; i < numUids; i++) {
- final UidTraffic traffic = uidTraffic[i];
+ final UidTraffic[] lastUidTraffic = mLastBluetoothActivityEnergyInfo.getUidTraffic();
+ final ArrayList<UidTraffic> deltaTraffic = new ArrayList<>();
+ int m = 0, n = 0;
+ for (; m < uidTraffic.length && n < lastUidTraffic.length; m++) {
+ final UidTraffic traffic = uidTraffic[m];
+ final UidTraffic lastTraffic = lastUidTraffic[n];
+ if (traffic.getUid() == lastTraffic.getUid()) {
+ deltaTraffic.add(new UidTraffic(traffic.getUid(),
+ traffic.getRxBytes() - lastTraffic.getRxBytes(),
+ traffic.getTxBytes() - lastTraffic.getTxBytes()));
+ n++;
+ }
+ }
+ for (; m < uidTraffic.length; m ++) {
+ deltaTraffic.add(uidTraffic[m]);
+ }
+
+ for (int i = 0, j = 0; i < deltaTraffic.size(); i++) {
+ final UidTraffic traffic = deltaTraffic.get(i);
// Add to the global counters.
mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(
@@ -11408,8 +11487,8 @@
if ((totalTxBytes != 0 || totalRxBytes != 0) &&
(leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) {
- for (int i = 0; i < numUids; i++) {
- final UidTraffic traffic = uidTraffic[i];
+ for (int i = 0; i < deltaTraffic.size(); i++) {
+ final UidTraffic traffic = deltaTraffic.get(i);
final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
final ControllerActivityCounterImpl counter =
@@ -11440,12 +11519,9 @@
}
}
- mBluetoothActivity.getRxTimeCounter().addCountLocked(
- info.getControllerRxTimeMillis());
- mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(
- info.getControllerTxTimeMillis());
- mBluetoothActivity.getIdleTimeCounter().addCountLocked(
- info.getControllerIdleTimeMillis());
+ mBluetoothActivity.getRxTimeCounter().addCountLocked(rxTimeMs);
+ mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(txTimeMs);
+ mBluetoothActivity.getIdleTimeCounter().addCountLocked(idleTimeMs);
// POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
final double opVolt = mPowerProfile.getAveragePower(
@@ -11453,8 +11529,10 @@
if (opVolt != 0) {
// We store the power drain as mAms.
mBluetoothActivity.getPowerCounter().addCountLocked(
- (long) (info.getControllerEnergyUsed() / opVolt));
+ (long) ((info.getControllerEnergyUsed() -
+ mLastBluetoothActivityEnergyInfo.getControllerEnergyUsed() )/ opVolt));
}
+ mLastBluetoothActivityEnergyInfo = info;
}
/**
@@ -12074,11 +12152,14 @@
// stats to be reported in the next checkin. Only do this if we have
// a sufficient amount of data to make it interesting.
if (getLowDischargeAmountSinceCharge() >= 20) {
+ final long startTime = SystemClock.uptimeMillis();
final Parcel parcel = Parcel.obtain();
writeSummaryToParcel(parcel, true);
+ final long initialTime = SystemClock.uptimeMillis() - startTime;
BackgroundThread.getHandler().post(new Runnable() {
@Override public void run() {
synchronized (mCheckinFile) {
+ final long startTime2 = SystemClock.uptimeMillis();
FileOutputStream stream = null;
try {
stream = mCheckinFile.startWrite();
@@ -12087,6 +12168,9 @@
FileUtils.sync(stream);
stream.close();
mCheckinFile.finishWrite(stream);
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "batterystats-checkin",
+ initialTime + SystemClock.uptimeMillis() - startTime2);
} catch (IOException e) {
Slog.w("BatteryStats",
"Error writing checkin battery statistics", e);
@@ -12215,7 +12299,7 @@
}
// This should probably be exposed in the API, though it's not critical
- public static final int BATTERY_PLUGGED_NONE = 0;
+ public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
public void setBatteryStateLocked(final int status, final int health, final int plugType,
final int level, /* not final */ int temp, final int volt, final int chargeUAh,
@@ -13089,12 +13173,15 @@
mWriteLock.lock();
try {
+ final long startTime = SystemClock.uptimeMillis();
FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
stream.write(next.marshall());
stream.flush();
FileUtils.sync(stream);
stream.close();
mFile.commit();
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "batterystats", SystemClock.uptimeMillis() - startTime);
} catch (IOException e) {
Slog.w("BatteryStats", "Error writing battery statistics", e);
mFile.rollback();
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 95bc352..eadefc9 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -86,6 +86,7 @@
import android.widget.FrameLayout;
import android.widget.PopupWindow;
+import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -2216,7 +2217,7 @@
elevation = dipToPx(elevation);
mElevationAdjustedForStack = true;
} else if (windowingMode == WINDOWING_MODE_PINNED) {
- elevation = dipToPx(DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP);
+ elevation = dipToPx(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP);
mElevationAdjustedForStack = true;
} else {
mElevationAdjustedForStack = false;
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index ebb5f9f..f70d3c2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -132,6 +132,12 @@
void clickQsTile(in ComponentName tile);
void handleSystemKey(in int key);
+ /**
+ * Methods to show toast messages for screen pinning
+ */
+ void showPinningEnterExitToast(boolean entering);
+ void showPinningEscapeToast();
+
void showShutdownUi(boolean isReboot, String reason);
// Used to show the dialog when FingerprintService starts authentication
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index cb0b53c..adf4287 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -81,6 +81,12 @@
void clickTile(in ComponentName tile);
void handleSystemKey(in int key);
+ /**
+ * Methods to show toast messages for screen pinning
+ */
+ void showPinningEnterExitToast(boolean entering);
+ void showPinningEscapeToast();
+
// Used to show the dialog when FingerprintService starts authentication
void showFingerprintDialog(in Bundle bundle, IFingerprintDialogReceiver receiver);
// Used to hide the dialog when a finger is authenticated
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index 2f2c747..433d14f 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -138,14 +138,14 @@
public static @NonNull <I, O> List<O> mapNotNull(@Nullable List<I> cur,
Function<? super I, ? extends O> f) {
if (isEmpty(cur)) return Collections.emptyList();
- final ArrayList<O> result = new ArrayList<>();
+ List<O> result = null;
for (int i = 0; i < cur.size(); i++) {
O transformed = f.apply(cur.get(i));
if (transformed != null) {
- result.add(transformed);
+ result = add(result, transformed);
}
}
- return result;
+ return emptyIfNull(result);
}
/**
diff --git a/core/java/com/android/internal/util/ObjectUtils.java b/core/java/com/android/internal/util/ObjectUtils.java
index 379602a..59e5a64 100644
--- a/core/java/com/android/internal/util/ObjectUtils.java
+++ b/core/java/com/android/internal/util/ObjectUtils.java
@@ -29,9 +29,6 @@
return a != null ? a : Preconditions.checkNotNull(b);
}
- /**
- * Compares two {@link Nullable} objects with {@code null} values considered the smallest
- */
public static <T extends Comparable> int compare(@Nullable T a, @Nullable T b) {
if (a != null) {
return (b != null) ? a.compareTo(b) : 1;
@@ -39,13 +36,4 @@
return (b != null) ? -1 : 0;
}
}
-
- /**
- * @return {@code null} if the given instance is not of the given calss, or the given
- * instance otherwise
- */
- @Nullable
- public static <S, T extends S> T castOrNull(@Nullable S instance, @NonNull Class<T> c) {
- return c.isInstance(instance) ? (T) instance : null;
- }
}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 927d757..5673814 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -64,7 +64,7 @@
// {@code ServiceSpecificException} may be thrown to signal an error, which caller can
// convert to {@code RecoveryManagerException}.
void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList);
- KeyChainSnapshot getRecoveryData(in byte[] account);
+ KeyChainSnapshot getKeyChainSnapshot();
byte[] generateAndStoreKey(String alias);
void removeKey(String alias);
void setSnapshotCreatedPendingIntent(in PendingIntent intent);
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 32a7a2d..7a248f2 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -118,6 +118,7 @@
private float mInProgressY = -1;
private long mAnimatingPeriodStart;
+ private long[] mLineFadeStart = new long[9];
private DisplayMode mPatternDisplayMode = DisplayMode.Correct;
private boolean mInputEnabled = true;
@@ -596,12 +597,14 @@
}
/**
- * Clear the pattern lookup table.
+ * Clear the pattern lookup table. Also reset the line fade start times for
+ * the next attempt.
*/
private void clearPatternDrawLookup() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
mPatternDrawLookup[i][j] = false;
+ mLineFadeStart[i+j] = 0;
}
}
}
@@ -1136,7 +1139,8 @@
boolean anyCircles = false;
float lastX = 0f;
float lastY = 0f;
- for (int i = 0; i < count; i++) {
+ long elapsedRealtime = SystemClock.elapsedRealtime();
+ for (int i = 0; i < count; i++) {
Cell cell = pattern.get(i);
// only draw the part of the pattern stored in
@@ -1147,16 +1151,26 @@
}
anyCircles = true;
+ if (mLineFadeStart[i] == 0) {
+ mLineFadeStart[i] = SystemClock.elapsedRealtime();
+ }
+
float centerX = getCenterXForColumn(cell.column);
float centerY = getCenterYForRow(cell.row);
if (i != 0) {
+ // Set this line segment to slowly fade over the next second.
+ int lineFadeVal = (int) Math.min((elapsedRealtime -
+ mLineFadeStart[i])/2f, 255f);
+
CellState state = mCellStates[cell.row][cell.column];
currentPath.rewind();
currentPath.moveTo(lastX, lastY);
if (state.lineEndX != Float.MIN_VALUE && state.lineEndY != Float.MIN_VALUE) {
currentPath.lineTo(state.lineEndX, state.lineEndY);
+ mPathPaint.setAlpha((int) 255 - lineFadeVal );
} else {
currentPath.lineTo(centerX, centerY);
+ mPathPaint.setAlpha((int) 255 - lineFadeVal );
}
canvas.drawPath(currentPath, mPathPaint);
}
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 6f2246a..7635a72 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -22,7 +22,9 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcel;
@@ -502,7 +504,7 @@
}
private void onCollapsedChanged(boolean isCollapsed) {
- notifyAccessibilityStateChanged(
+ notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
if (mScrollIndicatorDrawable != null) {
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 8848e393..fb18669 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -35,6 +35,7 @@
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.Slog;
+import android.util.StatsLog;
import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
@@ -85,7 +86,7 @@
private static final String LOG_FILES_FILE = "log-files.xml";
private static final AtomicFile sFile = new AtomicFile(new File(
- Environment.getDataSystemDirectory(), LOG_FILES_FILE));
+ Environment.getDataSystemDirectory(), LOG_FILES_FILE), "log-files");
private static final String LAST_HEADER_FILE = "last-header.txt";
private static final File lastHeaderFile = new File(
Environment.getDataSystemDirectory(), LAST_HEADER_FILE);
@@ -112,6 +113,8 @@
private static final String SHUTDOWN_METRICS_FILE = "/data/system/shutdown-metrics.txt";
private static final String SHUTDOWN_TRON_METRICS_PREFIX = "shutdown_";
+ private static final String METRIC_SYSTEM_SERVER = "shutdown_system_server";
+ private static final String METRIC_SHUTDOWN_TIME_START = "begin_shutdown";
@Override
public void onReceive(final Context context, Intent intent) {
@@ -401,6 +404,10 @@
}
}
if (!TextUtils.isEmpty(metricsStr)) {
+ String reboot = null;
+ String reason = null;
+ String start_time = null;
+ String duration = null;
String[] array = metricsStr.split(",");
for (String keyValueStr : array) {
String[] keyValue = keyValueStr.split(":");
@@ -411,8 +418,19 @@
// Ignore keys that are not indended for tron
if (keyValue[0].startsWith(SHUTDOWN_TRON_METRICS_PREFIX)) {
logTronShutdownMetric(keyValue[0], keyValue[1]);
+ if (keyValue[0].equals(METRIC_SYSTEM_SERVER)) {
+ duration = keyValue[1];
+ }
+ }
+ if (keyValue[0].equals("reboot")) {
+ reboot = keyValue[1];
+ } else if (keyValue[0].equals("reason")) {
+ reason = keyValue[1];
+ } else if (keyValue[0].equals(METRIC_SHUTDOWN_TIME_START)) {
+ start_time = keyValue[1];
}
}
+ logStatsdShutdownAtom(reboot, reason, start_time, duration);
}
metricsFile.delete();
}
@@ -430,6 +448,52 @@
}
}
+ private static void logStatsdShutdownAtom(
+ String rebootStr, String reasonStr, String startStr, String durationStr) {
+ boolean reboot = false;
+ String reason = "<EMPTY>";
+ long start = 0;
+ long duration = 0;
+
+ if (rebootStr != null) {
+ if (rebootStr.equals("y")) {
+ reboot = true;
+ } else if (!rebootStr.equals("n")) {
+ Slog.e(TAG, "Unexpected value for reboot : " + rebootStr);
+ }
+ } else {
+ Slog.e(TAG, "No value received for reboot");
+ }
+
+ if (reasonStr != null) {
+ reason = reasonStr;
+ } else {
+ Slog.e(TAG, "No value received for shutdown reason");
+ }
+
+ if (startStr != null) {
+ try {
+ start = Long.parseLong(startStr);
+ } catch (NumberFormatException e) {
+ Slog.e(TAG, "Cannot parse shutdown start time: " + startStr);
+ }
+ } else {
+ Slog.e(TAG, "No value received for shutdown start time");
+ }
+
+ if (durationStr != null) {
+ try {
+ duration = Long.parseLong(durationStr);
+ } catch (NumberFormatException e) {
+ Slog.e(TAG, "Cannot parse shutdown duration: " + startStr);
+ }
+ } else {
+ Slog.e(TAG, "No value received for shutdown duration");
+ }
+
+ StatsLog.write(StatsLog.SHUTDOWN_SEQUENCE_REPORTED, reboot, reason, start, duration);
+ }
+
private static void logFsShutdownTime() {
File f = null;
for (String fileName : LAST_KMSG_FILES) {
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index c5af897..111934f 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -149,6 +149,9 @@
final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
+ final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
+ final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
+
final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
public static SystemConfig getInstance() {
@@ -240,6 +243,14 @@
return mVendorPrivAppDenyPermissions.get(packageName);
}
+ public ArraySet<String> getProductPrivAppPermissions(String packageName) {
+ return mProductPrivAppPermissions.get(packageName);
+ }
+
+ public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
+ return mProductPrivAppDenyPermissions.get(packageName);
+ }
+
public Map<String, Boolean> getOemPermissions(String packageName) {
final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
if (oemPermissions != null) {
@@ -278,6 +289,14 @@
Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
+
+ // Allow Product to customize system configs around libs, features, permissions and apps
+ int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
+ ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
+ readPermissions(Environment.buildPath(
+ Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
+ readPermissions(Environment.buildPath(
+ Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
}
void readPermissions(File libraryDir, int permissionFlag) {
@@ -598,15 +617,20 @@
}
XmlUtils.skipCurrentTag(parser);
} else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
- // privapp permissions from system and vendor partitions are stored
+ // privapp permissions from system, vendor and product partitions are stored
// separately. This is to prevent xml files in the vendor partition from
// granting permissions to priv apps in the system partition and vice
// versa.
boolean vendor = permFile.toPath().startsWith(
Environment.getVendorDirectory().toPath());
+ boolean product = permFile.toPath().startsWith(
+ Environment.getProductDirectory().toPath());
if (vendor) {
readPrivAppPermissions(parser, mVendorPrivAppPermissions,
mVendorPrivAppDenyPermissions);
+ } else if (product) {
+ readPrivAppPermissions(parser, mProductPrivAppPermissions,
+ mProductPrivAppDenyPermissions);
} else {
readPrivAppPermissions(parser, mPrivAppPermissions,
mPrivAppDenyPermissions);
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 78a3e13..33f80ce 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -110,8 +110,8 @@
"android_util_AssetManager.cpp",
"android_util_Binder.cpp",
"android_util_EventLog.cpp",
- "android_util_Log.cpp",
"android_util_MemoryIntArray.cpp",
+ "android_util_Log.cpp",
"android_util_PathParser.cpp",
"android_util_Process.cpp",
"android_util_StringBlock.cpp",
@@ -191,7 +191,6 @@
"android_backup_FileBackupHelperBase.cpp",
"android_backup_BackupHelperDispatcher.cpp",
"android_app_backup_FullBackup.cpp",
- "android_content_res_ApkAssets.cpp",
"android_content_res_ObbScanner.cpp",
"android_content_res_Configuration.cpp",
"android_animation_PropertyValuesHolder.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 78be2fd..d202173 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -123,7 +123,6 @@
extern int register_android_util_PathParser(JNIEnv* env);
extern int register_android_content_StringBlock(JNIEnv* env);
extern int register_android_content_XmlBlock(JNIEnv* env);
-extern int register_android_content_res_ApkAssets(JNIEnv* env);
extern int register_android_graphics_Canvas(JNIEnv* env);
extern int register_android_graphics_CanvasProperty(JNIEnv* env);
extern int register_android_graphics_ColorFilter(JNIEnv* env);
@@ -767,18 +766,17 @@
/*
* Enable debugging only for apps forked from zygote.
- * Set suspend=y to pause during VM init and use android ADB transport.
*/
if (zygote) {
+ // Set the JDWP provider and required arguments. By default let the runtime choose how JDWP is
+ // implemented. When this is not set the runtime defaults to not allowing JDWP.
addOption("-XjdwpOptions:suspend=n,server=y");
+ parseRuntimeOption("dalvik.vm.jdwp-provider",
+ jdwpProviderBuf,
+ "-XjdwpProvider:",
+ "default");
}
- // Set the JDWP provider. By default let the runtime choose.
- parseRuntimeOption("dalvik.vm.jdwp-provider",
- jdwpProviderBuf,
- "-XjdwpProvider:",
- "default");
-
parseRuntimeOption("dalvik.vm.lockprof.threshold",
lockProfThresholdBuf,
"-Xlockprofthreshold:");
@@ -975,6 +973,12 @@
addOption("--generate-debug-info");
}
+ // The mini-debug-info makes it possible to backtrace through JIT code.
+ if (property_get_bool("dalvik.vm.minidebuginfo", 0)) {
+ addOption("-Xcompiler-option");
+ addOption("--generate-mini-debug-info");
+ }
+
/*
* Retrieve the build fingerprint and provide it to the runtime. That way, ANR dumps will
* contain the fingerprint and can be parsed.
@@ -1342,7 +1346,6 @@
REG_JNI(register_android_content_AssetManager),
REG_JNI(register_android_content_StringBlock),
REG_JNI(register_android_content_XmlBlock),
- REG_JNI(register_android_content_res_ApkAssets),
REG_JNI(register_android_text_AndroidCharacter),
REG_JNI(register_android_text_Hyphenator),
REG_JNI(register_android_text_MeasuredParagraph),
diff --git a/core/jni/android/graphics/AnimatedImageDrawable.cpp b/core/jni/android/graphics/AnimatedImageDrawable.cpp
index 262b553..c88cf5c 100644
--- a/core/jni/android/graphics/AnimatedImageDrawable.cpp
+++ b/core/jni/android/graphics/AnimatedImageDrawable.cpp
@@ -16,18 +16,20 @@
#include "GraphicsJNI.h"
#include "ImageDecoder.h"
+#include "Utils.h"
#include "core_jni_helpers.h"
-#include <hwui/AnimatedImageDrawable.h>
-#include <hwui/Canvas.h>
#include <SkAndroidCodec.h>
#include <SkAnimatedImage.h>
#include <SkColorFilter.h>
#include <SkPicture.h>
#include <SkPictureRecorder.h>
+#include <hwui/AnimatedImageDrawable.h>
+#include <hwui/Canvas.h>
using namespace android;
+static jmethodID gAnimatedImageDrawable_postOnAnimationEndMethodID;
// Note: jpostProcess holds a handle to the ImageDecoder.
static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/,
@@ -83,6 +85,9 @@
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&AnimatedImageDrawable_destruct));
}
+// Java's FINISHED relies on this being -1
+static_assert(SkAnimatedImage::kFinished == -1);
+
static jlong AnimatedImageDrawable_nDraw(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
jlong canvasPtr) {
auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
@@ -123,12 +128,55 @@
drawable->stop();
}
+// Java's LOOP_INFINITE relies on this being the same.
+static_assert(SkCodec::kRepetitionCountInfinite == -1);
+
+static void AnimatedImageDrawable_nSetLoopCount(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
+ jint loopCount) {
+ auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+ drawable->setRepetitionCount(loopCount);
+}
+
+class JniAnimationEndListener : public OnAnimationEndListener {
+public:
+ JniAnimationEndListener(JNIEnv* env, jobject javaObject) {
+ LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&mJvm) != JNI_OK);
+ mJavaObject = env->NewGlobalRef(javaObject);
+ }
+
+ ~JniAnimationEndListener() override {
+ auto* env = get_env_or_die(mJvm);
+ env->DeleteGlobalRef(mJavaObject);
+ }
+
+ void onAnimationEnd() override {
+ auto* env = get_env_or_die(mJvm);
+ env->CallVoidMethod(mJavaObject, gAnimatedImageDrawable_postOnAnimationEndMethodID);
+ }
+
+private:
+ JavaVM* mJvm;
+ jobject mJavaObject;
+};
+
+static void AnimatedImageDrawable_nSetOnAnimationEndListener(JNIEnv* env, jobject /*clazz*/,
+ jlong nativePtr, jobject jdrawable) {
+ auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+ drawable->setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener>(
+ new JniAnimationEndListener(env, jdrawable)));
+}
+
static long AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
// FIXME: Report the size of the internal SkBitmap etc.
return sizeof(drawable);
}
+static void AnimatedImageDrawable_nMarkInvisible(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+ auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
+ drawable->markInvisible();
+}
+
static const JNINativeMethod gAnimatedImageDrawableMethods[] = {
{ "nCreate", "(JLandroid/graphics/ImageDecoder;IILandroid/graphics/Rect;)J", (void*) AnimatedImageDrawable_nCreate },
{ "nGetNativeFinalizer", "()J", (void*) AnimatedImageDrawable_nGetNativeFinalizer },
@@ -139,10 +187,16 @@
{ "nIsRunning", "(J)Z", (void*) AnimatedImageDrawable_nIsRunning },
{ "nStart", "(J)Z", (void*) AnimatedImageDrawable_nStart },
{ "nStop", "(J)V", (void*) AnimatedImageDrawable_nStop },
+ { "nSetLoopCount", "(JI)V", (void*) AnimatedImageDrawable_nSetLoopCount },
+ { "nSetOnAnimationEndListener", "(JLandroid/graphics/drawable/AnimatedImageDrawable;)V", (void*) AnimatedImageDrawable_nSetOnAnimationEndListener },
{ "nNativeByteSize", "(J)J", (void*) AnimatedImageDrawable_nNativeByteSize },
+ { "nMarkInvisible", "(J)V", (void*) AnimatedImageDrawable_nMarkInvisible },
};
int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv* env) {
+ jclass animatedImageDrawable_class = FindClassOrDie(env, "android/graphics/drawable/AnimatedImageDrawable");
+ gAnimatedImageDrawable_postOnAnimationEndMethodID = GetMethodIDOrDie(env, animatedImageDrawable_class, "postOnAnimationEnd", "()V");
+
return android::RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedImageDrawable",
gAnimatedImageDrawableMethods, NELEM(gAnimatedImageDrawableMethods));
}
diff --git a/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp b/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp
index 85c9ef3..173818b 100644
--- a/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp
+++ b/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp
@@ -1,5 +1,6 @@
#include "ByteBufferStreamAdaptor.h"
#include "core_jni_helpers.h"
+#include "Utils.h"
#include <SkStream.h>
@@ -8,14 +9,6 @@
static jmethodID gByteBuffer_getMethodID;
static jmethodID gByteBuffer_setPositionMethodID;
-static JNIEnv* get_env_or_die(JavaVM* jvm) {
- JNIEnv* env;
- if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", jvm);
- }
- return env;
-}
-
class ByteBufferStream : public SkStreamAsset {
private:
ByteBufferStream(JavaVM* jvm, jobject jbyteBuffer, size_t initialPosition, size_t length,
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index 4257c98..7a9fea7 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -12,15 +12,6 @@
static jmethodID gInputStream_readMethodID;
static jmethodID gInputStream_skipMethodID;
-// FIXME: Share with ByteBufferStreamAdaptor.cpp?
-static JNIEnv* get_env_or_die(JavaVM* jvm) {
- JNIEnv* env;
- if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", jvm);
- }
- return env;
-}
-
/**
* Wrapper for a Java InputStream.
*/
@@ -57,13 +48,13 @@
}
~JavaInputStreamAdaptor() override {
- auto* env = get_env_or_die(fJvm);
+ auto* env = android::get_env_or_die(fJvm);
env->DeleteGlobalRef(fJavaInputStream);
env->DeleteGlobalRef(fJavaByteArray);
}
size_t read(void* buffer, size_t size) override {
- auto* env = get_env_or_die(fJvm);
+ auto* env = android::get_env_or_die(fJvm);
if (!fSwallowExceptions && checkException(env)) {
// Just in case the caller did not clear from a previous exception.
return 0;
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index c50026e..dd3e6f0 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -28,7 +28,7 @@
#include <nativehelper/ScopedUtfChars.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_util_AssetManager.h>
-#include <androidfw/AssetManager2.h>
+#include <androidfw/AssetManager.h>
#include "Utils.h"
#include "FontUtils.h"
@@ -224,8 +224,7 @@
NPE_CHECK_RETURN_ZERO(env, jpath);
NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-
- Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, jassetMgr);
+ AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
if (NULL == mgr) {
builder->axes.clear();
return false;
@@ -237,33 +236,27 @@
return false;
}
- std::unique_ptr<Asset> asset;
- {
- ScopedLock<AssetManager2> locked_mgr(*mgr);
- if (isAsset) {
- asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
- } else if (cookie > 0) {
- // Valid java cookies are 1-based, but AssetManager cookies are 0-based.
- asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1),
- Asset::ACCESS_BUFFER);
- } else {
- asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
- }
+ Asset* asset;
+ if (isAsset) {
+ asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+ } else {
+ asset = cookie ? mgr->openNonAsset(static_cast<int32_t>(cookie), str.c_str(),
+ Asset::ACCESS_BUFFER) : mgr->openNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
}
- if (nullptr == asset) {
+ if (NULL == asset) {
builder->axes.clear();
return false;
}
const void* buf = asset->getBuffer(false);
if (NULL == buf) {
+ delete asset;
builder->axes.clear();
return false;
}
- sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset,
- asset.release()));
+ sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset, asset));
return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
}
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index 743a7ef..e2ce1a4 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -74,7 +74,8 @@
// FIXME: Avoid parsing the whole image?
const bool animated = codec->getFrameCount() > 1;
- decoder->mCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
+ decoder->mCodec = SkAndroidCodec::MakeFromCodec(std::move(codec),
+ SkAndroidCodec::ExifOrientationBehavior::kRespect);
if (!decoder->mCodec.get()) {
doThrowIOE(env, "Could not create AndroidCodec");
return nullptr;
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 49cbb54..115d0d5 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -24,6 +24,7 @@
#include "core_jni_helpers.h"
#include <nativehelper/ScopedStringChars.h>
#include <nativehelper/ScopedUtfChars.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
#include "SkBlurDrawLooper.h"
#include "SkColorFilter.h"
@@ -515,11 +516,10 @@
jint start, jint end, jint contextStart, jint contextEnd, jboolean isRtl, jint offset) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
const Typeface* typeface = paint->getAndroidTypeface();
- jchar* textArray = (jchar*) env->GetPrimitiveArrayCritical(text, nullptr);
- jfloat result = doRunAdvance(paint, typeface, textArray + contextStart,
+ ScopedCharArrayRO textArray(env, text);
+ jfloat result = doRunAdvance(paint, typeface, textArray.get() + contextStart,
start - contextStart, end - start, contextEnd - contextStart, isRtl,
offset - contextStart);
- env->ReleasePrimitiveArrayCritical(text, textArray, JNI_ABORT);
return result;
}
@@ -537,11 +537,10 @@
jboolean isRtl, jfloat advance) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
const Typeface* typeface = paint->getAndroidTypeface();
- jchar* textArray = (jchar*) env->GetPrimitiveArrayCritical(text, nullptr);
- jint result = doOffsetForAdvance(paint, typeface, textArray + contextStart,
+ ScopedCharArrayRO textArray(env, text);
+ jint result = doOffsetForAdvance(paint, typeface, textArray.get() + contextStart,
start - contextStart, end - start, contextEnd - contextStart, isRtl, advance);
result += contextStart;
- env->ReleasePrimitiveArrayCritical(text, textArray, JNI_ABORT);
return result;
}
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
index 630220a..dd9bafe 100644
--- a/core/jni/android/graphics/Utils.cpp
+++ b/core/jni/android/graphics/Utils.cpp
@@ -117,3 +117,11 @@
bool android::isSeekable(int descriptor) {
return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
}
+
+JNIEnv* android::get_env_or_die(JavaVM* jvm) {
+ JNIEnv* env;
+ if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", jvm);
+ }
+ return env;
+}
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
index 69930a5..2f2ee96 100644
--- a/core/jni/android/graphics/Utils.h
+++ b/core/jni/android/graphics/Utils.h
@@ -74,6 +74,8 @@
*/
bool isSeekable(int descriptor);
+JNIEnv* get_env_or_die(JavaVM* jvm);
+
}; // namespace android
#endif // _ANDROID_GRAPHICS_UTILS_H_
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 49a24a3..09e37e1 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -361,7 +361,7 @@
code->sdkVersion = sdkVersion;
code->javaAssetManager = env->NewGlobalRef(jAssetMgr);
- code->assetManager = NdkAssetManagerForJavaObject(env, jAssetMgr);
+ code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
if (obbDir != NULL) {
dirStr = env->GetStringUTFChars(obbDir, NULL);
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
deleted file mode 100644
index c0f151b..0000000
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ /dev/null
@@ -1,150 +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.
- */
-
-#include "android-base/macros.h"
-#include "android-base/stringprintf.h"
-#include "android-base/unique_fd.h"
-#include "androidfw/ApkAssets.h"
-#include "utils/misc.h"
-
-#include "core_jni_helpers.h"
-#include "jni.h"
-#include "nativehelper/ScopedUtfChars.h"
-
-using ::android::base::unique_fd;
-
-namespace android {
-
-static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, jstring java_path, jboolean system,
- jboolean force_shared_lib, jboolean overlay) {
- ScopedUtfChars path(env, java_path);
- if (path.c_str() == nullptr) {
- return 0;
- }
-
- std::unique_ptr<const ApkAssets> apk_assets;
- if (overlay) {
- apk_assets = ApkAssets::LoadOverlay(path.c_str(), system);
- } else if (force_shared_lib) {
- apk_assets = ApkAssets::LoadAsSharedLibrary(path.c_str(), system);
- } else {
- apk_assets = ApkAssets::Load(path.c_str(), system);
- }
-
- if (apk_assets == nullptr) {
- std::string error_msg = base::StringPrintf("Failed to load asset path %s", path.c_str());
- jniThrowException(env, "java/io/IOException", error_msg.c_str());
- return 0;
- }
- return reinterpret_cast<jlong>(apk_assets.release());
-}
-
-static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, jobject file_descriptor,
- jstring friendly_name, jboolean system, jboolean force_shared_lib) {
- ScopedUtfChars friendly_name_utf8(env, friendly_name);
- if (friendly_name_utf8.c_str() == nullptr) {
- return 0;
- }
-
- int fd = jniGetFDFromFileDescriptor(env, file_descriptor);
- if (fd < 0) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "Bad FileDescriptor");
- return 0;
- }
-
- unique_fd dup_fd(::dup(fd));
- if (dup_fd < 0) {
- jniThrowIOException(env, errno);
- return 0;
- }
-
- std::unique_ptr<const ApkAssets> apk_assets = ApkAssets::LoadFromFd(std::move(dup_fd),
- friendly_name_utf8.c_str(),
- system, force_shared_lib);
- if (apk_assets == nullptr) {
- std::string error_msg = base::StringPrintf("Failed to load asset path %s from fd %d",
- friendly_name_utf8.c_str(), dup_fd.get());
- jniThrowException(env, "java/io/IOException", error_msg.c_str());
- return 0;
- }
- return reinterpret_cast<jlong>(apk_assets.release());
-}
-
-static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
- delete reinterpret_cast<ApkAssets*>(ptr);
-}
-
-static jstring NativeGetAssetPath(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
- const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
- return env->NewStringUTF(apk_assets->GetPath().c_str());
-}
-
-static jlong NativeGetStringBlock(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
- const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
- return reinterpret_cast<jlong>(apk_assets->GetLoadedArsc()->GetStringPool());
-}
-
-static jboolean NativeIsUpToDate(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
- const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
- (void)apk_assets;
- return JNI_TRUE;
-}
-
-static jlong NativeOpenXml(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring file_name) {
- ScopedUtfChars path_utf8(env, file_name);
- if (path_utf8.c_str() == nullptr) {
- return 0;
- }
-
- const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
- std::unique_ptr<Asset> asset = apk_assets->Open(path_utf8.c_str(),
- Asset::AccessMode::ACCESS_RANDOM);
- if (asset == nullptr) {
- jniThrowException(env, "java/io/FileNotFoundException", path_utf8.c_str());
- return 0;
- }
-
- // DynamicRefTable is only needed when looking up resource references. Opening an XML file
- // directly from an ApkAssets has no notion of proper resource references.
- std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(nullptr /*dynamicRefTable*/);
- status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), true);
- asset.reset();
-
- if (err != NO_ERROR) {
- jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
- return 0;
- }
- return reinterpret_cast<jlong>(xml_tree.release());
-}
-
-// JNI registration.
-static const JNINativeMethod gApkAssetsMethods[] = {
- {"nativeLoad", "(Ljava/lang/String;ZZZ)J", (void*)NativeLoad},
- {"nativeLoadFromFd", "(Ljava/io/FileDescriptor;Ljava/lang/String;ZZ)J",
- (void*)NativeLoadFromFd},
- {"nativeDestroy", "(J)V", (void*)NativeDestroy},
- {"nativeGetAssetPath", "(J)Ljava/lang/String;", (void*)NativeGetAssetPath},
- {"nativeGetStringBlock", "(J)J", (void*)NativeGetStringBlock},
- {"nativeIsUpToDate", "(J)Z", (void*)NativeIsUpToDate},
- {"nativeOpenXml", "(JLjava/lang/String;)J", (void*)NativeOpenXml},
-};
-
-int register_android_content_res_ApkAssets(JNIEnv* env) {
- return RegisterMethodsOrDie(env, "android/content/res/ApkAssets", gApkAssetsMethods,
- arraysize(gApkAssetsMethods));
-}
-
-} // namespace android
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index 0d09b56..86cda44 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -519,8 +519,21 @@
(void*)nativeDispose },
{ "nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
(void*)nativeWriteToParcel },
+
{ "nativeGetName", "(J)Ljava/lang/String;",
(void*)nativeGetName },
+ { "nativeGetBlob", "(JII)[B",
+ (void*)nativeGetBlob },
+ { "nativeGetString", "(JII)Ljava/lang/String;",
+ (void*)nativeGetString },
+ { "nativeCopyStringToBuffer", "(JIILandroid/database/CharArrayBuffer;)V",
+ (void*)nativeCopyStringToBuffer },
+ { "nativePutBlob", "(J[BII)Z",
+ (void*)nativePutBlob },
+ { "nativePutString", "(JLjava/lang/String;II)Z",
+ (void*)nativePutString },
+
+ // ------- @FastNative below here ----------------------
{ "nativeClear", "(J)V",
(void*)nativeClear },
{ "nativeGetNumRows", "(J)I",
@@ -533,20 +546,11 @@
(void*)nativeFreeLastRow },
{ "nativeGetType", "(JII)I",
(void*)nativeGetType },
- { "nativeGetBlob", "(JII)[B",
- (void*)nativeGetBlob },
- { "nativeGetString", "(JII)Ljava/lang/String;",
- (void*)nativeGetString },
{ "nativeGetLong", "(JII)J",
(void*)nativeGetLong },
{ "nativeGetDouble", "(JII)D",
(void*)nativeGetDouble },
- { "nativeCopyStringToBuffer", "(JIILandroid/database/CharArrayBuffer;)V",
- (void*)nativeCopyStringToBuffer },
- { "nativePutBlob", "(J[BII)Z",
- (void*)nativePutBlob },
- { "nativePutString", "(JLjava/lang/String;II)Z",
- (void*)nativePutString },
+
{ "nativePutLong", "(JJII)Z",
(void*)nativePutLong },
{ "nativePutDouble", "(JDII)Z",
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index b9ff0a7..bf183cc 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -107,6 +107,7 @@
struct stat_fields {
jfieldID pss_field;
jfieldID pssSwappable_field;
+ jfieldID rss_field;
jfieldID privateDirty_field;
jfieldID sharedDirty_field;
jfieldID privateClean_field;
@@ -118,6 +119,7 @@
struct stat_field_names {
const char* pss_name;
const char* pssSwappable_name;
+ const char* rss_name;
const char* privateDirty_name;
const char* sharedDirty_name;
const char* privateClean_name;
@@ -129,11 +131,11 @@
static stat_fields stat_fields[_NUM_CORE_HEAP];
static stat_field_names stat_field_names[_NUM_CORE_HEAP] = {
- { "otherPss", "otherSwappablePss", "otherPrivateDirty", "otherSharedDirty",
+ { "otherPss", "otherSwappablePss", "otherRss", "otherPrivateDirty", "otherSharedDirty",
"otherPrivateClean", "otherSharedClean", "otherSwappedOut", "otherSwappedOutPss" },
- { "dalvikPss", "dalvikSwappablePss", "dalvikPrivateDirty", "dalvikSharedDirty",
+ { "dalvikPss", "dalvikSwappablePss", "dalvikRss", "dalvikPrivateDirty", "dalvikSharedDirty",
"dalvikPrivateClean", "dalvikSharedClean", "dalvikSwappedOut", "dalvikSwappedOutPss" },
- { "nativePss", "nativeSwappablePss", "nativePrivateDirty", "nativeSharedDirty",
+ { "nativePss", "nativeSwappablePss", "nativeRss", "nativePrivateDirty", "nativeSharedDirty",
"nativePrivateClean", "nativeSharedClean", "nativeSwappedOut", "nativeSwappedOutPss" }
};
@@ -143,6 +145,7 @@
struct stats_t {
int pss;
int swappablePss;
+ int rss;
int privateDirty;
int sharedDirty;
int privateClean;
@@ -246,7 +249,7 @@
int len, nameLen;
bool skip, done = false;
- unsigned pss = 0, swappable_pss = 0;
+ unsigned pss = 0, swappable_pss = 0, rss = 0;
float sharing_proportion = 0.0;
unsigned shared_clean = 0, shared_dirty = 0;
unsigned private_clean = 0, private_dirty = 0;
@@ -412,7 +415,7 @@
if (line[0] == 'S' && sscanf(line, "Size: %d kB", &temp) == 1) {
/* size = temp; */
} else if (line[0] == 'R' && sscanf(line, "Rss: %d kB", &temp) == 1) {
- /* resident = temp; */
+ rss = temp;
} else if (line[0] == 'P' && sscanf(line, "Pss: %d kB", &temp) == 1) {
pss = temp;
} else if (line[0] == 'S' && sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
@@ -450,6 +453,7 @@
stats[whichHeap].pss += pss;
stats[whichHeap].swappablePss += swappable_pss;
+ stats[whichHeap].rss += rss;
stats[whichHeap].privateDirty += private_dirty;
stats[whichHeap].sharedDirty += shared_dirty;
stats[whichHeap].privateClean += private_clean;
@@ -460,6 +464,7 @@
whichHeap == HEAP_DEX || whichHeap == HEAP_ART) {
stats[subHeap].pss += pss;
stats[subHeap].swappablePss += swappable_pss;
+ stats[subHeap].rss += rss;
stats[subHeap].privateDirty += private_dirty;
stats[subHeap].sharedDirty += shared_dirty;
stats[subHeap].privateClean += private_clean;
@@ -495,15 +500,19 @@
if (read_memtrack_memory(pid, &graphics_mem) == 0) {
stats[HEAP_GRAPHICS].pss = graphics_mem.graphics;
stats[HEAP_GRAPHICS].privateDirty = graphics_mem.graphics;
+ stats[HEAP_GRAPHICS].rss = graphics_mem.graphics;
stats[HEAP_GL].pss = graphics_mem.gl;
stats[HEAP_GL].privateDirty = graphics_mem.gl;
+ stats[HEAP_GL].rss = graphics_mem.gl;
stats[HEAP_OTHER_MEMTRACK].pss = graphics_mem.other;
stats[HEAP_OTHER_MEMTRACK].privateDirty = graphics_mem.other;
+ stats[HEAP_OTHER_MEMTRACK].rss = graphics_mem.other;
}
for (int i=_NUM_CORE_HEAP; i<_NUM_EXCLUSIVE_HEAP; i++) {
stats[HEAP_UNKNOWN].pss += stats[i].pss;
stats[HEAP_UNKNOWN].swappablePss += stats[i].swappablePss;
+ stats[HEAP_UNKNOWN].rss += stats[i].rss;
stats[HEAP_UNKNOWN].privateDirty += stats[i].privateDirty;
stats[HEAP_UNKNOWN].sharedDirty += stats[i].sharedDirty;
stats[HEAP_UNKNOWN].privateClean += stats[i].privateClean;
@@ -515,6 +524,7 @@
for (int i=0; i<_NUM_CORE_HEAP; i++) {
env->SetIntField(object, stat_fields[i].pss_field, stats[i].pss);
env->SetIntField(object, stat_fields[i].pssSwappable_field, stats[i].swappablePss);
+ env->SetIntField(object, stat_fields[i].rss_field, stats[i].rss);
env->SetIntField(object, stat_fields[i].privateDirty_field, stats[i].privateDirty);
env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty);
env->SetIntField(object, stat_fields[i].privateClean_field, stats[i].privateClean);
@@ -536,6 +546,7 @@
for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) {
otherArray[j++] = stats[i].pss;
otherArray[j++] = stats[i].swappablePss;
+ otherArray[j++] = stats[i].rss;
otherArray[j++] = stats[i].privateDirty;
otherArray[j++] = stats[i].sharedDirty;
otherArray[j++] = stats[i].privateClean;
@@ -580,10 +591,11 @@
}
static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid,
- jlongArray outUssSwapPss, jlongArray outMemtrack)
+ jlongArray outUssSwapPssRss, jlongArray outMemtrack)
{
- char line[1024];
+ char lineBuffer[1024];
jlong pss = 0;
+ jlong rss = 0;
jlong swapPss = 0;
jlong uss = 0;
jlong memtrack = 0;
@@ -597,50 +609,70 @@
UniqueFile fp = OpenSmapsOrRollup(pid);
if (fp != nullptr) {
+ char* line;
+
while (true) {
- if (fgets(line, sizeof (line), fp.get()) == NULL) {
+ if (fgets(lineBuffer, sizeof (lineBuffer), fp.get()) == NULL) {
break;
}
+ line = lineBuffer;
- if (line[0] == 'P') {
- if (strncmp(line, "Pss:", 4) == 0) {
- char* c = line + 4;
- while (*c != 0 && (*c < '0' || *c > '9')) {
- c++;
+ switch (line[0]) {
+ case 'P':
+ if (strncmp(line, "Pss:", 4) == 0) {
+ char* c = line + 4;
+ while (*c != 0 && (*c < '0' || *c > '9')) {
+ c++;
+ }
+ pss += atoi(c);
+ } else if (strncmp(line, "Private_Clean:", 14) == 0
+ || strncmp(line, "Private_Dirty:", 14) == 0) {
+ char* c = line + 14;
+ while (*c != 0 && (*c < '0' || *c > '9')) {
+ c++;
+ }
+ uss += atoi(c);
}
- pss += atoi(c);
- } else if (strncmp(line, "Private_Clean:", 14) == 0
- || strncmp(line, "Private_Dirty:", 14) == 0) {
- char* c = line + 14;
- while (*c != 0 && (*c < '0' || *c > '9')) {
- c++;
+ break;
+ case 'R':
+ if (strncmp(line, "Rss:", 4) == 0) {
+ char* c = line + 4;
+ while (*c != 0 && (*c < '0' || *c > '9')) {
+ c++;
+ }
+ rss += atoi(c);
}
- uss += atoi(c);
- }
- } else if (line[0] == 'S' && strncmp(line, "SwapPss:", 8) == 0) {
- char* c = line + 8;
- jlong lSwapPss;
- while (*c != 0 && (*c < '0' || *c > '9')) {
- c++;
- }
- lSwapPss = atoi(c);
- swapPss += lSwapPss;
- pss += lSwapPss; // Also in swap, those pages would be accounted as Pss without SWAP
+ break;
+ case 'S':
+ if (strncmp(line, "SwapPss:", 8) == 0) {
+ char* c = line + 8;
+ jlong lSwapPss;
+ while (*c != 0 && (*c < '0' || *c > '9')) {
+ c++;
+ }
+ lSwapPss = atoi(c);
+ swapPss += lSwapPss;
+ pss += lSwapPss; // Also in swap, those pages would be accounted as Pss without SWAP
+ }
+ break;
}
}
}
}
- if (outUssSwapPss != NULL) {
- if (env->GetArrayLength(outUssSwapPss) >= 1) {
- jlong* outUssSwapPssArray = env->GetLongArrayElements(outUssSwapPss, 0);
- if (outUssSwapPssArray != NULL) {
- outUssSwapPssArray[0] = uss;
- if (env->GetArrayLength(outUssSwapPss) >= 2) {
- outUssSwapPssArray[1] = swapPss;
+ if (outUssSwapPssRss != NULL) {
+ if (env->GetArrayLength(outUssSwapPssRss) >= 1) {
+ jlong* outUssSwapPssRssArray = env->GetLongArrayElements(outUssSwapPssRss, 0);
+ if (outUssSwapPssRssArray != NULL) {
+ outUssSwapPssRssArray[0] = uss;
+ if (env->GetArrayLength(outUssSwapPssRss) >= 2) {
+ outUssSwapPssRssArray[1] = swapPss;
+ }
+ if (env->GetArrayLength(outUssSwapPssRss) >= 3) {
+ outUssSwapPssRssArray[2] = rss;
}
}
- env->ReleaseLongArrayElements(outUssSwapPss, outUssSwapPssArray, 0);
+ env->ReleaseLongArrayElements(outUssSwapPssRss, outUssSwapPssRssArray, 0);
}
}
@@ -1209,6 +1241,8 @@
env->GetFieldID(clazz, stat_field_names[i].pss_name, "I");
stat_fields[i].pssSwappable_field =
env->GetFieldID(clazz, stat_field_names[i].pssSwappable_name, "I");
+ stat_fields[i].rss_field =
+ env->GetFieldID(clazz, stat_field_names[i].rss_name, "I");
stat_fields[i].privateDirty_field =
env->GetFieldID(clazz, stat_field_names[i].privateDirty_name, "I");
stat_fields[i].sharedDirty_field =
diff --git a/core/jni/android_text_MeasuredParagraph.cpp b/core/jni/android_text_MeasuredParagraph.cpp
index f0e449d..d33337d 100644
--- a/core/jni/android_text_MeasuredParagraph.cpp
+++ b/core/jni/android_text_MeasuredParagraph.cpp
@@ -72,8 +72,7 @@
Paint* paint = toPaint(paintPtr);
const Typeface* typeface = Typeface::resolveDefault(paint->getAndroidTypeface());
minikin::MinikinPaint minikinPaint = MinikinUtils::prepareMinikinPaint(paint, typeface);
- toBuilder(builderPtr)->addStyleRun(start, end, std::move(minikinPaint),
- typeface->fFontCollection, isRtl);
+ toBuilder(builderPtr)->addStyleRun(start, end, std::move(minikinPaint), isRtl);
}
// Regular JNI
@@ -115,6 +114,10 @@
return toJLong(&releaseMeasuredParagraph);
}
+static jint nGetMemoryUsage(jlong ptr) {
+ return static_cast<jint>(toMeasuredParagraph(ptr)->getMemoryUsage());
+}
+
static const JNINativeMethod gMethods[] = {
// MeasuredParagraphBuilder native functions.
{"nInitBuilder", "()J", (void*) nInitBuilder},
@@ -126,6 +129,7 @@
// MeasuredParagraph native functions.
{"nGetWidth", "(JII)F", (void*) nGetWidth}, // Critical Natives
{"nGetReleaseFunc", "()J", (void*) nGetReleaseFunc}, // Critical Natives
+ {"nGetMemoryUsage", "(J)I", (void*) nGetMemoryUsage}, // Critical Native
};
int register_android_text_MeasuredParagraph(JNIEnv* env) {
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 403937b..683b4c4 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1,1437 +1,1851 @@
-/*
- * 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.
- */
+/* //device/libs/android_runtime/android_util_AssetManager.cpp
+**
+** 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.
+*/
#define LOG_TAG "asset"
+#include <android_runtime/android_util_AssetManager.h>
+
#include <inttypes.h>
#include <linux/capability.h>
#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/system_properties.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/system_properties.h>
#include <private/android_filesystem_config.h> // for AID_SYSTEM
-#include "android-base/logging.h"
-#include "android-base/properties.h"
-#include "android-base/stringprintf.h"
-#include "android_runtime/android_util_AssetManager.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "android_util_Binder.h"
#include "androidfw/Asset.h"
#include "androidfw/AssetManager.h"
-#include "androidfw/AssetManager2.h"
#include "androidfw/AttributeResolution.h"
-#include "androidfw/MutexGuard.h"
#include "androidfw/ResourceTypes.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "android_util_Binder.h"
#include "core_jni_helpers.h"
#include "jni.h"
-#include "nativehelper/JNIHelp.h"
-#include "nativehelper/ScopedPrimitiveArray.h"
-#include "nativehelper/ScopedStringChars.h"
-#include "nativehelper/ScopedUtfChars.h"
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedStringChars.h>
+#include <nativehelper/ScopedUtfChars.h>
#include "utils/Log.h"
-#include "utils/String8.h"
#include "utils/misc.h"
+#include "utils/String8.h"
extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
-using ::android::base::StringPrintf;
namespace android {
+static const bool kThrowOnBadId = false;
+
// ----------------------------------------------------------------------------
-static struct typedvalue_offsets_t {
- jfieldID mType;
- jfieldID mData;
- jfieldID mString;
- jfieldID mAssetCookie;
- jfieldID mResourceId;
- jfieldID mChangingConfigurations;
- jfieldID mDensity;
+static struct typedvalue_offsets_t
+{
+ jfieldID mType;
+ jfieldID mData;
+ jfieldID mString;
+ jfieldID mAssetCookie;
+ jfieldID mResourceId;
+ jfieldID mChangingConfigurations;
+ jfieldID mDensity;
} gTypedValueOffsets;
-static struct assetfiledescriptor_offsets_t {
- jfieldID mFd;
- jfieldID mStartOffset;
- jfieldID mLength;
+static struct assetfiledescriptor_offsets_t
+{
+ jfieldID mFd;
+ jfieldID mStartOffset;
+ jfieldID mLength;
} gAssetFileDescriptorOffsets;
-static struct assetmanager_offsets_t {
- jfieldID mObject;
+static struct assetmanager_offsets_t
+{
+ jfieldID mObject;
} gAssetManagerOffsets;
-static struct {
- jfieldID native_ptr;
-} gApkAssetsFields;
-
-static struct sparsearray_offsets_t {
- jclass classObject;
- jmethodID constructor;
- jmethodID put;
+static struct sparsearray_offsets_t
+{
+ jclass classObject;
+ jmethodID constructor;
+ jmethodID put;
} gSparseArrayOffsets;
-static struct configuration_offsets_t {
- jclass classObject;
- jmethodID constructor;
- jfieldID mSmallestScreenWidthDpOffset;
- jfieldID mScreenWidthDpOffset;
- jfieldID mScreenHeightDpOffset;
+static struct configuration_offsets_t
+{
+ jclass classObject;
+ jmethodID constructor;
+ jfieldID mSmallestScreenWidthDpOffset;
+ jfieldID mScreenWidthDpOffset;
+ jfieldID mScreenHeightDpOffset;
} gConfigurationOffsets;
-jclass g_stringClass = nullptr;
+jclass g_stringClass = NULL;
// ----------------------------------------------------------------------------
-// Java asset cookies have 0 as an invalid cookie, but TypedArray expects < 0.
-constexpr inline static jint ApkAssetsCookieToJavaCookie(ApkAssetsCookie cookie) {
- return cookie != kInvalidCookie ? static_cast<jint>(cookie + 1) : -1;
-}
+static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
+ const Res_value& value, uint32_t ref, ssize_t block,
+ uint32_t typeSpecFlags, ResTable_config* config = NULL);
-constexpr inline static ApkAssetsCookie JavaCookieToApkAssetsCookie(jint cookie) {
- return cookie > 0 ? static_cast<ApkAssetsCookie>(cookie - 1) : kInvalidCookie;
+jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
+ const Res_value& value, uint32_t ref, ssize_t block,
+ uint32_t typeSpecFlags, ResTable_config* config)
+{
+ env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
+ env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
+ static_cast<jint>(table->getTableCookie(block)));
+ env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
+ env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
+ env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
+ env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
+ typeSpecFlags);
+ if (config != NULL) {
+ env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
+ }
+ return block;
}
// This is called by zygote (running as user root) as part of preloadResources.
-static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) {
- switch (pid_t pid = fork()) {
- case -1:
- PLOG(ERROR) << "failed to fork for idmap";
- break;
+static void verifySystemIdmaps()
+{
+ pid_t pid;
+ char system_id[10];
- // child
- case 0: {
- struct __user_cap_header_struct capheader;
- struct __user_cap_data_struct capdata;
+ snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
- memset(&capheader, 0, sizeof(capheader));
- memset(&capdata, 0, sizeof(capdata));
+ switch (pid = fork()) {
+ case -1:
+ ALOGE("failed to fork for idmap: %s", strerror(errno));
+ break;
+ case 0: // child
+ {
+ struct __user_cap_header_struct capheader;
+ struct __user_cap_data_struct capdata;
- capheader.version = _LINUX_CAPABILITY_VERSION;
- capheader.pid = 0;
+ memset(&capheader, 0, sizeof(capheader));
+ memset(&capdata, 0, sizeof(capdata));
- if (capget(&capheader, &capdata) != 0) {
- PLOG(ERROR) << "capget";
- exit(1);
- }
+ capheader.version = _LINUX_CAPABILITY_VERSION;
+ capheader.pid = 0;
- capdata.effective = capdata.permitted;
- if (capset(&capheader, &capdata) != 0) {
- PLOG(ERROR) << "capset";
- exit(1);
- }
+ if (capget(&capheader, &capdata) != 0) {
+ ALOGE("capget: %s\n", strerror(errno));
+ exit(1);
+ }
- if (setgid(AID_SYSTEM) != 0) {
- PLOG(ERROR) << "setgid";
- exit(1);
- }
+ capdata.effective = capdata.permitted;
+ if (capset(&capheader, &capdata) != 0) {
+ ALOGE("capset: %s\n", strerror(errno));
+ exit(1);
+ }
- if (setuid(AID_SYSTEM) != 0) {
- PLOG(ERROR) << "setuid";
- exit(1);
- }
+ if (setgid(AID_SYSTEM) != 0) {
+ ALOGE("setgid: %s\n", strerror(errno));
+ exit(1);
+ }
- // Generic idmap parameters
- const char* argv[8];
- int argc = 0;
- struct stat st;
+ if (setuid(AID_SYSTEM) != 0) {
+ ALOGE("setuid: %s\n", strerror(errno));
+ exit(1);
+ }
- memset(argv, 0, sizeof(argv));
- argv[argc++] = AssetManager::IDMAP_BIN;
- argv[argc++] = "--scan";
- argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
- argv[argc++] = AssetManager::TARGET_APK_PATH;
- argv[argc++] = AssetManager::IDMAP_DIR;
+ // Generic idmap parameters
+ const char* argv[8];
+ int argc = 0;
+ struct stat st;
- // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
- // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
- std::string overlay_theme_path = base::GetProperty(AssetManager::OVERLAY_THEME_DIR_PROPERTY,
- "");
- if (!overlay_theme_path.empty()) {
- overlay_theme_path = std::string(AssetManager::OVERLAY_DIR) + "/" + overlay_theme_path;
- if (stat(overlay_theme_path.c_str(), &st) == 0) {
- argv[argc++] = overlay_theme_path.c_str();
- }
- }
+ memset(argv, NULL, sizeof(argv));
+ argv[argc++] = AssetManager::IDMAP_BIN;
+ argv[argc++] = "--scan";
+ argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
+ argv[argc++] = AssetManager::TARGET_APK_PATH;
+ argv[argc++] = AssetManager::IDMAP_DIR;
- if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
- argv[argc++] = AssetManager::OVERLAY_DIR;
- }
+ // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
+ // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
+ char subdir[PROP_VALUE_MAX];
+ int len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PROPERTY, subdir);
+ if (len > 0) {
+ String8 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
+ if (stat(overlayPath.string(), &st) == 0) {
+ argv[argc++] = overlayPath.string();
+ }
+ }
+ if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
+ argv[argc++] = AssetManager::OVERLAY_DIR;
+ }
- // Finally, invoke idmap (if any overlay directory exists)
- if (argc > 5) {
- execv(AssetManager::IDMAP_BIN, (char* const*)argv);
- PLOG(ERROR) << "failed to execv for idmap";
- exit(1); // should never get here
- } else {
- exit(0);
- }
- } break;
+ if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
+ argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
+ }
- // parent
- default:
- waitpid(pid, nullptr, 0);
- break;
- }
+ // Finally, invoke idmap (if any overlay directory exists)
+ if (argc > 5) {
+ execv(AssetManager::IDMAP_BIN, (char* const*)argv);
+ ALOGE("failed to execv for idmap: %s", strerror(errno));
+ exit(1); // should never get here
+ } else {
+ exit(0);
+ }
+ }
+ break;
+ default: // parent
+ waitpid(pid, NULL, 0);
+ break;
+ }
}
-static jint CopyValue(JNIEnv* env, ApkAssetsCookie cookie, const Res_value& value, uint32_t ref,
- uint32_t type_spec_flags, ResTable_config* config, jobject out_typed_value) {
- env->SetIntField(out_typed_value, gTypedValueOffsets.mType, value.dataType);
- env->SetIntField(out_typed_value, gTypedValueOffsets.mAssetCookie,
- ApkAssetsCookieToJavaCookie(cookie));
- env->SetIntField(out_typed_value, gTypedValueOffsets.mData, value.data);
- env->SetObjectField(out_typed_value, gTypedValueOffsets.mString, nullptr);
- env->SetIntField(out_typed_value, gTypedValueOffsets.mResourceId, ref);
- env->SetIntField(out_typed_value, gTypedValueOffsets.mChangingConfigurations, type_spec_flags);
- if (config != nullptr) {
- env->SetIntField(out_typed_value, gTypedValueOffsets.mDensity, config->density);
- }
- return static_cast<jint>(ApkAssetsCookieToJavaCookie(cookie));
-}
// ----------------------------------------------------------------------------
-// Let the opaque type AAssetManager refer to a guarded AssetManager2 instance.
-struct GuardedAssetManager : public ::AAssetManager {
- Guarded<AssetManager2> guarded_assetmanager;
-};
-
-::AAssetManager* NdkAssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager) {
- jlong assetmanager_handle = env->GetLongField(jassetmanager, gAssetManagerOffsets.mObject);
- ::AAssetManager* am = reinterpret_cast<::AAssetManager*>(assetmanager_handle);
- if (am == nullptr) {
+// this guy is exported to other jni routines
+AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
+{
+ jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
+ AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
+ if (am != NULL) {
+ return am;
+ }
jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
- return nullptr;
- }
- return am;
+ return NULL;
}
-Guarded<AssetManager2>* AssetManagerForNdkAssetManager(::AAssetManager* assetmanager) {
- if (assetmanager == nullptr) {
- return nullptr;
- }
- return &reinterpret_cast<GuardedAssetManager*>(assetmanager)->guarded_assetmanager;
-}
-
-Guarded<AssetManager2>* AssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager) {
- return AssetManagerForNdkAssetManager(NdkAssetManagerForJavaObject(env, jassetmanager));
-}
-
-static Guarded<AssetManager2>& AssetManagerFromLong(jlong ptr) {
- return *AssetManagerForNdkAssetManager(reinterpret_cast<AAssetManager*>(ptr));
-}
-
-static jobject ReturnParcelFileDescriptor(JNIEnv* env, std::unique_ptr<Asset> asset,
- jlongArray out_offsets) {
- off64_t start_offset, length;
- int fd = asset->openFileDescriptor(&start_offset, &length);
- asset.reset();
-
- if (fd < 0) {
- jniThrowException(env, "java/io/FileNotFoundException",
- "This file can not be opened as a file descriptor; it is probably "
- "compressed");
- return nullptr;
- }
-
- jlong* offsets = reinterpret_cast<jlong*>(env->GetPrimitiveArrayCritical(out_offsets, 0));
- if (offsets == nullptr) {
- close(fd);
- return nullptr;
- }
-
- offsets[0] = start_offset;
- offsets[1] = length;
-
- env->ReleasePrimitiveArrayCritical(out_offsets, offsets, 0);
-
- jobject file_desc = jniCreateFileDescriptor(env, fd);
- if (file_desc == nullptr) {
- close(fd);
- return nullptr;
- }
- return newParcelFileDescriptor(env, file_desc);
-}
-
-static jint NativeGetGlobalAssetCount(JNIEnv* /*env*/, jobject /*clazz*/) {
- return Asset::getGlobalCount();
-}
-
-static jobject NativeGetAssetAllocations(JNIEnv* env, jobject /*clazz*/) {
- String8 alloc = Asset::getAssetAllocations();
- if (alloc.length() <= 0) {
- return nullptr;
- }
- return env->NewStringUTF(alloc.string());
-}
-
-static jint NativeGetGlobalAssetManagerCount(JNIEnv* /*env*/, jobject /*clazz*/) {
- // TODO(adamlesinski): Switch to AssetManager2.
- return AssetManager::getGlobalCount();
-}
-
-static jlong NativeCreate(JNIEnv* /*env*/, jclass /*clazz*/) {
- // AssetManager2 needs to be protected by a lock. To avoid cache misses, we allocate the lock and
- // AssetManager2 in a contiguous block (GuardedAssetManager).
- return reinterpret_cast<jlong>(new GuardedAssetManager());
-}
-
-static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
- delete reinterpret_cast<GuardedAssetManager*>(ptr);
-}
-
-static void NativeSetApkAssets(JNIEnv* env, jclass /*clazz*/, jlong ptr,
- jobjectArray apk_assets_array, jboolean invalidate_caches) {
- const jsize apk_assets_len = env->GetArrayLength(apk_assets_array);
- std::vector<const ApkAssets*> apk_assets;
- apk_assets.reserve(apk_assets_len);
- for (jsize i = 0; i < apk_assets_len; i++) {
- jobject obj = env->GetObjectArrayElement(apk_assets_array, i);
- if (obj == nullptr) {
- std::string msg = StringPrintf("ApkAssets at index %d is null", i);
- jniThrowNullPointerException(env, msg.c_str());
- return;
+static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
+ jstring fileName, jint mode)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
}
- jlong apk_assets_native_ptr = env->GetLongField(obj, gApkAssetsFields.native_ptr);
- if (env->ExceptionCheck()) {
- return;
- }
- apk_assets.push_back(reinterpret_cast<const ApkAssets*>(apk_assets_native_ptr));
- }
+ ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- assetmanager->SetApkAssets(apk_assets, invalidate_caches);
-}
-
-static void NativeSetConfiguration(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint mcc, jint mnc,
- jstring locale, jint orientation, jint touchscreen, jint density,
- jint keyboard, jint keyboard_hidden, jint navigation,
- jint screen_width, jint screen_height,
- jint smallest_screen_width_dp, jint screen_width_dp,
- jint screen_height_dp, jint screen_layout, jint ui_mode,
- jint color_mode, jint major_version) {
- ResTable_config configuration;
- memset(&configuration, 0, sizeof(configuration));
- configuration.mcc = static_cast<uint16_t>(mcc);
- configuration.mnc = static_cast<uint16_t>(mnc);
- configuration.orientation = static_cast<uint8_t>(orientation);
- configuration.touchscreen = static_cast<uint8_t>(touchscreen);
- configuration.density = static_cast<uint16_t>(density);
- configuration.keyboard = static_cast<uint8_t>(keyboard);
- configuration.inputFlags = static_cast<uint8_t>(keyboard_hidden);
- configuration.navigation = static_cast<uint8_t>(navigation);
- configuration.screenWidth = static_cast<uint16_t>(screen_width);
- configuration.screenHeight = static_cast<uint16_t>(screen_height);
- configuration.smallestScreenWidthDp = static_cast<uint16_t>(smallest_screen_width_dp);
- configuration.screenWidthDp = static_cast<uint16_t>(screen_width_dp);
- configuration.screenHeightDp = static_cast<uint16_t>(screen_height_dp);
- configuration.screenLayout = static_cast<uint8_t>(screen_layout);
- configuration.uiMode = static_cast<uint8_t>(ui_mode);
- configuration.colorMode = static_cast<uint8_t>(color_mode);
- configuration.sdkVersion = static_cast<uint16_t>(major_version);
-
- if (locale != nullptr) {
- ScopedUtfChars locale_utf8(env, locale);
- CHECK(locale_utf8.c_str() != nullptr);
- configuration.setBcp47Locale(locale_utf8.c_str());
- }
-
- // Constants duplicated from Java class android.content.res.Configuration.
- static const jint kScreenLayoutRoundMask = 0x300;
- static const jint kScreenLayoutRoundShift = 8;
-
- // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
- // in C++. We must extract the round qualifier out of the Java screenLayout and put it
- // into screenLayout2.
- configuration.screenLayout2 =
- static_cast<uint8_t>((screen_layout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
-
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- assetmanager->SetConfiguration(configuration);
-}
-
-static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
-
- jobject sparse_array =
- env->NewObject(gSparseArrayOffsets.classObject, gSparseArrayOffsets.constructor);
-
- if (sparse_array == nullptr) {
- // An exception is pending.
- return nullptr;
- }
-
- assetmanager->ForEachPackage([&](const std::string& package_name, uint8_t package_id) {
- jstring jpackage_name = env->NewStringUTF(package_name.c_str());
- if (jpackage_name == nullptr) {
- // An exception is pending.
- return;
+ ScopedUtfChars fileName8(env, fileName);
+ if (fileName8.c_str() == NULL) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
+ return -1;
}
- env->CallVoidMethod(sparse_array, gSparseArrayOffsets.put, static_cast<jint>(package_id),
- jpackage_name);
- });
- return sparse_array;
+ if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
+ && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
+ return -1;
+ }
+
+ Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
+
+ if (a == NULL) {
+ jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+ return -1;
+ }
+
+ //printf("Created Asset Stream: %p\n", a);
+
+ return reinterpret_cast<jlong>(a);
}
-static jobjectArray NativeList(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring path) {
- ScopedUtfChars path_utf8(env, path);
- if (path_utf8.c_str() == nullptr) {
- // This will throw NPE.
- return nullptr;
- }
+static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
+{
+ off64_t startOffset, length;
+ int fd = a->openFileDescriptor(&startOffset, &length);
+ delete a;
- std::vector<std::string> all_file_paths;
- {
- StringPiece normalized_path = path_utf8.c_str();
- if (normalized_path.data()[0] == '/') {
- normalized_path = normalized_path.substr(1);
+ if (fd < 0) {
+ jniThrowException(env, "java/io/FileNotFoundException",
+ "This file can not be opened as a file descriptor; it is probably compressed");
+ return NULL;
}
- std::string root_path = StringPrintf("assets/%s", normalized_path.data());
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- for (const ApkAssets* assets : assetmanager->GetApkAssets()) {
- assets->ForEachFile(root_path, [&](const StringPiece& file_path, FileType type) {
- if (type == FileType::kFileTypeRegular) {
- all_file_paths.push_back(file_path.to_string());
+
+ jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
+ if (offsets == NULL) {
+ close(fd);
+ return NULL;
+ }
+
+ offsets[0] = startOffset;
+ offsets[1] = length;
+
+ env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
+
+ jobject fileDesc = jniCreateFileDescriptor(env, fd);
+ if (fileDesc == NULL) {
+ close(fd);
+ return NULL;
+ }
+
+ return newParcelFileDescriptor(env, fileDesc);
+}
+
+static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
+ jstring fileName, jlongArray outOffsets)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+
+ ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
+
+ ScopedUtfChars fileName8(env, fileName);
+ if (fileName8.c_str() == NULL) {
+ return NULL;
+ }
+
+ Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
+
+ if (a == NULL) {
+ jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+ return NULL;
+ }
+
+ //printf("Created Asset Stream: %p\n", a);
+
+ return returnParcelFileDescriptor(env, a, outOffsets);
+}
+
+static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
+ jint cookie,
+ jstring fileName,
+ jint mode)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+
+ ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
+
+ ScopedUtfChars fileName8(env, fileName);
+ if (fileName8.c_str() == NULL) {
+ return -1;
+ }
+
+ if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
+ && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
+ return -1;
+ }
+
+ Asset* a = cookie
+ ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
+ (Asset::AccessMode)mode)
+ : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
+
+ if (a == NULL) {
+ jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+ return -1;
+ }
+
+ //printf("Created Asset Stream: %p\n", a);
+
+ return reinterpret_cast<jlong>(a);
+}
+
+static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
+ jint cookie,
+ jstring fileName,
+ jlongArray outOffsets)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+
+ ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
+
+ ScopedUtfChars fileName8(env, fileName);
+ if (fileName8.c_str() == NULL) {
+ return NULL;
+ }
+
+ Asset* a = cookie
+ ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
+ : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
+
+ if (a == NULL) {
+ jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+ return NULL;
+ }
+
+ //printf("Created Asset Stream: %p\n", a);
+
+ return returnParcelFileDescriptor(env, a, outOffsets);
+}
+
+static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
+ jstring fileName)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+
+ ScopedUtfChars fileName8(env, fileName);
+ if (fileName8.c_str() == NULL) {
+ return NULL;
+ }
+
+ AssetDir* dir = am->openDir(fileName8.c_str());
+
+ if (dir == NULL) {
+ jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+ return NULL;
+ }
+
+ size_t N = dir->getFileCount();
+
+ jobjectArray array = env->NewObjectArray(dir->getFileCount(),
+ g_stringClass, NULL);
+ if (array == NULL) {
+ delete dir;
+ return NULL;
+ }
+
+ for (size_t i=0; i<N; i++) {
+ const String8& name = dir->getFileName(i);
+ jstring str = env->NewStringUTF(name.string());
+ if (str == NULL) {
+ delete dir;
+ return NULL;
}
- });
- }
- }
-
- jobjectArray array = env->NewObjectArray(all_file_paths.size(), g_stringClass, nullptr);
- if (array == nullptr) {
- return nullptr;
- }
-
- jsize index = 0;
- for (const std::string& file_path : all_file_paths) {
- jstring java_string = env->NewStringUTF(file_path.c_str());
-
- // Check for errors creating the strings (if malformed or no memory).
- if (env->ExceptionCheck()) {
- return nullptr;
+ env->SetObjectArrayElement(array, i, str);
+ env->DeleteLocalRef(str);
}
- env->SetObjectArrayElement(array, index++, java_string);
+ delete dir;
- // If we have a large amount of string in our array, we might overflow the
- // local reference table of the VM.
- env->DeleteLocalRef(java_string);
- }
- return array;
+ return array;
}
-static jlong NativeOpenAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring asset_path,
- jint access_mode) {
- ScopedUtfChars asset_path_utf8(env, asset_path);
- if (asset_path_utf8.c_str() == nullptr) {
- // This will throw NPE.
- return 0;
- }
+static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
+ jlong assetHandle)
+{
+ Asset* a = reinterpret_cast<Asset*>(assetHandle);
- if (access_mode != Asset::ACCESS_UNKNOWN && access_mode != Asset::ACCESS_RANDOM &&
- access_mode != Asset::ACCESS_STREAMING && access_mode != Asset::ACCESS_BUFFER) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
- return 0;
- }
+ //printf("Destroying Asset Stream: %p\n", a);
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- std::unique_ptr<Asset> asset =
- assetmanager->Open(asset_path_utf8.c_str(), static_cast<Asset::AccessMode>(access_mode));
- if (!asset) {
- jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
- return 0;
- }
- return reinterpret_cast<jlong>(asset.release());
-}
-
-static jobject NativeOpenAssetFd(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring asset_path,
- jlongArray out_offsets) {
- ScopedUtfChars asset_path_utf8(env, asset_path);
- if (asset_path_utf8.c_str() == nullptr) {
- // This will throw NPE.
- return nullptr;
- }
-
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- std::unique_ptr<Asset> asset = assetmanager->Open(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM);
- if (!asset) {
- jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
- return nullptr;
- }
- return ReturnParcelFileDescriptor(env, std::move(asset), out_offsets);
-}
-
-static jlong NativeOpenNonAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint jcookie,
- jstring asset_path, jint access_mode) {
- ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
- ScopedUtfChars asset_path_utf8(env, asset_path);
- if (asset_path_utf8.c_str() == nullptr) {
- // This will throw NPE.
- return 0;
- }
-
- if (access_mode != Asset::ACCESS_UNKNOWN && access_mode != Asset::ACCESS_RANDOM &&
- access_mode != Asset::ACCESS_STREAMING && access_mode != Asset::ACCESS_BUFFER) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
- return 0;
- }
-
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- std::unique_ptr<Asset> asset;
- if (cookie != kInvalidCookie) {
- asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie,
- static_cast<Asset::AccessMode>(access_mode));
- } else {
- asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(),
- static_cast<Asset::AccessMode>(access_mode));
- }
-
- if (!asset) {
- jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
- return 0;
- }
- return reinterpret_cast<jlong>(asset.release());
-}
-
-static jobject NativeOpenNonAssetFd(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint jcookie,
- jstring asset_path, jlongArray out_offsets) {
- ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
- ScopedUtfChars asset_path_utf8(env, asset_path);
- if (asset_path_utf8.c_str() == nullptr) {
- // This will throw NPE.
- return nullptr;
- }
-
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- std::unique_ptr<Asset> asset;
- if (cookie != kInvalidCookie) {
- asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM);
- } else {
- asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM);
- }
-
- if (!asset) {
- jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
- return nullptr;
- }
- return ReturnParcelFileDescriptor(env, std::move(asset), out_offsets);
-}
-
-static jlong NativeOpenXmlAsset(JNIEnv* env, jobject /*clazz*/, jlong ptr, jint jcookie,
- jstring asset_path) {
- ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
- ScopedUtfChars asset_path_utf8(env, asset_path);
- if (asset_path_utf8.c_str() == nullptr) {
- // This will throw NPE.
- return 0;
- }
-
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- std::unique_ptr<Asset> asset;
- if (cookie != kInvalidCookie) {
- asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM);
- } else {
- asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM, &cookie);
- }
-
- if (!asset) {
- jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str());
- return 0;
- }
-
- // May be nullptr.
- const DynamicRefTable* dynamic_ref_table = assetmanager->GetDynamicRefTableForCookie(cookie);
-
- std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(dynamic_ref_table);
- status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), true);
- asset.reset();
-
- if (err != NO_ERROR) {
- jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
- return 0;
- }
- return reinterpret_cast<jlong>(xml_tree.release());
-}
-
-static jint NativeGetResourceValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
- jshort density, jobject typed_value,
- jboolean resolve_references) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- Res_value value;
- ResTable_config selected_config;
- uint32_t flags;
- ApkAssetsCookie cookie =
- assetmanager->GetResource(static_cast<uint32_t>(resid), false /*may_be_bag*/,
- static_cast<uint16_t>(density), &value, &selected_config, &flags);
- if (cookie == kInvalidCookie) {
- return ApkAssetsCookieToJavaCookie(kInvalidCookie);
- }
-
- uint32_t ref = static_cast<uint32_t>(resid);
- if (resolve_references) {
- cookie = assetmanager->ResolveReference(cookie, &value, &selected_config, &flags, &ref);
- if (cookie == kInvalidCookie) {
- return ApkAssetsCookieToJavaCookie(kInvalidCookie);
- }
- }
- return CopyValue(env, cookie, value, ref, flags, &selected_config, typed_value);
-}
-
-static jint NativeGetResourceBagValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
- jint bag_entry_id, jobject typed_value) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
- if (bag == nullptr) {
- return ApkAssetsCookieToJavaCookie(kInvalidCookie);
- }
-
- uint32_t type_spec_flags = bag->type_spec_flags;
- ApkAssetsCookie cookie = kInvalidCookie;
- const Res_value* bag_value = nullptr;
- for (const ResolvedBag::Entry& entry : bag) {
- if (entry.key == static_cast<uint32_t>(bag_entry_id)) {
- cookie = entry.cookie;
- bag_value = &entry.value;
-
- // Keep searching (the old implementation did that).
- }
- }
-
- if (cookie == kInvalidCookie) {
- return ApkAssetsCookieToJavaCookie(kInvalidCookie);
- }
-
- Res_value value = *bag_value;
- uint32_t ref = static_cast<uint32_t>(resid);
- ResTable_config selected_config;
- cookie = assetmanager->ResolveReference(cookie, &value, &selected_config, &type_spec_flags, &ref);
- if (cookie == kInvalidCookie) {
- return ApkAssetsCookieToJavaCookie(kInvalidCookie);
- }
- return CopyValue(env, cookie, value, ref, type_spec_flags, nullptr, typed_value);
-}
-
-static jintArray NativeGetStyleAttributes(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
- if (bag == nullptr) {
- return nullptr;
- }
-
- jintArray array = env->NewIntArray(bag->entry_count);
- if (env->ExceptionCheck()) {
- return nullptr;
- }
-
- for (uint32_t i = 0; i < bag->entry_count; i++) {
- jint attr_resid = bag->entries[i].key;
- env->SetIntArrayRegion(array, i, 1, &attr_resid);
- }
- return array;
-}
-
-static jobjectArray NativeGetResourceStringArray(JNIEnv* env, jclass /*clazz*/, jlong ptr,
- jint resid) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
- if (bag == nullptr) {
- return nullptr;
- }
-
- jobjectArray array = env->NewObjectArray(bag->entry_count, g_stringClass, nullptr);
- if (array == nullptr) {
- return nullptr;
- }
-
- for (uint32_t i = 0; i < bag->entry_count; i++) {
- const ResolvedBag::Entry& entry = bag->entries[i];
-
- // Resolve any references to their final value.
- Res_value value = entry.value;
- ResTable_config selected_config;
- uint32_t flags;
- uint32_t ref;
- ApkAssetsCookie cookie =
- assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
- if (cookie == kInvalidCookie) {
- return nullptr;
+ if (a == NULL) {
+ jniThrowNullPointerException(env, "asset");
+ return;
}
- if (value.dataType == Res_value::TYPE_STRING) {
- const ApkAssets* apk_assets = assetmanager->GetApkAssets()[cookie];
- const ResStringPool* pool = apk_assets->GetLoadedArsc()->GetStringPool();
-
- jstring java_string = nullptr;
- size_t str_len;
- const char* str_utf8 = pool->string8At(value.data, &str_len);
- if (str_utf8 != nullptr) {
- java_string = env->NewStringUTF(str_utf8);
- } else {
- const char16_t* str_utf16 = pool->stringAt(value.data, &str_len);
- java_string = env->NewString(reinterpret_cast<const jchar*>(str_utf16), str_len);
- }
-
- // Check for errors creating the strings (if malformed or no memory).
- if (env->ExceptionCheck()) {
- return nullptr;
- }
-
- env->SetObjectArrayElement(array, i, java_string);
-
- // If we have a large amount of string in our array, we might overflow the
- // local reference table of the VM.
- env->DeleteLocalRef(java_string);
- }
- }
- return array;
+ delete a;
}
-static jintArray NativeGetResourceStringArrayInfo(JNIEnv* env, jclass /*clazz*/, jlong ptr,
- jint resid) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
- if (bag == nullptr) {
- return nullptr;
- }
+static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
+ jlong assetHandle)
+{
+ Asset* a = reinterpret_cast<Asset*>(assetHandle);
- jintArray array = env->NewIntArray(bag->entry_count * 2);
- if (array == nullptr) {
- return nullptr;
- }
-
- jint* buffer = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(array, nullptr));
- if (buffer == nullptr) {
- return nullptr;
- }
-
- for (size_t i = 0; i < bag->entry_count; i++) {
- const ResolvedBag::Entry& entry = bag->entries[i];
- Res_value value = entry.value;
- ResTable_config selected_config;
- uint32_t flags;
- uint32_t ref;
- ApkAssetsCookie cookie =
- assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
- if (cookie == kInvalidCookie) {
- env->ReleasePrimitiveArrayCritical(array, buffer, JNI_ABORT);
- return nullptr;
+ if (a == NULL) {
+ jniThrowNullPointerException(env, "asset");
+ return -1;
}
- jint string_index = -1;
- if (value.dataType == Res_value::TYPE_STRING) {
- string_index = static_cast<jint>(value.data);
- }
-
- buffer[i * 2] = ApkAssetsCookieToJavaCookie(cookie);
- buffer[(i * 2) + 1] = string_index;
- }
- env->ReleasePrimitiveArrayCritical(array, buffer, 0);
- return array;
+ uint8_t b;
+ ssize_t res = a->read(&b, 1);
+ return res == 1 ? b : -1;
}
-static jintArray NativeGetResourceIntArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
- if (bag == nullptr) {
- return nullptr;
- }
+static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
+ jlong assetHandle, jbyteArray bArray,
+ jint off, jint len)
+{
+ Asset* a = reinterpret_cast<Asset*>(assetHandle);
- jintArray array = env->NewIntArray(bag->entry_count);
- if (array == nullptr) {
- return nullptr;
- }
-
- jint* buffer = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(array, nullptr));
- if (buffer == nullptr) {
- return nullptr;
- }
-
- for (size_t i = 0; i < bag->entry_count; i++) {
- const ResolvedBag::Entry& entry = bag->entries[i];
- Res_value value = entry.value;
- ResTable_config selected_config;
- uint32_t flags;
- uint32_t ref;
- ApkAssetsCookie cookie =
- assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
- if (cookie == kInvalidCookie) {
- env->ReleasePrimitiveArrayCritical(array, buffer, JNI_ABORT);
- return nullptr;
+ if (a == NULL || bArray == NULL) {
+ jniThrowNullPointerException(env, "asset");
+ return -1;
}
- if (value.dataType >= Res_value::TYPE_FIRST_INT && value.dataType <= Res_value::TYPE_LAST_INT) {
- buffer[i] = static_cast<jint>(value.data);
+ if (len == 0) {
+ return 0;
}
- }
- env->ReleasePrimitiveArrayCritical(array, buffer, 0);
- return array;
-}
-static jint NativeGetResourceArraySize(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jint resid) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
- if (bag == nullptr) {
+ jsize bLen = env->GetArrayLength(bArray);
+ if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
+ jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
+ return -1;
+ }
+
+ jbyte* b = env->GetByteArrayElements(bArray, NULL);
+ ssize_t res = a->read(b+off, len);
+ env->ReleaseByteArrayElements(bArray, b, 0);
+
+ if (res > 0) return static_cast<jint>(res);
+
+ if (res < 0) {
+ jniThrowException(env, "java/io/IOException", "");
+ }
return -1;
- }
- return static_cast<jint>(bag->entry_count);
}
-static jint NativeGetResourceArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid,
- jintArray out_data) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- const ResolvedBag* bag = assetmanager->GetBag(static_cast<uint32_t>(resid));
- if (bag == nullptr) {
- return -1;
- }
+static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
+ jlong assetHandle,
+ jlong offset, jint whence)
+{
+ Asset* a = reinterpret_cast<Asset*>(assetHandle);
- const jsize out_data_length = env->GetArrayLength(out_data);
- if (env->ExceptionCheck()) {
- return -1;
- }
-
- if (static_cast<jsize>(bag->entry_count) > out_data_length * STYLE_NUM_ENTRIES) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "Input array is not large enough");
- return -1;
- }
-
- jint* buffer = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_data, nullptr));
- if (buffer == nullptr) {
- return -1;
- }
-
- jint* cursor = buffer;
- for (size_t i = 0; i < bag->entry_count; i++) {
- const ResolvedBag::Entry& entry = bag->entries[i];
- Res_value value = entry.value;
- ResTable_config selected_config;
- selected_config.density = 0;
- uint32_t flags = bag->type_spec_flags;
- uint32_t ref;
- ApkAssetsCookie cookie =
- assetmanager->ResolveReference(entry.cookie, &value, &selected_config, &flags, &ref);
- if (cookie == kInvalidCookie) {
- env->ReleasePrimitiveArrayCritical(out_data, buffer, JNI_ABORT);
- return -1;
+ if (a == NULL) {
+ jniThrowNullPointerException(env, "asset");
+ return -1;
}
- // Deal with the special @null value -- it turns back to TYPE_NULL.
- if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
- value.dataType = Res_value::TYPE_NULL;
- value.data = Res_value::DATA_NULL_UNDEFINED;
+ return a->seek(
+ offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
+}
+
+static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
+ jlong assetHandle)
+{
+ Asset* a = reinterpret_cast<Asset*>(assetHandle);
+
+ if (a == NULL) {
+ jniThrowNullPointerException(env, "asset");
+ return -1;
}
- cursor[STYLE_TYPE] = static_cast<jint>(value.dataType);
- cursor[STYLE_DATA] = static_cast<jint>(value.data);
- cursor[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
- cursor[STYLE_RESOURCE_ID] = static_cast<jint>(ref);
- cursor[STYLE_CHANGING_CONFIGURATIONS] = static_cast<jint>(flags);
- cursor[STYLE_DENSITY] = static_cast<jint>(selected_config.density);
- cursor += STYLE_NUM_ENTRIES;
- }
- env->ReleasePrimitiveArrayCritical(out_data, buffer, 0);
- return static_cast<jint>(bag->entry_count);
+ return a->getLength();
}
-static jint NativeGetResourceIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring name,
- jstring def_type, jstring def_package) {
- ScopedUtfChars name_utf8(env, name);
- if (name_utf8.c_str() == nullptr) {
- // This will throw NPE.
- return 0;
- }
+static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
+ jlong assetHandle)
+{
+ Asset* a = reinterpret_cast<Asset*>(assetHandle);
- std::string type;
- if (def_type != nullptr) {
- ScopedUtfChars type_utf8(env, def_type);
- CHECK(type_utf8.c_str() != nullptr);
- type = type_utf8.c_str();
- }
-
- std::string package;
- if (def_package != nullptr) {
- ScopedUtfChars package_utf8(env, def_package);
- CHECK(package_utf8.c_str() != nullptr);
- package = package_utf8.c_str();
- }
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- return static_cast<jint>(assetmanager->GetResourceId(name_utf8.c_str(), type, package));
-}
-
-static jstring NativeGetResourceName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- AssetManager2::ResourceName name;
- if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
- return nullptr;
- }
-
- std::string result;
- if (name.package != nullptr) {
- result.append(name.package, name.package_len);
- }
-
- if (name.type != nullptr || name.type16 != nullptr) {
- if (!result.empty()) {
- result += ":";
+ if (a == NULL) {
+ jniThrowNullPointerException(env, "asset");
+ return -1;
}
- if (name.type != nullptr) {
- result.append(name.type, name.type_len);
- } else {
- result += util::Utf16ToUtf8(StringPiece16(name.type16, name.type_len));
- }
- }
+ return a->getRemainingLength();
+}
- if (name.entry != nullptr || name.entry16 != nullptr) {
- if (!result.empty()) {
- result += "/";
+static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
+ jstring path, jboolean appAsLib)
+{
+ ScopedUtfChars path8(env, path);
+ if (path8.c_str() == NULL) {
+ return 0;
}
- if (name.entry != nullptr) {
- result.append(name.entry, name.entry_len);
- } else {
- result += util::Utf16ToUtf8(StringPiece16(name.entry16, name.entry_len));
- }
- }
- return env->NewStringUTF(result.c_str());
-}
-
-static jstring NativeGetResourcePackageName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- AssetManager2::ResourceName name;
- if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
- return nullptr;
- }
-
- if (name.package != nullptr) {
- return env->NewStringUTF(name.package);
- }
- return nullptr;
-}
-
-static jstring NativeGetResourceTypeName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- AssetManager2::ResourceName name;
- if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
- return nullptr;
- }
-
- if (name.type != nullptr) {
- return env->NewStringUTF(name.type);
- } else if (name.type16 != nullptr) {
- return env->NewString(reinterpret_cast<const jchar*>(name.type16), name.type_len);
- }
- return nullptr;
-}
-
-static jstring NativeGetResourceEntryName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- AssetManager2::ResourceName name;
- if (!assetmanager->GetResourceName(static_cast<uint32_t>(resid), &name)) {
- return nullptr;
- }
-
- if (name.entry != nullptr) {
- return env->NewStringUTF(name.entry);
- } else if (name.entry16 != nullptr) {
- return env->NewString(reinterpret_cast<const jchar*>(name.entry16), name.entry_len);
- }
- return nullptr;
-}
-
-static jobjectArray NativeGetLocales(JNIEnv* env, jclass /*class*/, jlong ptr,
- jboolean exclude_system) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- std::set<std::string> locales =
- assetmanager->GetResourceLocales(exclude_system, true /*merge_equivalent_languages*/);
-
- jobjectArray array = env->NewObjectArray(locales.size(), g_stringClass, nullptr);
- if (array == nullptr) {
- return nullptr;
- }
-
- size_t idx = 0;
- for (const std::string& locale : locales) {
- jstring java_string = env->NewStringUTF(locale.c_str());
- if (java_string == nullptr) {
- return nullptr;
- }
- env->SetObjectArrayElement(array, idx++, java_string);
- env->DeleteLocalRef(java_string);
- }
- return array;
-}
-
-static jobject ConstructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
- jobject result =
- env->NewObject(gConfigurationOffsets.classObject, gConfigurationOffsets.constructor);
- if (result == nullptr) {
- return nullptr;
- }
-
- env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
- config.smallestScreenWidthDp);
- env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
- env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
- return result;
-}
-
-static jobjectArray NativeGetSizeConfigurations(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- std::set<ResTable_config> configurations =
- assetmanager->GetResourceConfigurations(true /*exclude_system*/, false /*exclude_mipmap*/);
-
- jobjectArray array =
- env->NewObjectArray(configurations.size(), gConfigurationOffsets.classObject, nullptr);
- if (array == nullptr) {
- return nullptr;
- }
-
- size_t idx = 0;
- for (const ResTable_config& configuration : configurations) {
- jobject java_configuration = ConstructConfigurationObject(env, configuration);
- if (java_configuration == nullptr) {
- return nullptr;
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
}
- env->SetObjectArrayElement(array, idx++, java_configuration);
- env->DeleteLocalRef(java_configuration);
- }
- return array;
+ int32_t cookie;
+ bool res = am->addAssetPath(String8(path8.c_str()), &cookie, appAsLib);
+
+ return (res) ? static_cast<jint>(cookie) : 0;
}
-static void NativeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
- jint def_style_attr, jint def_style_resid, jlong xml_parser_ptr,
- jintArray java_attrs, jlong out_values_ptr, jlong out_indices_ptr) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
- CHECK(theme->GetAssetManager() == &(*assetmanager));
- (void) assetmanager;
+static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
+ jstring idmapPath)
+{
+ ScopedUtfChars idmapPath8(env, idmapPath);
+ if (idmapPath8.c_str() == NULL) {
+ return 0;
+ }
- ResXMLParser* xml_parser = reinterpret_cast<ResXMLParser*>(xml_parser_ptr);
- uint32_t* out_values = reinterpret_cast<uint32_t*>(out_values_ptr);
- uint32_t* out_indices = reinterpret_cast<uint32_t*>(out_indices_ptr);
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
- jsize attrs_len = env->GetArrayLength(java_attrs);
- jint* attrs = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_attrs, nullptr));
- if (attrs == nullptr) {
- return;
- }
+ int32_t cookie;
+ bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
- ApplyStyle(theme, xml_parser, static_cast<uint32_t>(def_style_attr),
- static_cast<uint32_t>(def_style_resid), reinterpret_cast<uint32_t*>(attrs), attrs_len,
- out_values, out_indices);
- env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
+ return (res) ? (jint)cookie : 0;
}
-static jboolean NativeResolveAttrs(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
- jint def_style_attr, jint def_style_resid, jintArray java_values,
- jintArray java_attrs, jintArray out_java_values,
- jintArray out_java_indices) {
- const jsize attrs_len = env->GetArrayLength(java_attrs);
- const jsize out_values_len = env->GetArrayLength(out_java_values);
- if (out_values_len < (attrs_len * STYLE_NUM_ENTRIES)) {
- jniThrowException(env, "java/lang/IndexOutOfBoundsException", "outValues too small");
- return JNI_FALSE;
- }
+static jint android_content_AssetManager_addAssetFd(JNIEnv* env, jobject clazz,
+ jobject fileDescriptor, jstring debugPathName,
+ jboolean appAsLib)
+{
+ ScopedUtfChars debugPathName8(env, debugPathName);
- jint* attrs = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_attrs, nullptr));
- if (attrs == nullptr) {
- return JNI_FALSE;
- }
-
- jint* values = nullptr;
- jsize values_len = 0;
- if (java_values != nullptr) {
- values_len = env->GetArrayLength(java_values);
- values = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_values, nullptr));
- if (values == nullptr) {
- env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
- return JNI_FALSE;
+ int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+ if (fd < 0) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "Bad FileDescriptor");
+ return 0;
}
- }
- jint* out_values =
- reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_values, nullptr));
- if (out_values == nullptr) {
- env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
- if (values != nullptr) {
- env->ReleasePrimitiveArrayCritical(java_values, values, JNI_ABORT);
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
}
- return JNI_FALSE;
- }
- jint* out_indices = nullptr;
- if (out_java_indices != nullptr) {
- jsize out_indices_len = env->GetArrayLength(out_java_indices);
- if (out_indices_len > attrs_len) {
- out_indices =
- reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_indices, nullptr));
- if (out_indices == nullptr) {
- env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
- if (values != nullptr) {
- env->ReleasePrimitiveArrayCritical(java_values, values, JNI_ABORT);
+ int dupfd = ::dup(fd);
+ if (dupfd < 0) {
+ jniThrowIOException(env, errno);
+ return 0;
+ }
+
+ int32_t cookie;
+ bool res = am->addAssetFd(dupfd, String8(debugPathName8.c_str()), &cookie, appAsLib);
+
+ return (res) ? static_cast<jint>(cookie) : 0;
+}
+
+static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return JNI_TRUE;
+ }
+ return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
+}
+
+static jobjectArray getLocales(JNIEnv* env, jobject clazz, bool includeSystemLocales)
+{
+ Vector<String8> locales;
+
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+
+ am->getLocales(&locales, includeSystemLocales);
+
+ const int N = locales.size();
+
+ jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ for (int i=0; i<N; i++) {
+ jstring str = env->NewStringUTF(locales[i].string());
+ if (str == NULL) {
+ return NULL;
}
- env->ReleasePrimitiveArrayCritical(out_java_values, out_values, JNI_ABORT);
+ env->SetObjectArrayElement(result, i, str);
+ env->DeleteLocalRef(str);
+ }
+
+ return result;
+}
+
+static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
+{
+ return getLocales(env, clazz, true /* include system locales */);
+}
+
+static jobjectArray android_content_AssetManager_getNonSystemLocales(JNIEnv* env, jobject clazz)
+{
+ return getLocales(env, clazz, false /* don't include system locales */);
+}
+
+static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
+ jobject result = env->NewObject(gConfigurationOffsets.classObject,
+ gConfigurationOffsets.constructor);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
+ config.smallestScreenWidthDp);
+ env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
+ env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
+
+ return result;
+}
+
+static jobjectArray getSizeConfigurationsInternal(JNIEnv* env,
+ const Vector<ResTable_config>& configs) {
+ const int N = configs.size();
+ jobjectArray result = env->NewObjectArray(N, gConfigurationOffsets.classObject, NULL);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ for (int i=0; i<N; i++) {
+ jobject config = constructConfigurationObject(env, configs[i]);
+ if (config == NULL) {
+ env->DeleteLocalRef(result);
+ return NULL;
+ }
+
+ env->SetObjectArrayElement(result, i, config);
+ env->DeleteLocalRef(config);
+ }
+
+ return result;
+}
+
+static jobjectArray android_content_AssetManager_getSizeConfigurations(JNIEnv* env, jobject clazz) {
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+
+ const ResTable& res(am->getResources());
+ Vector<ResTable_config> configs;
+ res.getConfigurations(&configs, false /* ignoreMipmap */, true /* ignoreAndroidPackage */);
+
+ return getSizeConfigurationsInternal(env, configs);
+}
+
+static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
+ jint mcc, jint mnc,
+ jstring locale, jint orientation,
+ jint touchscreen, jint density,
+ jint keyboard, jint keyboardHidden,
+ jint navigation,
+ jint screenWidth, jint screenHeight,
+ jint smallestScreenWidthDp,
+ jint screenWidthDp, jint screenHeightDp,
+ jint screenLayout, jint uiMode,
+ jint colorMode, jint sdkVersion)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return;
+ }
+
+ ResTable_config config;
+ memset(&config, 0, sizeof(config));
+
+ const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
+
+ // Constants duplicated from Java class android.content.res.Configuration.
+ static const jint kScreenLayoutRoundMask = 0x300;
+ static const jint kScreenLayoutRoundShift = 8;
+
+ config.mcc = (uint16_t)mcc;
+ config.mnc = (uint16_t)mnc;
+ config.orientation = (uint8_t)orientation;
+ config.touchscreen = (uint8_t)touchscreen;
+ config.density = (uint16_t)density;
+ config.keyboard = (uint8_t)keyboard;
+ config.inputFlags = (uint8_t)keyboardHidden;
+ config.navigation = (uint8_t)navigation;
+ config.screenWidth = (uint16_t)screenWidth;
+ config.screenHeight = (uint16_t)screenHeight;
+ config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
+ config.screenWidthDp = (uint16_t)screenWidthDp;
+ config.screenHeightDp = (uint16_t)screenHeightDp;
+ config.screenLayout = (uint8_t)screenLayout;
+ config.uiMode = (uint8_t)uiMode;
+ config.colorMode = (uint8_t)colorMode;
+ config.sdkVersion = (uint16_t)sdkVersion;
+ config.minorVersion = 0;
+
+ // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
+ // in C++. We must extract the round qualifier out of the Java screenLayout and put it
+ // into screenLayout2.
+ config.screenLayout2 =
+ (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
+
+ am->setConfiguration(config, locale8);
+
+ if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
+}
+
+static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
+ jstring name,
+ jstring defType,
+ jstring defPackage)
+{
+ ScopedStringChars name16(env, name);
+ if (name16.get() == NULL) {
+ return 0;
+ }
+
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+
+ const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
+ ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
+ : NULL;
+ jsize defTypeLen = defType
+ ? env->GetStringLength(defType) : 0;
+ const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
+ ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
+ NULL))
+ : NULL;
+ jsize defPackageLen = defPackage
+ ? env->GetStringLength(defPackage) : 0;
+
+ jint ident = am->getResources().identifierForName(
+ reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
+ defType16, defTypeLen, defPackage16, defPackageLen);
+
+ if (defPackage16) {
+ env->ReleaseStringChars(defPackage,
+ reinterpret_cast<const jchar*>(defPackage16));
+ }
+ if (defType16) {
+ env->ReleaseStringChars(defType,
+ reinterpret_cast<const jchar*>(defType16));
+ }
+
+ return ident;
+}
+
+static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
+ jint resid)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+
+ ResTable::resource_name name;
+ if (!am->getResources().getResourceName(resid, true, &name)) {
+ return NULL;
+ }
+
+ String16 str;
+ if (name.package != NULL) {
+ str.setTo(name.package, name.packageLen);
+ }
+ if (name.type8 != NULL || name.type != NULL) {
+ if (str.size() > 0) {
+ char16_t div = ':';
+ str.append(&div, 1);
+ }
+ if (name.type8 != NULL) {
+ str.append(String16(name.type8, name.typeLen));
+ } else {
+ str.append(name.type, name.typeLen);
+ }
+ }
+ if (name.name8 != NULL || name.name != NULL) {
+ if (str.size() > 0) {
+ char16_t div = '/';
+ str.append(&div, 1);
+ }
+ if (name.name8 != NULL) {
+ str.append(String16(name.name8, name.nameLen));
+ } else {
+ str.append(name.name, name.nameLen);
+ }
+ }
+
+ return env->NewString((const jchar*)str.string(), str.size());
+}
+
+static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
+ jint resid)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+
+ ResTable::resource_name name;
+ if (!am->getResources().getResourceName(resid, true, &name)) {
+ return NULL;
+ }
+
+ if (name.package != NULL) {
+ return env->NewString((const jchar*)name.package, name.packageLen);
+ }
+
+ return NULL;
+}
+
+static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
+ jint resid)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+
+ ResTable::resource_name name;
+ if (!am->getResources().getResourceName(resid, true, &name)) {
+ return NULL;
+ }
+
+ if (name.type8 != NULL) {
+ return env->NewStringUTF(name.type8);
+ }
+
+ if (name.type != NULL) {
+ return env->NewString((const jchar*)name.type, name.typeLen);
+ }
+
+ return NULL;
+}
+
+static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
+ jint resid)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+
+ ResTable::resource_name name;
+ if (!am->getResources().getResourceName(resid, true, &name)) {
+ return NULL;
+ }
+
+ if (name.name8 != NULL) {
+ return env->NewStringUTF(name.name8);
+ }
+
+ if (name.name != NULL) {
+ return env->NewString((const jchar*)name.name, name.nameLen);
+ }
+
+ return NULL;
+}
+
+static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
+ jint ident,
+ jshort density,
+ jobject outValue,
+ jboolean resolve)
+{
+ if (outValue == NULL) {
+ jniThrowNullPointerException(env, "outValue");
+ return 0;
+ }
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+ const ResTable& res(am->getResources());
+
+ Res_value value;
+ ResTable_config config;
+ uint32_t typeSpecFlags;
+ ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
+ if (kThrowOnBadId) {
+ if (block == BAD_INDEX) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+ return 0;
+ }
+ }
+ uint32_t ref = ident;
+ if (resolve) {
+ block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
+ if (kThrowOnBadId) {
+ if (block == BAD_INDEX) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+ return 0;
+ }
+ }
+ }
+ if (block >= 0) {
+ return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
+ }
+
+ return static_cast<jint>(block);
+}
+
+static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
+ jint ident, jint bagEntryId,
+ jobject outValue, jboolean resolve)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+ const ResTable& res(am->getResources());
+
+ // Now lock down the resource object and start pulling stuff from it.
+ res.lock();
+
+ ssize_t block = -1;
+ Res_value value;
+
+ const ResTable::bag_entry* entry = NULL;
+ uint32_t typeSpecFlags;
+ ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
+
+ for (ssize_t i=0; i<entryCount; i++) {
+ if (((uint32_t)bagEntryId) == entry->map.name.ident) {
+ block = entry->stringBlock;
+ value = entry->map.value;
+ }
+ entry++;
+ }
+
+ res.unlock();
+
+ if (block < 0) {
+ return static_cast<jint>(block);
+ }
+
+ uint32_t ref = ident;
+ if (resolve) {
+ block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
+ if (kThrowOnBadId) {
+ if (block == BAD_INDEX) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+ return 0;
+ }
+ }
+ }
+ if (block >= 0) {
+ return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
+ }
+
+ return static_cast<jint>(block);
+}
+
+static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+ return am->getResources().getTableCount();
+}
+
+static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
+ jint block)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+ return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
+}
+
+static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
+ jint cookie)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+ String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
+ if (name.length() == 0) {
+ jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
+ return NULL;
+ }
+ jstring str = env->NewStringUTF(name.string());
+ return str;
+}
+
+static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+
+ const ResTable& res = am->getResources();
+
+ jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
+ gSparseArrayOffsets.constructor);
+ const size_t N = res.getBasePackageCount();
+ for (size_t i = 0; i < N; i++) {
+ const String16 name = res.getBasePackageName(i);
+ env->CallVoidMethod(
+ sparseArray, gSparseArrayOffsets.put,
+ static_cast<jint>(res.getBasePackageId(i)),
+ env->NewString(reinterpret_cast<const jchar*>(name.string()),
+ name.size()));
+ }
+ return sparseArray;
+}
+
+static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+ return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
+}
+
+static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
+ jlong themeHandle)
+{
+ ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+ delete theme;
+}
+
+static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
+ jlong themeHandle,
+ jint styleRes,
+ jboolean force)
+{
+ ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+ theme->applyStyle(styleRes, force ? true : false);
+}
+
+static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
+ jlong destHandle, jlong srcHandle)
+{
+ ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
+ ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
+ dest->setTo(*src);
+}
+
+static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
+{
+ ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+ theme->clear();
+}
+
+static jint android_content_AssetManager_loadThemeAttributeValue(
+ JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
+{
+ ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+ const ResTable& res(theme->getResTable());
+
+ Res_value value;
+ // XXX value could be different in different configs!
+ uint32_t typeSpecFlags = 0;
+ ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
+ uint32_t ref = 0;
+ if (resolve) {
+ block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
+ if (kThrowOnBadId) {
+ if (block == BAD_INDEX) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+ return 0;
+ }
+ }
+ }
+ return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
+}
+
+static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
+ jlong themeHandle)
+{
+ ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+ return theme->getChangingConfigurations();
+}
+
+static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
+ jlong themeHandle, jint pri,
+ jstring tag, jstring prefix)
+{
+ ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
+ const ResTable& res(theme->getResTable());
+ (void)res;
+
+ // XXX Need to use params.
+ theme->dumpToLog();
+}
+
+static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
+ jlong themeToken,
+ jint defStyleAttr,
+ jint defStyleRes,
+ jintArray inValues,
+ jintArray attrs,
+ jintArray outValues,
+ jintArray outIndices)
+{
+ if (themeToken == 0) {
+ jniThrowNullPointerException(env, "theme token");
return JNI_FALSE;
- }
}
- }
-
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
- CHECK(theme->GetAssetManager() == &(*assetmanager));
- (void) assetmanager;
-
- bool result = ResolveAttrs(
- theme, static_cast<uint32_t>(def_style_attr), static_cast<uint32_t>(def_style_resid),
- reinterpret_cast<uint32_t*>(values), values_len, reinterpret_cast<uint32_t*>(attrs),
- attrs_len, reinterpret_cast<uint32_t*>(out_values), reinterpret_cast<uint32_t*>(out_indices));
- if (out_indices != nullptr) {
- env->ReleasePrimitiveArrayCritical(out_java_indices, out_indices, 0);
- }
-
- env->ReleasePrimitiveArrayCritical(out_java_values, out_values, 0);
- if (values != nullptr) {
- env->ReleasePrimitiveArrayCritical(java_values, values, JNI_ABORT);
- }
- env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
- return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean NativeRetrieveAttributes(JNIEnv* env, jclass /*clazz*/, jlong ptr,
- jlong xml_parser_ptr, jintArray java_attrs,
- jintArray out_java_values, jintArray out_java_indices) {
- const jsize attrs_len = env->GetArrayLength(java_attrs);
- const jsize out_values_len = env->GetArrayLength(out_java_values);
- if (out_values_len < (attrs_len * STYLE_NUM_ENTRIES)) {
- jniThrowException(env, "java/lang/IndexOutOfBoundsException", "outValues too small");
- return JNI_FALSE;
- }
-
- jint* attrs = reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(java_attrs, nullptr));
- if (attrs == nullptr) {
- return JNI_FALSE;
- }
-
- jint* out_values =
- reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_values, nullptr));
- if (out_values == nullptr) {
- env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
- return JNI_FALSE;
- }
-
- jint* out_indices = nullptr;
- if (out_java_indices != nullptr) {
- jsize out_indices_len = env->GetArrayLength(out_java_indices);
- if (out_indices_len > attrs_len) {
- out_indices =
- reinterpret_cast<jint*>(env->GetPrimitiveArrayCritical(out_java_indices, nullptr));
- if (out_indices == nullptr) {
- env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
- env->ReleasePrimitiveArrayCritical(out_java_values, out_values, JNI_ABORT);
+ if (attrs == NULL) {
+ jniThrowNullPointerException(env, "attrs");
return JNI_FALSE;
- }
}
- }
-
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- ResXMLParser* xml_parser = reinterpret_cast<ResXMLParser*>(xml_parser_ptr);
-
- bool result = RetrieveAttributes(assetmanager.get(), xml_parser,
- reinterpret_cast<uint32_t*>(attrs), attrs_len,
- reinterpret_cast<uint32_t*>(out_values),
- reinterpret_cast<uint32_t*>(out_indices));
-
- if (out_indices != nullptr) {
- env->ReleasePrimitiveArrayCritical(out_java_indices, out_indices, 0);
- }
- env->ReleasePrimitiveArrayCritical(out_java_values, out_values, 0);
- env->ReleasePrimitiveArrayCritical(java_attrs, attrs, JNI_ABORT);
- return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jlong NativeThemeCreate(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- return reinterpret_cast<jlong>(assetmanager->NewTheme().release());
-}
-
-static void NativeThemeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong theme_ptr) {
- delete reinterpret_cast<Theme*>(theme_ptr);
-}
-
-static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
- jint resid, jboolean force) {
- // AssetManager is accessed via the theme, so grab an explicit lock here.
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
- CHECK(theme->GetAssetManager() == &(*assetmanager));
- (void) assetmanager;
- theme->ApplyStyle(static_cast<uint32_t>(resid), force);
-
- // TODO(adamlesinski): Consider surfacing exception when result is failure.
- // CTS currently expects no exceptions from this method.
- // std::string error_msg = StringPrintf("Failed to apply style 0x%08x to theme", resid);
- // jniThrowException(env, "java/lang/IllegalArgumentException", error_msg.c_str());
-}
-
-static void NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_theme_ptr,
- jlong src_theme_ptr) {
- Theme* dst_theme = reinterpret_cast<Theme*>(dst_theme_ptr);
- Theme* src_theme = reinterpret_cast<Theme*>(src_theme_ptr);
- if (!dst_theme->SetTo(*src_theme)) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "Themes are from different AssetManagers");
- }
-}
-
-static void NativeThemeClear(JNIEnv* /*env*/, jclass /*clazz*/, jlong theme_ptr) {
- reinterpret_cast<Theme*>(theme_ptr)->Clear();
-}
-
-static jint NativeThemeGetAttributeValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
- jint resid, jobject typed_value,
- jboolean resolve_references) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
- CHECK(theme->GetAssetManager() == &(*assetmanager));
- (void) assetmanager;
-
- Res_value value;
- uint32_t flags;
- ApkAssetsCookie cookie = theme->GetAttribute(static_cast<uint32_t>(resid), &value, &flags);
- if (cookie == kInvalidCookie) {
- return ApkAssetsCookieToJavaCookie(kInvalidCookie);
- }
-
- uint32_t ref = 0u;
- if (resolve_references) {
- ResTable_config selected_config;
- cookie =
- theme->GetAssetManager()->ResolveReference(cookie, &value, &selected_config, &flags, &ref);
- if (cookie == kInvalidCookie) {
- return ApkAssetsCookieToJavaCookie(kInvalidCookie);
+ if (outValues == NULL) {
+ jniThrowNullPointerException(env, "out values");
+ return JNI_FALSE;
}
- }
- return CopyValue(env, cookie, value, ref, flags, nullptr, typed_value);
+
+ const jsize NI = env->GetArrayLength(attrs);
+ const jsize NV = env->GetArrayLength(outValues);
+ if (NV < (NI*STYLE_NUM_ENTRIES)) {
+ jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
+ return JNI_FALSE;
+ }
+
+ jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
+ if (src == NULL) {
+ return JNI_FALSE;
+ }
+
+ jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
+ const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
+
+ jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
+ if (baseDest == NULL) {
+ env->ReleasePrimitiveArrayCritical(attrs, src, 0);
+ return JNI_FALSE;
+ }
+
+ jint* indices = NULL;
+ if (outIndices != NULL) {
+ if (env->GetArrayLength(outIndices) > NI) {
+ indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
+ }
+ }
+
+ ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
+ bool result = ResolveAttrs(theme, defStyleAttr, defStyleRes,
+ (uint32_t*) srcValues, NSV,
+ (uint32_t*) src, NI,
+ (uint32_t*) baseDest,
+ (uint32_t*) indices);
+
+ if (indices != NULL) {
+ env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
+ }
+ env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
+ env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
+ env->ReleasePrimitiveArrayCritical(attrs, src, 0);
+ return result ? JNI_TRUE : JNI_FALSE;
}
-static void NativeThemeDump(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
- jint priority, jstring tag, jstring prefix) {
- ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
- Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
- CHECK(theme->GetAssetManager() == &(*assetmanager));
- (void) assetmanager;
- (void) theme;
- (void) priority;
- (void) tag;
- (void) prefix;
+static void android_content_AssetManager_applyStyle(JNIEnv* env, jobject, jlong themeToken,
+ jint defStyleAttr, jint defStyleRes, jlong xmlParserToken, jintArray attrsObj, jint length,
+ jlong outValuesAddress, jlong outIndicesAddress) {
+ jint* attrs = env->GetIntArrayElements(attrsObj, 0);
+ ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
+ ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
+ uint32_t* outValues = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outValuesAddress));
+ uint32_t* outIndices = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outIndicesAddress));
+ ApplyStyle(theme, xmlParser, defStyleAttr, defStyleRes,
+ reinterpret_cast<const uint32_t*>(attrs), length, outValues, outIndices);
+ env->ReleaseIntArrayElements(attrsObj, attrs, JNI_ABORT);
}
-static jint NativeThemeGetChangingConfigurations(JNIEnv* /*env*/, jclass /*clazz*/,
- jlong theme_ptr) {
- Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
- return static_cast<jint>(theme->GetChangingConfigurations());
+static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
+ jlong xmlParserToken,
+ jintArray attrs,
+ jintArray outValues,
+ jintArray outIndices)
+{
+ if (xmlParserToken == 0) {
+ jniThrowNullPointerException(env, "xmlParserToken");
+ return JNI_FALSE;
+ }
+ if (attrs == NULL) {
+ jniThrowNullPointerException(env, "attrs");
+ return JNI_FALSE;
+ }
+ if (outValues == NULL) {
+ jniThrowNullPointerException(env, "out values");
+ return JNI_FALSE;
+ }
+
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return JNI_FALSE;
+ }
+ const ResTable& res(am->getResources());
+ ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
+
+ const jsize NI = env->GetArrayLength(attrs);
+ const jsize NV = env->GetArrayLength(outValues);
+ if (NV < (NI*STYLE_NUM_ENTRIES)) {
+ jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
+ return JNI_FALSE;
+ }
+
+ jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
+ if (src == NULL) {
+ return JNI_FALSE;
+ }
+
+ jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
+ if (baseDest == NULL) {
+ env->ReleasePrimitiveArrayCritical(attrs, src, 0);
+ return JNI_FALSE;
+ }
+
+ jint* indices = NULL;
+ if (outIndices != NULL) {
+ if (env->GetArrayLength(outIndices) > NI) {
+ indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
+ }
+ }
+
+ bool result = RetrieveAttributes(&res, xmlParser,
+ (uint32_t*) src, NI,
+ (uint32_t*) baseDest,
+ (uint32_t*) indices);
+
+ if (indices != NULL) {
+ env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
+ }
+ env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
+ env->ReleasePrimitiveArrayCritical(attrs, src, 0);
+ return result ? JNI_TRUE : JNI_FALSE;
}
-static void NativeAssetDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
- delete reinterpret_cast<Asset*>(asset_ptr);
+static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
+ jint id)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+ const ResTable& res(am->getResources());
+
+ res.lock();
+ const ResTable::bag_entry* defStyleEnt = NULL;
+ ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
+ res.unlock();
+
+ return static_cast<jint>(bagOff);
}
-static jint NativeAssetReadChar(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
- Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
- uint8_t b;
- ssize_t res = asset->read(&b, sizeof(b));
- return res == sizeof(b) ? static_cast<jint>(b) : -1;
+static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
+ jint id,
+ jintArray outValues)
+{
+ if (outValues == NULL) {
+ jniThrowNullPointerException(env, "out values");
+ return JNI_FALSE;
+ }
+
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return JNI_FALSE;
+ }
+ const ResTable& res(am->getResources());
+ ResTable_config config;
+ Res_value value;
+ ssize_t block;
+
+ const jsize NV = env->GetArrayLength(outValues);
+
+ jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
+ jint* dest = baseDest;
+ if (dest == NULL) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", "");
+ return JNI_FALSE;
+ }
+
+ // Now lock down the resource object and start pulling stuff from it.
+ res.lock();
+
+ const ResTable::bag_entry* arrayEnt = NULL;
+ uint32_t arrayTypeSetFlags = 0;
+ ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
+ const ResTable::bag_entry* endArrayEnt = arrayEnt +
+ (bagOff >= 0 ? bagOff : 0);
+
+ int i = 0;
+ uint32_t typeSetFlags;
+ while (i < NV && arrayEnt < endArrayEnt) {
+ block = arrayEnt->stringBlock;
+ typeSetFlags = arrayTypeSetFlags;
+ config.density = 0;
+ value = arrayEnt->map.value;
+
+ uint32_t resid = 0;
+ if (value.dataType != Res_value::TYPE_NULL) {
+ // Take care of resolving the found resource to its final value.
+ //printf("Resolving attribute reference\n");
+ ssize_t newBlock = res.resolveReference(&value, block, &resid,
+ &typeSetFlags, &config);
+ if (kThrowOnBadId) {
+ if (newBlock == BAD_INDEX) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+ return JNI_FALSE;
+ }
+ }
+ if (newBlock >= 0) block = newBlock;
+ }
+
+ // Deal with the special @null value -- it turns back to TYPE_NULL.
+ if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
+ value.dataType = Res_value::TYPE_NULL;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
+ }
+
+ //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
+
+ // Write the final value back to Java.
+ dest[STYLE_TYPE] = value.dataType;
+ dest[STYLE_DATA] = value.data;
+ dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
+ dest[STYLE_RESOURCE_ID] = resid;
+ dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+ dest[STYLE_DENSITY] = config.density;
+ dest += STYLE_NUM_ENTRIES;
+ i+= STYLE_NUM_ENTRIES;
+ arrayEnt++;
+ }
+
+ i /= STYLE_NUM_ENTRIES;
+
+ res.unlock();
+
+ env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
+
+ return i;
}
-static jint NativeAssetRead(JNIEnv* env, jclass /*clazz*/, jlong asset_ptr, jbyteArray java_buffer,
- jint offset, jint len) {
- if (len == 0) {
- return 0;
- }
+static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
+ jint cookie,
+ jstring fileName)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
- jsize buffer_len = env->GetArrayLength(java_buffer);
- if (offset < 0 || offset >= buffer_len || len < 0 || len > buffer_len ||
- offset > buffer_len - len) {
- jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
- return -1;
- }
+ ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
- ScopedByteArrayRW byte_array(env, java_buffer);
- if (byte_array.get() == nullptr) {
- return -1;
- }
+ ScopedUtfChars fileName8(env, fileName);
+ if (fileName8.c_str() == NULL) {
+ return 0;
+ }
- Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
- ssize_t res = asset->read(byte_array.get() + offset, len);
- if (res < 0) {
- jniThrowException(env, "java/io/IOException", "");
- return -1;
- }
- return res > 0 ? static_cast<jint>(res) : -1;
+ int32_t assetCookie = static_cast<int32_t>(cookie);
+ Asset* a = assetCookie
+ ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
+ : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
+
+ if (a == NULL) {
+ jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
+ return 0;
+ }
+
+ const DynamicRefTable* dynamicRefTable =
+ am->getResources().getDynamicRefTableForCookie(assetCookie);
+ ResXMLTree* block = new ResXMLTree(dynamicRefTable);
+ status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
+ a->close();
+ delete a;
+
+ if (err != NO_ERROR) {
+ jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
+ return 0;
+ }
+
+ return reinterpret_cast<jlong>(block);
}
-static jlong NativeAssetSeek(JNIEnv* env, jclass /*clazz*/, jlong asset_ptr, jlong offset,
- jint whence) {
- Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
- return static_cast<jlong>(asset->seek(
- static_cast<off64_t>(offset), (whence > 0 ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR))));
+static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
+ jint arrayResId)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+ const ResTable& res(am->getResources());
+
+ const ResTable::bag_entry* startOfBag;
+ const ssize_t N = res.lockBag(arrayResId, &startOfBag);
+ if (N < 0) {
+ return NULL;
+ }
+
+ jintArray array = env->NewIntArray(N * 2);
+ if (array == NULL) {
+ res.unlockBag(startOfBag);
+ return NULL;
+ }
+
+ Res_value value;
+ const ResTable::bag_entry* bag = startOfBag;
+ for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
+ jint stringIndex = -1;
+ jint stringBlock = 0;
+ value = bag->map.value;
+
+ // Take care of resolving the found resource to its final value.
+ stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
+ if (value.dataType == Res_value::TYPE_STRING) {
+ stringIndex = value.data;
+ }
+
+ if (kThrowOnBadId) {
+ if (stringBlock == BAD_INDEX) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+ return array;
+ }
+ }
+
+ //todo: It might be faster to allocate a C array to contain
+ // the blocknums and indices, put them in there and then
+ // do just one SetIntArrayRegion()
+ env->SetIntArrayRegion(array, j, 1, &stringBlock);
+ env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
+ j = j + 2;
+ }
+ res.unlockBag(startOfBag);
+ return array;
}
-static jlong NativeAssetGetLength(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
- Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
- return static_cast<jlong>(asset->getLength());
+static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
+ jint arrayResId)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+ const ResTable& res(am->getResources());
+
+ const ResTable::bag_entry* startOfBag;
+ const ssize_t N = res.lockBag(arrayResId, &startOfBag);
+ if (N < 0) {
+ return NULL;
+ }
+
+ jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
+ if (env->ExceptionCheck()) {
+ res.unlockBag(startOfBag);
+ return NULL;
+ }
+
+ Res_value value;
+ const ResTable::bag_entry* bag = startOfBag;
+ size_t strLen = 0;
+ for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
+ value = bag->map.value;
+ jstring str = NULL;
+
+ // Take care of resolving the found resource to its final value.
+ ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
+ if (kThrowOnBadId) {
+ if (block == BAD_INDEX) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+ return array;
+ }
+ }
+ if (value.dataType == Res_value::TYPE_STRING) {
+ const ResStringPool* pool = res.getTableStringBlock(block);
+ const char* str8 = pool->string8At(value.data, &strLen);
+ if (str8 != NULL) {
+ str = env->NewStringUTF(str8);
+ } else {
+ const char16_t* str16 = pool->stringAt(value.data, &strLen);
+ str = env->NewString(reinterpret_cast<const jchar*>(str16),
+ strLen);
+ }
+
+ // If one of our NewString{UTF} calls failed due to memory, an
+ // exception will be pending.
+ if (env->ExceptionCheck()) {
+ res.unlockBag(startOfBag);
+ return NULL;
+ }
+
+ env->SetObjectArrayElement(array, i, str);
+
+ // str is not NULL at that point, otherwise ExceptionCheck would have been true.
+ // If we have a large amount of strings in our array, we might
+ // overflow the local reference table of the VM.
+ env->DeleteLocalRef(str);
+ }
+ }
+ res.unlockBag(startOfBag);
+ return array;
}
-static jlong NativeAssetGetRemainingLength(JNIEnv* /*env*/, jclass /*clazz*/, jlong asset_ptr) {
- Asset* asset = reinterpret_cast<Asset*>(asset_ptr);
- return static_cast<jlong>(asset->getRemainingLength());
+static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
+ jint arrayResId)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+ const ResTable& res(am->getResources());
+
+ const ResTable::bag_entry* startOfBag;
+ const ssize_t N = res.lockBag(arrayResId, &startOfBag);
+ if (N < 0) {
+ return NULL;
+ }
+
+ jintArray array = env->NewIntArray(N);
+ if (array == NULL) {
+ res.unlockBag(startOfBag);
+ return NULL;
+ }
+
+ Res_value value;
+ const ResTable::bag_entry* bag = startOfBag;
+ for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
+ value = bag->map.value;
+
+ // Take care of resolving the found resource to its final value.
+ ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
+ if (kThrowOnBadId) {
+ if (block == BAD_INDEX) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
+ return array;
+ }
+ }
+ if (value.dataType >= Res_value::TYPE_FIRST_INT
+ && value.dataType <= Res_value::TYPE_LAST_INT) {
+ int intVal = value.data;
+ env->SetIntArrayRegion(array, i, 1, &intVal);
+ }
+ }
+ res.unlockBag(startOfBag);
+ return array;
+}
+
+static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
+ jint styleId)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+ const ResTable& res(am->getResources());
+
+ const ResTable::bag_entry* startOfBag;
+ const ssize_t N = res.lockBag(styleId, &startOfBag);
+ if (N < 0) {
+ return NULL;
+ }
+
+ jintArray array = env->NewIntArray(N);
+ if (array == NULL) {
+ res.unlockBag(startOfBag);
+ return NULL;
+ }
+
+ const ResTable::bag_entry* bag = startOfBag;
+ for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
+ int resourceId = bag->map.name.ident;
+ env->SetIntArrayRegion(array, i, 1, &resourceId);
+ }
+ res.unlockBag(startOfBag);
+ return array;
+}
+
+static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
+{
+ if (isSystem) {
+ verifySystemIdmaps();
+ }
+ AssetManager* am = new AssetManager();
+ if (am == NULL) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", "");
+ return;
+ }
+
+ am->addDefaultAssets();
+
+ ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
+ env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
+}
+
+static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
+{
+ AssetManager* am = (AssetManager*)
+ (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
+ ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
+ if (am != NULL) {
+ delete am;
+ env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
+ }
+}
+
+static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
+{
+ return Asset::getGlobalCount();
+}
+
+static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
+{
+ String8 alloc = Asset::getAssetAllocations();
+ if (alloc.length() <= 0) {
+ return NULL;
+ }
+
+ jstring str = env->NewStringUTF(alloc.string());
+ return str;
+}
+
+static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
+{
+ return AssetManager::getGlobalCount();
}
// ----------------------------------------------------------------------------
-// JNI registration.
+/*
+ * JNI registration.
+ */
static const JNINativeMethod gAssetManagerMethods[] = {
- // AssetManager setup methods.
- {"nativeCreate", "()J", (void*)NativeCreate},
- {"nativeDestroy", "(J)V", (void*)NativeDestroy},
- {"nativeSetApkAssets", "(J[Landroid/content/res/ApkAssets;Z)V", (void*)NativeSetApkAssets},
- {"nativeSetConfiguration", "(JIILjava/lang/String;IIIIIIIIIIIIIII)V",
- (void*)NativeSetConfiguration},
- {"nativeGetAssignedPackageIdentifiers", "(J)Landroid/util/SparseArray;",
- (void*)NativeGetAssignedPackageIdentifiers},
+ /* name, signature, funcPtr */
- // AssetManager file methods.
- {"nativeList", "(JLjava/lang/String;)[Ljava/lang/String;", (void*)NativeList},
- {"nativeOpenAsset", "(JLjava/lang/String;I)J", (void*)NativeOpenAsset},
- {"nativeOpenAssetFd", "(JLjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
- (void*)NativeOpenAssetFd},
- {"nativeOpenNonAsset", "(JILjava/lang/String;I)J", (void*)NativeOpenNonAsset},
- {"nativeOpenNonAssetFd", "(JILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
- (void*)NativeOpenNonAssetFd},
- {"nativeOpenXmlAsset", "(JILjava/lang/String;)J", (void*)NativeOpenXmlAsset},
+ // Basic asset stuff.
+ { "openAsset", "(Ljava/lang/String;I)J",
+ (void*) android_content_AssetManager_openAsset },
+ { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
+ (void*) android_content_AssetManager_openAssetFd },
+ { "openNonAssetNative", "(ILjava/lang/String;I)J",
+ (void*) android_content_AssetManager_openNonAssetNative },
+ { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
+ (void*) android_content_AssetManager_openNonAssetFdNative },
+ { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
+ (void*) android_content_AssetManager_list },
+ { "destroyAsset", "(J)V",
+ (void*) android_content_AssetManager_destroyAsset },
+ { "readAssetChar", "(J)I",
+ (void*) android_content_AssetManager_readAssetChar },
+ { "readAsset", "(J[BII)I",
+ (void*) android_content_AssetManager_readAsset },
+ { "seekAsset", "(JJI)J",
+ (void*) android_content_AssetManager_seekAsset },
+ { "getAssetLength", "(J)J",
+ (void*) android_content_AssetManager_getAssetLength },
+ { "getAssetRemainingLength", "(J)J",
+ (void*) android_content_AssetManager_getAssetRemainingLength },
+ { "addAssetPathNative", "(Ljava/lang/String;Z)I",
+ (void*) android_content_AssetManager_addAssetPath },
+ { "addAssetFdNative", "(Ljava/io/FileDescriptor;Ljava/lang/String;Z)I",
+ (void*) android_content_AssetManager_addAssetFd },
+ { "addOverlayPathNative", "(Ljava/lang/String;)I",
+ (void*) android_content_AssetManager_addOverlayPath },
+ { "isUpToDate", "()Z",
+ (void*) android_content_AssetManager_isUpToDate },
- // AssetManager resource methods.
- {"nativeGetResourceValue", "(JISLandroid/util/TypedValue;Z)I", (void*)NativeGetResourceValue},
- {"nativeGetResourceBagValue", "(JIILandroid/util/TypedValue;)I",
- (void*)NativeGetResourceBagValue},
- {"nativeGetStyleAttributes", "(JI)[I", (void*)NativeGetStyleAttributes},
- {"nativeGetResourceStringArray", "(JI)[Ljava/lang/String;",
- (void*)NativeGetResourceStringArray},
- {"nativeGetResourceStringArrayInfo", "(JI)[I", (void*)NativeGetResourceStringArrayInfo},
- {"nativeGetResourceIntArray", "(JI)[I", (void*)NativeGetResourceIntArray},
- {"nativeGetResourceArraySize", "(JI)I", (void*)NativeGetResourceArraySize},
- {"nativeGetResourceArray", "(JI[I)I", (void*)NativeGetResourceArray},
+ // Resources.
+ { "getLocales", "()[Ljava/lang/String;",
+ (void*) android_content_AssetManager_getLocales },
+ { "getNonSystemLocales", "()[Ljava/lang/String;",
+ (void*) android_content_AssetManager_getNonSystemLocales },
+ { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
+ (void*) android_content_AssetManager_getSizeConfigurations },
+ { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIIII)V",
+ (void*) android_content_AssetManager_setConfiguration },
+ { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+ (void*) android_content_AssetManager_getResourceIdentifier },
+ { "getResourceName","(I)Ljava/lang/String;",
+ (void*) android_content_AssetManager_getResourceName },
+ { "getResourcePackageName","(I)Ljava/lang/String;",
+ (void*) android_content_AssetManager_getResourcePackageName },
+ { "getResourceTypeName","(I)Ljava/lang/String;",
+ (void*) android_content_AssetManager_getResourceTypeName },
+ { "getResourceEntryName","(I)Ljava/lang/String;",
+ (void*) android_content_AssetManager_getResourceEntryName },
+ { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
+ (void*) android_content_AssetManager_loadResourceValue },
+ { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
+ (void*) android_content_AssetManager_loadResourceBagValue },
+ { "getStringBlockCount","()I",
+ (void*) android_content_AssetManager_getStringBlockCount },
+ { "getNativeStringBlock","(I)J",
+ (void*) android_content_AssetManager_getNativeStringBlock },
+ { "getCookieName","(I)Ljava/lang/String;",
+ (void*) android_content_AssetManager_getCookieName },
+ { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
+ (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
- // AssetManager resource name/ID methods.
- {"nativeGetResourceIdentifier", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
- (void*)NativeGetResourceIdentifier},
- {"nativeGetResourceName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceName},
- {"nativeGetResourcePackageName", "(JI)Ljava/lang/String;", (void*)NativeGetResourcePackageName},
- {"nativeGetResourceTypeName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceTypeName},
- {"nativeGetResourceEntryName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceEntryName},
- {"nativeGetLocales", "(JZ)[Ljava/lang/String;", (void*)NativeGetLocales},
- {"nativeGetSizeConfigurations", "(J)[Landroid/content/res/Configuration;",
- (void*)NativeGetSizeConfigurations},
+ // Themes.
+ { "newTheme", "()J",
+ (void*) android_content_AssetManager_newTheme },
+ { "deleteTheme", "(J)V",
+ (void*) android_content_AssetManager_deleteTheme },
+ { "applyThemeStyle", "(JIZ)V",
+ (void*) android_content_AssetManager_applyThemeStyle },
+ { "copyTheme", "(JJ)V",
+ (void*) android_content_AssetManager_copyTheme },
+ { "clearTheme", "(J)V",
+ (void*) android_content_AssetManager_clearTheme },
+ { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
+ (void*) android_content_AssetManager_loadThemeAttributeValue },
+ { "getThemeChangingConfigurations", "(J)I",
+ (void*) android_content_AssetManager_getThemeChangingConfigurations },
+ { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
+ (void*) android_content_AssetManager_dumpTheme },
+ { "applyStyle","(JIIJ[IIJJ)V",
+ (void*) android_content_AssetManager_applyStyle },
+ { "resolveAttrs","(JII[I[I[I[I)Z",
+ (void*) android_content_AssetManager_resolveAttrs },
+ { "retrieveAttributes","(J[I[I[I)Z",
+ (void*) android_content_AssetManager_retrieveAttributes },
+ { "getArraySize","(I)I",
+ (void*) android_content_AssetManager_getArraySize },
+ { "retrieveArray","(I[I)I",
+ (void*) android_content_AssetManager_retrieveArray },
- // Style attribute related methods.
- {"nativeApplyStyle", "(JJIIJ[IJJ)V", (void*)NativeApplyStyle},
- {"nativeResolveAttrs", "(JJII[I[I[I[I)Z", (void*)NativeResolveAttrs},
- {"nativeRetrieveAttributes", "(JJ[I[I[I)Z", (void*)NativeRetrieveAttributes},
+ // XML files.
+ { "openXmlAssetNative", "(ILjava/lang/String;)J",
+ (void*) android_content_AssetManager_openXmlAssetNative },
- // Theme related methods.
- {"nativeThemeCreate", "(J)J", (void*)NativeThemeCreate},
- {"nativeThemeDestroy", "(J)V", (void*)NativeThemeDestroy},
- {"nativeThemeApplyStyle", "(JJIZ)V", (void*)NativeThemeApplyStyle},
- {"nativeThemeCopy", "(JJ)V", (void*)NativeThemeCopy},
- {"nativeThemeClear", "(J)V", (void*)NativeThemeClear},
- {"nativeThemeGetAttributeValue", "(JJILandroid/util/TypedValue;Z)I",
- (void*)NativeThemeGetAttributeValue},
- {"nativeThemeDump", "(JJILjava/lang/String;Ljava/lang/String;)V", (void*)NativeThemeDump},
- {"nativeThemeGetChangingConfigurations", "(J)I", (void*)NativeThemeGetChangingConfigurations},
+ // Arrays.
+ { "getArrayStringResource","(I)[Ljava/lang/String;",
+ (void*) android_content_AssetManager_getArrayStringResource },
+ { "getArrayStringInfo","(I)[I",
+ (void*) android_content_AssetManager_getArrayStringInfo },
+ { "getArrayIntResource","(I)[I",
+ (void*) android_content_AssetManager_getArrayIntResource },
+ { "getStyleAttributes","(I)[I",
+ (void*) android_content_AssetManager_getStyleAttributes },
- // AssetInputStream methods.
- {"nativeAssetDestroy", "(J)V", (void*)NativeAssetDestroy},
- {"nativeAssetReadChar", "(J)I", (void*)NativeAssetReadChar},
- {"nativeAssetRead", "(J[BII)I", (void*)NativeAssetRead},
- {"nativeAssetSeek", "(JJI)J", (void*)NativeAssetSeek},
- {"nativeAssetGetLength", "(J)J", (void*)NativeAssetGetLength},
- {"nativeAssetGetRemainingLength", "(J)J", (void*)NativeAssetGetRemainingLength},
-
- // System/idmap related methods.
- {"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps},
-
- // Global management/debug methods.
- {"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount},
- {"getAssetAllocations", "()Ljava/lang/String;", (void*)NativeGetAssetAllocations},
- {"getGlobalAssetManagerCount", "()I", (void*)NativeGetGlobalAssetManagerCount},
+ // Bookkeeping.
+ { "init", "(Z)V",
+ (void*) android_content_AssetManager_init },
+ { "destroy", "()V",
+ (void*) android_content_AssetManager_destroy },
+ { "getGlobalAssetCount", "()I",
+ (void*) android_content_AssetManager_getGlobalAssetCount },
+ { "getAssetAllocations", "()Ljava/lang/String;",
+ (void*) android_content_AssetManager_getAssetAllocations },
+ { "getGlobalAssetManagerCount", "()I",
+ (void*) android_content_AssetManager_getGlobalAssetManagerCount },
};
-int register_android_content_AssetManager(JNIEnv* env) {
- jclass apk_assets_class = FindClassOrDie(env, "android/content/res/ApkAssets");
- gApkAssetsFields.native_ptr = GetFieldIDOrDie(env, apk_assets_class, "mNativePtr", "J");
+int register_android_content_AssetManager(JNIEnv* env)
+{
+ jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
+ gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
+ gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
+ gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
+ "Ljava/lang/CharSequence;");
+ gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
+ gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
+ gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
+ "changingConfigurations", "I");
+ gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
- jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
- gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
- gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
- gTypedValueOffsets.mString =
- GetFieldIDOrDie(env, typedValue, "string", "Ljava/lang/CharSequence;");
- gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
- gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
- gTypedValueOffsets.mChangingConfigurations =
- GetFieldIDOrDie(env, typedValue, "changingConfigurations", "I");
- gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
+ jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
+ gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
+ "Landroid/os/ParcelFileDescriptor;");
+ gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
+ gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
- jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
- gAssetFileDescriptorOffsets.mFd =
- GetFieldIDOrDie(env, assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
- gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
- gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
+ jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
+ gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
- jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
- gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
+ jclass stringClass = FindClassOrDie(env, "java/lang/String");
+ g_stringClass = MakeGlobalRefOrDie(env, stringClass);
- jclass stringClass = FindClassOrDie(env, "java/lang/String");
- g_stringClass = MakeGlobalRefOrDie(env, stringClass);
+ jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
+ gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
+ gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
+ "<init>", "()V");
+ gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
+ "(ILjava/lang/Object;)V");
- jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
- gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
- gSparseArrayOffsets.constructor =
- GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "<init>", "()V");
- gSparseArrayOffsets.put =
- GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put", "(ILjava/lang/Object;)V");
+ jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
+ gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
+ gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass,
+ "<init>", "()V");
+ gConfigurationOffsets.mSmallestScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
+ "smallestScreenWidthDp", "I");
+ gConfigurationOffsets.mScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
+ "screenWidthDp", "I");
+ gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass,
+ "screenHeightDp", "I");
- jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
- gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
- gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass, "<init>", "()V");
- gConfigurationOffsets.mSmallestScreenWidthDpOffset =
- GetFieldIDOrDie(env, configurationClass, "smallestScreenWidthDp", "I");
- gConfigurationOffsets.mScreenWidthDpOffset =
- GetFieldIDOrDie(env, configurationClass, "screenWidthDp", "I");
- gConfigurationOffsets.mScreenHeightDpOffset =
- GetFieldIDOrDie(env, configurationClass, "screenHeightDp", "I");
-
- return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
- NELEM(gAssetManagerMethods));
+ return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
+ NELEM(gAssetManagerMethods));
}
}; // namespace android
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index dec6c02..62aa1f38 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -610,7 +610,7 @@
return -1;
}
- char buffer[256];
+ char buffer[2048];
const int len = read(fd, buffer, sizeof(buffer)-1);
close(fd);
@@ -719,7 +719,7 @@
int fd = open(file.string(), O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
- const size_t BUFFER_SIZE = 2048;
+ const size_t BUFFER_SIZE = 4096;
char* buffer = (char*)malloc(BUFFER_SIZE);
int len = read(fd, buffer, BUFFER_SIZE-1);
close(fd);
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 37ff8c8..8770d78 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -174,8 +174,25 @@
return renderNode->stagingProperties().hasShadow();
}
-static jboolean android_view_RenderNode_setShadowColor(jlong renderNodePtr, jint shadowColor) {
- return SET_AND_DIRTY(setShadowColor, static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
+static jboolean android_view_RenderNode_setSpotShadowColor(jlong renderNodePtr, jint shadowColor) {
+ return SET_AND_DIRTY(setSpotShadowColor,
+ static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
+}
+
+static jint android_view_RenderNode_getSpotShadowColor(jlong renderNodePtr) {
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ return renderNode->stagingProperties().getSpotShadowColor();
+}
+
+static jboolean android_view_RenderNode_setAmbientShadowColor(jlong renderNodePtr,
+ jint shadowColor) {
+ return SET_AND_DIRTY(setAmbientShadowColor,
+ static_cast<SkColor>(shadowColor), RenderNode::GENERIC);
+}
+
+static jint android_view_RenderNode_getAmbientShadowColor(jlong renderNodePtr) {
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ return renderNode->stagingProperties().getAmbientShadowColor();
}
static jboolean android_view_RenderNode_setClipToOutline(jlong renderNodePtr,
@@ -575,7 +592,10 @@
{ "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty },
{ "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone },
{ "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow },
- { "nSetShadowColor", "(JI)Z", (void*) android_view_RenderNode_setShadowColor },
+ { "nSetSpotShadowColor", "(JI)Z", (void*) android_view_RenderNode_setSpotShadowColor },
+ { "nGetSpotShadowColor", "(J)I", (void*) android_view_RenderNode_getSpotShadowColor },
+ { "nSetAmbientShadowColor","(JI)Z", (void*) android_view_RenderNode_setAmbientShadowColor },
+ { "nGetAmbientShadowColor","(J)I", (void*) android_view_RenderNode_getAmbientShadowColor },
{ "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline },
{ "nSetRevealClip", "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 421e0de..f5c09fd 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -524,15 +524,15 @@
static jint nativeSetSharedBufferModeEnabled(JNIEnv* env, jclass clazz, jlong nativeObject,
jboolean enabled) {
Surface* surface = reinterpret_cast<Surface*>(nativeObject);
- return ((ANativeWindow*) nativeObject)->perform(surface,
- NATIVE_WINDOW_SET_SHARED_BUFFER_MODE, enabled);
+ ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
+ return anw->perform(surface, NATIVE_WINDOW_SET_SHARED_BUFFER_MODE, int(enabled));
}
static jint nativeSetAutoRefreshEnabled(JNIEnv* env, jclass clazz, jlong nativeObject,
jboolean enabled) {
Surface* surface = reinterpret_cast<Surface*>(nativeObject);
- return ((ANativeWindow*) nativeObject)->perform(surface,
- NATIVE_WINDOW_SET_AUTO_REFRESH, enabled);
+ ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
+ return anw->perform(surface, NATIVE_WINDOW_SET_AUTO_REFRESH, int(enabled));
}
namespace uirenderer {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 13e6fcd..32945bf 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -141,32 +141,45 @@
errno = saved_errno;
}
-// Configures the SIGCHLD handler for the zygote process. This is configured
-// very late, because earlier in the runtime we may fork() and exec()
-// other processes, and we want to waitpid() for those rather than
+// Configures the SIGCHLD/SIGHUP handlers for the zygote process. This is
+// configured very late, because earlier in the runtime we may fork() and
+// exec() other processes, and we want to waitpid() for those rather than
// have them be harvested immediately.
//
+// Ignore SIGHUP because all processes forked by the zygote are in the same
+// process group as the zygote and we don't want to be notified if we become
+// an orphaned group and have one or more stopped processes. This is not a
+// theoretical concern :
+// - we can become an orphaned group if one of our direct descendants forks
+// and is subsequently killed before its children.
+// - crash_dump routinely STOPs the process it's tracing.
+//
+// See issues b/71965619 and b/25567761 for further details.
+//
// This ends up being called repeatedly before each fork(), but there's
// no real harm in that.
-static void SetSigChldHandler() {
- struct sigaction sa;
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = SigChldHandler;
+static void SetSignalHandlers() {
+ struct sigaction sig_chld = {};
+ sig_chld.sa_handler = SigChldHandler;
- int err = sigaction(SIGCHLD, &sa, NULL);
- if (err < 0) {
+ if (sigaction(SIGCHLD, &sig_chld, NULL) < 0) {
ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
}
+
+ struct sigaction sig_hup = {};
+ sig_hup.sa_handler = SIG_IGN;
+ if (sigaction(SIGHUP, &sig_hup, NULL) < 0) {
+ ALOGW("Error setting SIGHUP handler: %s", strerror(errno));
+ }
}
// Sets the SIGCHLD handler back to default behavior in zygote children.
-static void UnsetSigChldHandler() {
+static void UnsetChldSignalHandler() {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
- int err = sigaction(SIGCHLD, &sa, NULL);
- if (err < 0) {
+ if (sigaction(SIGCHLD, &sa, NULL) < 0) {
ALOGW("Error unsetting SIGCHLD handler: %s", strerror(errno));
}
}
@@ -505,7 +518,7 @@
bool is_system_server, jintArray fdsToClose,
jintArray fdsToIgnore,
jstring instructionSet, jstring dataDir) {
- SetSigChldHandler();
+ SetSignalHandlers();
sigset_t sigchld;
sigemptyset(&sigchld);
@@ -682,7 +695,8 @@
delete se_info;
delete se_name;
- UnsetSigChldHandler();
+ // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
+ UnsetChldSignalHandler();
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
is_system_server, instructionSet);
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 956b724..3b7b14c 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -85,11 +85,15 @@
static const char* kOverlayDir = "/system/vendor/overlay/";
static const char* kVendorOverlayDir = "/vendor/overlay";
static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
+ static const char* kSystemProductOverlayDir = "/system/product/overlay/";
+ static const char* kProductOverlayDir = "/product/overlay";
static const char* kApkSuffix = ".apk";
if ((android::base::StartsWith(path, kOverlayDir)
|| android::base::StartsWith(path, kOverlaySubdir)
- || android::base::StartsWith(path, kVendorOverlayDir))
+ || android::base::StartsWith(path, kVendorOverlayDir)
+ || android::base::StartsWith(path, kSystemProductOverlayDir)
+ || android::base::StartsWith(path, kProductOverlayDir))
&& android::base::EndsWith(path, kApkSuffix)
&& path.find("/../") == std::string::npos) {
return true;
diff --git a/core/jni/include/android_runtime/android_util_AssetManager.h b/core/jni/include/android_runtime/android_util_AssetManager.h
index 2c1e357..8dd9337 100644
--- a/core/jni/include/android_runtime/android_util_AssetManager.h
+++ b/core/jni/include/android_runtime/android_util_AssetManager.h
@@ -14,20 +14,17 @@
* limitations under the License.
*/
-#ifndef ANDROID_RUNTIME_ASSETMANAGER_H
-#define ANDROID_RUNTIME_ASSETMANAGER_H
+#ifndef android_util_AssetManager_H
+#define android_util_AssetManager_H
-#include "androidfw/AssetManager2.h"
-#include "androidfw/MutexGuard.h"
+#include <androidfw/AssetManager.h>
#include "jni.h"
namespace android {
-extern AAssetManager* NdkAssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager);
-extern Guarded<AssetManager2>* AssetManagerForJavaObject(JNIEnv* env, jobject jassetmanager);
-extern Guarded<AssetManager2>* AssetManagerForNdkAssetManager(AAssetManager* assetmanager);
+extern AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject assetMgr);
-} // namespace android
+}
-#endif // ANDROID_RUNTIME_ASSETMANAGER_H
+#endif
diff --git a/core/proto/android/app/alarmmanager.proto b/core/proto/android/app/alarmmanager.proto
index 789e3d6..7ef08ca 100644
--- a/core/proto/android/app/alarmmanager.proto
+++ b/core/proto/android/app/alarmmanager.proto
@@ -17,6 +17,7 @@
syntax = "proto2";
import "frameworks/base/core/proto/android/app/pendingintent.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
option java_multiple_files = true;
@@ -47,6 +48,8 @@
// An android.app.AlarmManager.AlarmClockInfo object.
message AlarmClockInfoProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
// This value is UTC wall clock time in milliseconds, as returned by
// System#currentTimeMillis() for example.
optional int64 trigger_time_ms = 1;
diff --git a/core/proto/android/app/enums.proto b/core/proto/android/app/enums.proto
index 2de2574..5eb05be 100644
--- a/core/proto/android/app/enums.proto
+++ b/core/proto/android/app/enums.proto
@@ -21,6 +21,19 @@
option java_outer_classname = "AppProtoEnums";
option java_multiple_files = true;
+// ActivityManagerInternal.java's APP_TRANSITION reasons.
+enum AppTransitionReasonEnum {
+ APP_TRANSITION_REASON_UNKNOWN = 0;
+ // The transition was started because we drew the splash screen.
+ APP_TRANSITION_SPLASH_SCREEN = 1;
+ // The transition was started because we all app windows were drawn.
+ APP_TRANSITION_WINDOWS_DRAWN = 2;
+ // The transition was started because of a timeout.
+ APP_TRANSITION_TIMEOUT = 3;
+ // The transition was started because of a we drew a task snapshot.
+ APP_TRANSITION_SNAPSHOT = 4;
+}
+
// ActivityManager.java PROCESS_STATEs
enum ProcessStateEnum {
// Unlike the ActivityManager PROCESS_STATE values, the ordering and numerical values
diff --git a/core/proto/android/app/notification.proto b/core/proto/android/app/notification.proto
index 379a4ae..c7e313a 100644
--- a/core/proto/android/app/notification.proto
+++ b/core/proto/android/app/notification.proto
@@ -18,10 +18,10 @@
option java_package = "android.app";
option java_multiple_files = true;
-import "frameworks/base/libs/incident/proto/android/privacy.proto";
-
package android.app;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
/**
* An android.app.Notification object.
* Deprecated fields are not included in the proto.
diff --git a/core/proto/android/app/notification_channel.proto b/core/proto/android/app/notification_channel.proto
index 0388547..337aa1c 100644
--- a/core/proto/android/app/notification_channel.proto
+++ b/core/proto/android/app/notification_channel.proto
@@ -21,19 +21,22 @@
package android.app;
import "frameworks/base/core/proto/android/media/audioattributes.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
/**
* An android.app.NotificationChannel object.
*/
message NotificationChannelProto {
- optional string id = 1;
- optional string name = 2;
- optional string description = 3;
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional string id = 1 [ (android.privacy).dest = DEST_EXPLICIT ];
+ optional string name = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
+ optional string description = 3 [ (android.privacy).dest = DEST_EXPLICIT ];
optional int32 importance = 4;
optional bool can_bypass_dnd = 5;
// Default is VISIBILITY_NO_OVERRIDE (-1000).
optional int32 lockscreen_visibility = 6;
- optional string sound = 7;
+ optional string sound = 7 [ (android.privacy).dest = DEST_EXPLICIT ];
optional bool use_lights = 8;
// Default is 0.
optional int32 light_color = 9;
@@ -46,7 +49,7 @@
optional bool show_badge = 13;
// Default is false.
optional bool is_deleted = 14;
- optional string group = 15;
+ optional string group = 15 [ (android.privacy).dest = DEST_EXPLICIT ];
optional android.media.AudioAttributesProto audio_attributes = 16;
// If this is a blockable system notification channel.
optional bool is_blockable_system = 17;
diff --git a/core/proto/android/app/notification_channel_group.proto b/core/proto/android/app/notification_channel_group.proto
index 89a540f..7b270d7 100644
--- a/core/proto/android/app/notification_channel_group.proto
+++ b/core/proto/android/app/notification_channel_group.proto
@@ -21,11 +21,14 @@
package android.app;
import "frameworks/base/core/proto/android/app/notification_channel.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
/**
* An android.app.NotificationChannelGroup object.
*/
message NotificationChannelGroupProto {
+ option (.android.msg_privacy).dest = DEST_EXPLICIT;
+
optional string id = 1;
optional string name = 2;
optional string description = 3;
diff --git a/core/proto/android/app/notificationmanager.proto b/core/proto/android/app/notificationmanager.proto
index 7d774ae..e991688 100644
--- a/core/proto/android/app/notificationmanager.proto
+++ b/core/proto/android/app/notificationmanager.proto
@@ -20,10 +20,14 @@
package android.app;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
/**
- * An android.app.NotificationMananger.Policy object.
+ * An android.app.NotificationManager.Policy object.
*/
message PolicyProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
enum Category {
CATEGORY_UNKNOWN = 0;
// Reminder notifications are prioritized.
@@ -36,6 +40,11 @@
CALLS = 4;
// Calls from repeat callers are prioritized.
REPEAT_CALLERS = 5;
+ // Alarms are prioritized.
+ ALARMS = 6;
+ // Media, system, game (catch-all for non-never suppressible sounds) are
+ // prioritized.
+ MEDIA_SYSTEM_OTHER = 7;
}
repeated Category priority_categories = 1;
diff --git a/core/proto/android/app/pendingintent.proto b/core/proto/android/app/pendingintent.proto
index b562c0b..ab0d34e 100644
--- a/core/proto/android/app/pendingintent.proto
+++ b/core/proto/android/app/pendingintent.proto
@@ -20,9 +20,13 @@
package android.app;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
/**
* An android.app.PendingIntent object.
*/
message PendingIntentProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional string target = 1;
}
diff --git a/core/proto/android/app/window_configuration.proto b/core/proto/android/app/window_configuration.proto
index 4d748e8..1e8ace4 100644
--- a/core/proto/android/app/window_configuration.proto
+++ b/core/proto/android/app/window_configuration.proto
@@ -21,9 +21,12 @@
package android.app;
import "frameworks/base/core/proto/android/graphics/rect.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
/** Proto representation for WindowConfiguration.java class. */
message WindowConfigurationProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional .android.graphics.RectProto app_bounds = 1;
optional int32 windowing_mode = 2;
optional int32 activity_type = 3;
diff --git a/core/proto/android/content/intent.proto b/core/proto/android/content/intent.proto
index c25b46d..5e0ed11 100644
--- a/core/proto/android/content/intent.proto
+++ b/core/proto/android/content/intent.proto
@@ -20,6 +20,7 @@
option java_package = "android.content";
option java_multiple_files = true;
+import "frameworks/base/core/proto/android/content/component_name.proto";
import "frameworks/base/core/proto/android/os/patternmatcher.proto";
import "frameworks/base/libs/incident/proto/android/privacy.proto";
@@ -51,14 +52,14 @@
optional string action = 1;
repeated string categories = 2;
- optional string data = 3 [ (.android.privacy).dest = DEST_EXPLICIT ];
+ optional string data = 3 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional string type = 4;
optional string flag = 5;
optional string package = 6;
- optional string component = 7;
+ optional ComponentNameProto component = 7;
optional string source_bounds = 8;
- optional string clip_data = 9 [ (.android.privacy).dest = DEST_EXPLICIT ];
- optional string extras = 10;
+ optional string clip_data = 9 [ (.android.privacy).dest = DEST_EXPLICIT ];
+ optional string extras = 10 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional int32 content_user_hint = 11;
optional string selector = 12;
}
diff --git a/core/proto/android/internal/locallog.proto b/core/proto/android/internal/locallog.proto
index 51f6c1c..73d1492 100644
--- a/core/proto/android/internal/locallog.proto
+++ b/core/proto/android/internal/locallog.proto
@@ -19,6 +19,10 @@
option java_multiple_files = true;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
message LocalLogProto {
+ option (.android.msg_privacy).dest = DEST_EXPLICIT;
+
repeated string lines = 1;
}
diff --git a/core/proto/android/media/audioattributes.proto b/core/proto/android/media/audioattributes.proto
index 860d608..ef04720 100644
--- a/core/proto/android/media/audioattributes.proto
+++ b/core/proto/android/media/audioattributes.proto
@@ -20,15 +20,19 @@
package android.media;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
/**
* An android.media.AudioAttributes object.
*/
message AudioAttributesProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional Usage usage = 1;
optional ContentType content_type = 2;
// Bit representation of set flags.
optional int32 flags = 3;
- repeated string tags = 4;
+ repeated string tags = 4 [ (android.privacy).dest = DEST_EXPLICIT ];
}
enum ContentType {
diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto
index ce1d5c9..9f9fd05 100644
--- a/core/proto/android/os/batterystats.proto
+++ b/core/proto/android/os/batterystats.proto
@@ -21,7 +21,7 @@
import "frameworks/base/core/proto/android/app/jobparameters.proto";
import "frameworks/base/core/proto/android/os/powermanager.proto";
-import "frameworks/base/core/proto/android/telephony/signalstrength.proto";
+import "frameworks/base/core/proto/android/telephony/enums.proto";
import "frameworks/base/libs/incident/proto/android/privacy.proto";
message BatteryStatsProto {
@@ -339,7 +339,7 @@
message PhoneSignalStrength {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
- optional android.telephony.SignalStrengthProto.StrengthName name = 1;
+ optional android.telephony.SignalStrengthEnum name = 1;
optional TimerProto total = 2;
};
repeated PhoneSignalStrength phone_signal_strength = 16;
diff --git a/core/proto/android/os/enums.proto b/core/proto/android/os/enums.proto
new file mode 100644
index 0000000..fe9b7ac
--- /dev/null
+++ b/core/proto/android/os/enums.proto
@@ -0,0 +1,112 @@
+/*
+ * 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_outer_classname = "OsProtoEnums";
+option java_multiple_files = true;
+
+// These constants are defined in hardware/interfaces/health/1.0/types.hal
+// They are primarily used by android/os/BatteryManager.java.
+enum BatteryHealthEnum {
+ BATTERY_HEALTH_INVALID = 0;
+ BATTERY_HEALTH_UNKNOWN = 1;
+ BATTERY_HEALTH_GOOD = 2;
+ BATTERY_HEALTH_OVERHEAT = 3;
+ BATTERY_HEALTH_DEAD = 4;
+ BATTERY_HEALTH_OVER_VOLTAGE = 5;
+ BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6;
+ BATTERY_HEALTH_COLD = 7;
+}
+
+// Plug states, primarily used by android/os/BatteryManager.java.
+enum BatteryPluggedStateEnum {
+ // Note that NONE is not in BatteryManager.java's constants.
+ BATTERY_PLUGGED_NONE = 0;
+ // Power source is an AC charger.
+ BATTERY_PLUGGED_AC = 1;
+ // Power source is a USB port.
+ BATTERY_PLUGGED_USB = 2;
+ // Power source is wireless.
+ BATTERY_PLUGGED_WIRELESS = 4;
+}
+
+// These constants are defined in hardware/interfaces/health/1.0/types.hal
+// They are primarily used by android/os/BatteryManager.java.
+enum BatteryStatusEnum {
+ BATTERY_STATUS_INVALID = 0;
+ BATTERY_STATUS_UNKNOWN = 1;
+ BATTERY_STATUS_CHARGING = 2;
+ BATTERY_STATUS_DISCHARGING = 3;
+ BATTERY_STATUS_NOT_CHARGING = 4;
+ BATTERY_STATUS_FULL = 5;
+}
+
+// Wakelock types, primarily used by android/os/PowerManager.java.
+enum WakeLockLevelEnum {
+ // NOTE: Wake lock levels were previously defined as a bit field, except
+ // that only a few combinations were actually supported so the bit field
+ // was removed. This explains why the numbering scheme is so odd. If
+ // adding a new wake lock level, any unused value can be used.
+
+ // Ensures that the CPU is running; the screen and keyboard backlight
+ // will be allowed to go off.
+ PARTIAL_WAKE_LOCK = 1;
+
+ // Ensures that the screen is on (but may be dimmed); the keyboard
+ // backlight will be allowed to go off. If the user presses the power
+ // button, then the SCREEN_DIM_WAKE_LOCK will be implicitly released by
+ // the system, causing both the screen and the CPU to be turned off.
+ SCREEN_DIM_WAKE_LOCK = 6 [deprecated = true];
+
+ // Ensures that the screen is on at full brightness; the keyboard
+ // backlight will be allowed to go off. If the user presses the power
+ // button, then the SCREEN_BRIGHT_WAKE_LOCK will be implicitly released
+ // by the system, causing both the screen and the CPU to be turned off.
+ SCREEN_BRIGHT_WAKE_LOCK = 10 [deprecated = true];
+
+ // Ensures that the screen and keyboard backlight are on at full
+ // brightness. If the user presses the power button, then the
+ // FULL_WAKE_LOCK will be implicitly released by the system, causing
+ // both the screen and the CPU to be turned off.
+ FULL_WAKE_LOCK = 26 [deprecated = true];
+
+ // Turns the screen off when the proximity sensor activates. If the
+ // proximity sensor detects that an object is nearby, the screen turns
+ // off immediately. Shortly after the object moves away, the screen
+ // turns on again.
+ // A proximity wake lock does not prevent the device from falling asleep
+ // unlike FULL_WAKE_LOCK, SCREEN_BRIGHT_WAKE_LOCK and
+ // SCREEN_DIM_WAKE_LOCK. If there is no user activity and no other wake
+ // locks are held, then the device will fall asleep (and lock) as usual.
+ // However, the device will not fall asleep while the screen has been
+ // turned off by the proximity sensor because it effectively counts as
+ // ongoing user activity.
+ PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
+
+ // Put the screen in a low power state and allow the CPU to suspend if
+ // no other wake locks are held. This is used by the dream manager to
+ // implement doze mode. It currently has no effect unless the power
+ // manager is in the dozing state.
+ DOZE_WAKE_LOCK = 64;
+
+ // Keep the device awake enough to allow drawing to occur. This is used
+ // by the window manager to allow applications to draw while the system
+ // is dozing. It currently has no effect unless the power manager is in
+ // the dozing state.
+ DRAW_WAKE_LOCK = 128;
+}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 828a55f..8a04bf7 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -16,7 +16,6 @@
syntax = "proto2";
option java_multiple_files = true;
-option java_outer_classname = "IncidentProtoMetadata";
import "frameworks/base/core/proto/android/os/batterytype.proto";
import "frameworks/base/core/proto/android/os/cpufreq.proto";
@@ -123,7 +122,7 @@
// Linux services
optional Procrank procrank = 2000 [
- (section).type = SECTION_COMMAND,
+ (section).type = SECTION_NONE, // disable procrank until figure out permission
(section).args = "/system/xbin/procrank"
];
diff --git a/core/proto/android/os/powermanager.proto b/core/proto/android/os/powermanager.proto
index 8e0a607..78a28ed 100644
--- a/core/proto/android/os/powermanager.proto
+++ b/core/proto/android/os/powermanager.proto
@@ -20,6 +20,7 @@
option java_multiple_files = true;
import "frameworks/base/core/proto/android/os/worksource.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
message PowerManagerProto {
/* User activity events in PowerManager.java. */
@@ -34,62 +35,10 @@
USER_ACTIVITY_EVENT_ACCESSIBILITY = 3;
}
- enum WakeLockLevel {
- // NOTE: Wake lock levels were previously defined as a bit field, except
- // that only a few combinations were actually supported so the bit field
- // was removed. This explains why the numbering scheme is so odd. If
- // adding a new wake lock level, any unused value can be used.
-
- // Ensures that the CPU is running; the screen and keyboard backlight
- // will be allowed to go off.
- PARTIAL_WAKE_LOCK = 1;
-
- // Ensures that the screen is on (but may be dimmed); the keyboard
- // backlight will be allowed to go off. If the user presses the power
- // button, then the SCREEN_DIM_WAKE_LOCK will be implicitly released by
- // the system, causing both the screen and the CPU to be turned off.
- SCREEN_DIM_WAKE_LOCK = 6 [deprecated = true];
-
- // Ensures that the screen is on at full brightness; the keyboard
- // backlight will be allowed to go off. If the user presses the power
- // button, then the SCREEN_BRIGHT_WAKE_LOCK will be implicitly released
- // by the system, causing both the screen and the CPU to be turned off.
- SCREEN_BRIGHT_WAKE_LOCK = 10 [deprecated = true];
-
- // Ensures that the screen and keyboard backlight are on at full
- // brightness. If the user presses the power button, then the
- // FULL_WAKE_LOCK will be implicitly released by the system, causing
- // both the screen and the CPU to be turned off.
- FULL_WAKE_LOCK = 26 [deprecated = true];
-
- // Turns the screen off when the proximity sensor activates. If the
- // proximity sensor detects that an object is nearby, the screen turns
- // off immediately. Shortly after the object moves away, the screen
- // turns on again.
- // A proximity wake lock does not prevent the device from falling asleep
- // unlike FULL_WAKE_LOCK, SCREEN_BRIGHT_WAKE_LOCK and
- // SCREEN_DIM_WAKE_LOCK. If there is no user activity and no other wake
- // locks are held, then the device will fall asleep (and lock) as usual.
- // However, the device will not fall asleep while the screen has been
- // turned off by the proximity sensor because it effectively counts as
- // ongoing user activity.
- PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
-
- // Put the screen in a low power state and allow the CPU to suspend if
- // no other wake locks are held. This is used by the dream manager to
- // implement doze mode. It currently has no effect unless the power
- // manager is in the dozing state.
- DOZE_WAKE_LOCK = 64;
-
- // Keep the device awake enough to allow drawing to occur. This is used
- // by the window manager to allow applications to draw while the system
- // is dozing. It currently has no effect unless the power manager is in
- // the dozing state.
- DRAW_WAKE_LOCK = 128;
- }
-
// WakeLock class in android.os.PowerManager, it is the one used by sdk
message WakeLockProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional string hex_string = 1;
optional bool held = 2;
optional int32 internal_count = 3;
diff --git a/core/proto/android/os/ps.proto b/core/proto/android/os/ps.proto
index 88c6609..9cce727 100644
--- a/core/proto/android/os/ps.proto
+++ b/core/proto/android/os/ps.proto
@@ -20,10 +20,17 @@
option java_multiple_files = true;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
message PsDumpProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
message Process {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
// Security label, most commonly used for SELinux context data.
optional string label = 1;
+ // String representation of uid.
optional string user = 2;
// Process ID number.
optional int32 pid = 3;
diff --git a/core/proto/android/os/worksource.proto b/core/proto/android/os/worksource.proto
index 2f8b2fb..0a9c2ed 100644
--- a/core/proto/android/os/worksource.proto
+++ b/core/proto/android/os/worksource.proto
@@ -17,15 +17,23 @@
syntax = "proto2";
package android.os;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
option java_multiple_files = true;
message WorkSourceProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
message WorkSourceContentProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 uid = 1;
optional string name = 2;
}
message WorkChain {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
repeated WorkSourceContentProto nodes = 1;
}
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index 27fbb24..bfd575a 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -20,7 +20,11 @@
option java_multiple_files = true;
option java_outer_classname = "SettingsServiceProto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
message SettingsServiceDumpProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
// Per user settings
repeated UserSettingsProto user_settings = 1;
@@ -29,8 +33,10 @@
}
message UserSettingsProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
// Should be 0, 10, 11, 12, etc. where 0 is the owner.
- optional int32 user_id = 1;
+ optional int32 user_id = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
// The secure settings for this user
optional SecureSettingsProto secure_settings = 2;
@@ -42,246 +48,266 @@
// Note: it's a conscious decision to add each setting as a separate field. This
// allows annotating each setting with its own privacy tag.
message GlobalSettingsProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
repeated SettingsOperationProto historical_operations = 1;
- optional SettingProto add_users_when_locked = 2;
- optional SettingProto enable_accessibility_global_gesture_enabled = 3;
- optional SettingProto airplane_mode_on = 4;
- optional SettingProto theater_mode_on = 5;
- optional SettingProto radio_bluetooth = 6;
- optional SettingProto radio_wifi = 7;
- optional SettingProto radio_wimax = 8;
- optional SettingProto radio_cell = 9;
- optional SettingProto radio_nfc = 10;
- optional SettingProto airplane_mode_radios = 11;
- optional SettingProto airplane_mode_toggleable_radios = 12;
- optional SettingProto bluetooth_class_of_device = 293;
+ optional SettingProto add_users_when_locked = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enable_accessibility_global_gesture_enabled = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto airplane_mode_on = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto theater_mode_on = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ reserved 6,7,8,9,10; // Accidentally used. They are currently free to be reused.
+ // A comma-separated list of radios that need to be disabled when airplane
+ // mode is on. This overrides wifi_on and bluetooth_on if wifi and bluetooth
+ // are included in the comma-separated list.
+ optional SettingProto airplane_mode_radios = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto airplane_mode_toggleable_radios = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_class_of_device = 293 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto bluetooth_disabled_profiles = 13;
optional SettingProto bluetooth_interoperability_list = 14;
- optional SettingProto wifi_sleep_policy = 15;
- optional SettingProto auto_time = 16;
- optional SettingProto auto_time_zone = 17;
+ optional SettingProto wifi_sleep_policy = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto auto_time = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto auto_time_zone = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto car_dock_sound = 18;
optional SettingProto car_undock_sound = 19;
optional SettingProto desk_dock_sound = 20;
optional SettingProto desk_undock_sound = 21;
- optional SettingProto dock_sounds_enabled = 22;
- optional SettingProto dock_sounds_enabled_when_accessibility = 23;
+ optional SettingProto dock_sounds_enabled = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dock_sounds_enabled_when_accessibility = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto lock_sound = 24;
optional SettingProto unlock_sound = 25;
optional SettingProto trusted_sound = 26;
optional SettingProto low_battery_sound = 27;
- optional SettingProto power_sounds_enabled = 28;
+ optional SettingProto power_sounds_enabled = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto wireless_charging_started_sound = 29;
- optional SettingProto charging_sounds_enabled = 30;
- optional SettingProto stay_on_while_plugged_in = 31;
- optional SettingProto bugreport_in_power_menu = 32;
- optional SettingProto adb_enabled = 33;
- optional SettingProto debug_view_attributes = 34;
- optional SettingProto assisted_gps_enabled = 35;
- optional SettingProto bluetooth_on = 36;
- optional SettingProto cdma_cell_broadcast_sms = 37;
- optional SettingProto cdma_roaming_mode = 38;
- optional SettingProto cdma_subscription_mode = 39;
- optional SettingProto data_activity_timeout_mobile = 40;
- optional SettingProto data_activity_timeout_wifi = 41;
- optional SettingProto data_roaming = 42;
- optional SettingProto mdc_initial_max_retry = 43;
- optional SettingProto force_allow_on_external = 44;
- optional SettingProto euicc_provisioned = 294;
- optional SettingProto development_force_resizable_activities = 45;
- optional SettingProto development_enable_freeform_windows_support = 46;
- optional SettingProto development_settings_enabled = 47;
- optional SettingProto device_provisioned = 48;
- optional SettingProto device_provisioning_mobile_data_enabled = 49;
- optional SettingProto display_size_forced = 50;
- optional SettingProto display_scaling_force = 51;
- optional SettingProto download_max_bytes_over_mobile = 52;
- optional SettingProto download_recommended_max_bytes_over_mobile = 53;
- optional SettingProto hdmi_control_enabled = 54;
- optional SettingProto hdmi_system_audio_control_enabled = 55;
- optional SettingProto hdmi_control_auto_wakeup_enabled = 56;
- optional SettingProto hdmi_control_auto_device_off_enabled = 57;
- optional SettingProto location_background_throttle_interval_ms = 295;
- optional SettingProto location_background_throttle_proximity_alert_interval_ms = 296;
- optional SettingProto location_background_throttle_package_whitelist = 297;
- optional SettingProto wifi_scan_background_throttle_interval_ms = 298;
- optional SettingProto wifi_scan_background_throttle_package_whitelist = 299;
- optional SettingProto mhl_input_switching_enabled = 58;
- optional SettingProto mhl_power_charge_enabled = 59;
- optional SettingProto mobile_data = 60;
- optional SettingProto mobile_data_always_on = 61;
- optional SettingProto connectivity_metrics_buffer_size = 62;
- optional SettingProto netstats_enabled = 63;
- optional SettingProto netstats_poll_interval = 64;
- optional SettingProto netstats_time_cache_max_age = 65;
- optional SettingProto netstats_global_alert_bytes = 66;
- optional SettingProto netstats_sample_enabled = 67;
- optional SettingProto netstats_augment_enabled = 300;
- optional SettingProto netstats_dev_bucket_duration = 68;
- optional SettingProto netstats_dev_persist_bytes = 69;
- optional SettingProto netstats_dev_rotate_age = 70;
- optional SettingProto netstats_dev_delete_age = 71;
- optional SettingProto netstats_uid_bucket_duration = 72;
- optional SettingProto netstats_uid_persist_bytes = 73;
- optional SettingProto netstats_uid_rotate_age = 74;
- optional SettingProto netstats_uid_delete_age = 75;
- optional SettingProto netstats_uid_tag_bucket_duration = 76;
- optional SettingProto netstats_uid_tag_persist_bytes = 77;
- optional SettingProto netstats_uid_tag_rotate_age = 78;
- optional SettingProto netstats_uid_tag_delete_age = 79;
+ optional SettingProto charging_sounds_enabled = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto stay_on_while_plugged_in = 31 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bugreport_in_power_menu = 32 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto adb_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Whether views are allowed to save their attribute data.
+ optional SettingProto debug_view_attributes = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto assisted_gps_enabled = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_on = 36 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto cdma_cell_broadcast_sms = 37 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto cdma_roaming_mode = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto cdma_subscription_mode = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto data_activity_timeout_mobile = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto data_activity_timeout_wifi = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto data_roaming = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto mdc_initial_max_retry = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto force_allow_on_external = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto euicc_provisioned = 294 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto development_force_resizable_activities = 45 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto development_enable_freeform_windows_support = 46 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto development_settings_enabled = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto device_provisioned = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto device_provisioning_mobile_data_enabled = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto display_size_forced = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto display_scaling_force = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto download_max_bytes_over_mobile = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto download_recommended_max_bytes_over_mobile = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto hdmi_control_enabled = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto hdmi_system_audio_control_enabled = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto hdmi_control_auto_wakeup_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto hdmi_control_auto_device_off_enabled = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto location_background_throttle_interval_ms = 295 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto location_background_throttle_proximity_alert_interval_ms = 296 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Packages that are whitelisted for background throttling (throttling will
+ // not be applied).
+ optional SettingProto location_background_throttle_package_whitelist = 297 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_scan_background_throttle_interval_ms = 298 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_scan_background_throttle_package_whitelist = 299 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto mhl_input_switching_enabled = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto mhl_power_charge_enabled = 59 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto mobile_data = 60 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto mobile_data_always_on = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto connectivity_metrics_buffer_size = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_enabled = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_poll_interval = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_time_cache_max_age = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_global_alert_bytes = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_sample_enabled = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_augment_enabled = 300 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_dev_bucket_duration = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_dev_persist_bytes = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_dev_rotate_age = 70 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_dev_delete_age = 71 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_uid_bucket_duration = 72 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_uid_persist_bytes = 73 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_uid_rotate_age = 74 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_uid_delete_age = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_uid_tag_bucket_duration = 76 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_uid_tag_persist_bytes = 77 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_uid_tag_rotate_age = 78 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto netstats_uid_tag_delete_age = 79 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // User preference for which network(s) should be used.
optional SettingProto network_preference = 80;
- optional SettingProto network_scorer_app = 81;
- optional SettingProto nitz_update_diff = 82;
- optional SettingProto nitz_update_spacing = 83;
+ optional SettingProto network_scorer_app = 81 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto nitz_update_diff = 82 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto nitz_update_spacing = 83 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto ntp_server = 84;
- optional SettingProto ntp_timeout = 85;
- optional SettingProto storage_benchmark_interval = 86;
- optional SettingProto dns_resolver_sample_validity_seconds = 87;
- optional SettingProto dns_resolver_success_threshold_percent = 88;
- optional SettingProto dns_resolver_min_samples = 89;
- optional SettingProto dns_resolver_max_samples = 90;
- optional SettingProto ota_disable_automatic_update = 91;
- optional SettingProto package_verifier_enable = 92;
- optional SettingProto package_verifier_timeout = 93;
+ optional SettingProto ntp_timeout = 85 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto storage_benchmark_interval = 86 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dns_resolver_sample_validity_seconds = 87 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dns_resolver_success_threshold_percent = 88 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dns_resolver_min_samples = 89 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dns_resolver_max_samples = 90 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Whether to disable the automatic scheduling of system updates.
+ optional SettingProto ota_disable_automatic_update = 91 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto package_verifier_enable = 92 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto package_verifier_timeout = 93 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto package_verifier_default_response = 94;
- optional SettingProto package_verifier_setting_visible = 95;
- optional SettingProto package_verifier_include_adb = 96;
- optional SettingProto fstrim_mandatory_interval = 97;
- optional SettingProto pdp_watchdog_poll_interval_ms = 98;
- optional SettingProto pdp_watchdog_long_poll_interval_ms = 99;
- optional SettingProto pdp_watchdog_error_poll_interval_ms = 100;
- optional SettingProto pdp_watchdog_trigger_packet_count = 101;
- optional SettingProto pdp_watchdog_error_poll_count = 102;
- optional SettingProto pdp_watchdog_max_pdp_reset_fail_count = 103;
+ optional SettingProto package_verifier_setting_visible = 95 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto package_verifier_include_adb = 96 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto fstrim_mandatory_interval = 97 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pdp_watchdog_poll_interval_ms = 98 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pdp_watchdog_long_poll_interval_ms = 99 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pdp_watchdog_error_poll_interval_ms = 100 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pdp_watchdog_trigger_packet_count = 101 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pdp_watchdog_error_poll_count = 102 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pdp_watchdog_max_pdp_reset_fail_count = 103 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto setup_prepaid_data_service_url = 105;
optional SettingProto setup_prepaid_detection_target_url = 106;
optional SettingProto setup_prepaid_detection_redir_host = 107;
- optional SettingProto sms_outgoing_check_interval_ms = 108;
- optional SettingProto sms_outgoing_check_max_count = 109;
- optional SettingProto sms_short_code_confirmation = 110;
- optional SettingProto sms_short_code_rule = 111;
- optional SettingProto tcp_default_init_rwnd = 112;
- optional SettingProto tether_supported = 113;
- optional SettingProto tether_dun_required = 114;
+ optional SettingProto sms_outgoing_check_interval_ms = 108 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sms_outgoing_check_max_count = 109 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Used to disable SMS short code confirmation. Defaults to true.
+ optional SettingProto sms_short_code_confirmation = 110 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sms_short_code_rule = 111 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto tcp_default_init_rwnd = 112 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto tether_supported = 113 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto tether_dun_required = 114 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto tether_dun_apn = 115;
- optional SettingProto tether_offload_disabled = 301;
- optional SettingProto carrier_app_whitelist = 116;
- optional SettingProto usb_mass_storage_enabled = 117;
- optional SettingProto use_google_mail = 118;
+ optional SettingProto tether_offload_disabled = 301 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // List of carrier apps which are whitelisted to prompt the user for install
+ // when a SIM card with marchin UICC carrier privilege rules is inserted.
+ optional SettingProto carrier_app_whitelist = 116 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto usb_mass_storage_enabled = 117 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto use_google_mail = 118 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto webview_data_reduction_proxy_key = 119;
- optional SettingProto webview_fallback_logic_enabled = 120;
- optional SettingProto webview_provider = 121;
- optional SettingProto webview_multiprocess = 122;
- optional SettingProto network_switch_notification_daily_limit = 123;
- optional SettingProto network_switch_notification_rate_limit_millis = 124;
- optional SettingProto network_avoid_bad_wifi = 125;
- optional SettingProto network_metered_multipath_preference = 302;
- optional SettingProto network_watchlist_last_report_time = 303;
- optional SettingProto wifi_badging_thresholds = 304;
- optional SettingProto wifi_display_on = 126;
- optional SettingProto wifi_display_certification_on = 127;
- optional SettingProto wifi_display_wps_config = 128;
- optional SettingProto wifi_networks_available_notification_on = 129;
- optional SettingProto wimax_networks_available_notification_on = 130;
- optional SettingProto wifi_networks_available_repeat_delay = 131;
+ optional SettingProto webview_fallback_logic_enabled = 120 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Name of the package used as WebView provider.
+ optional SettingProto webview_provider = 121 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto webview_multiprocess = 122 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto network_switch_notification_daily_limit = 123 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto network_switch_notification_rate_limit_millis = 124 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto network_avoid_bad_wifi = 125 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto network_metered_multipath_preference = 302 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto network_watchlist_last_report_time = 303 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_badging_thresholds = 304 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_display_on = 126 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_display_certification_on = 127 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_display_wps_config = 128 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_networks_available_notification_on = 129 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wimax_networks_available_notification_on = 130 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_networks_available_repeat_delay = 131 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto wifi_country_code = 132;
- optional SettingProto wifi_framework_scan_interval_ms = 133;
- optional SettingProto wifi_idle_ms = 134;
- optional SettingProto wifi_num_open_networks_kept = 135;
- optional SettingProto wifi_on = 136;
- optional SettingProto wifi_scan_always_available = 137;
- optional SettingProto wifi_wakeup_enabled = 138;
- optional SettingProto wifi_wakeup_available = 305;
- optional SettingProto network_scoring_ui_enabled = 306;
- optional SettingProto speed_label_cache_eviction_age_millis = 307;
- optional SettingProto recommended_network_evaluator_cache_expiry_ms = 308;
- optional SettingProto network_recommendations_enabled = 139;
- optional SettingProto network_recommendations_package = 286;
- optional SettingProto use_open_wifi_package = 309;
- optional SettingProto network_recommendation_request_timeout_ms = 310;
- optional SettingProto ble_scan_always_available = 140;
- optional SettingProto wifi_saved_state = 141;
- optional SettingProto wifi_supplicant_scan_interval_ms = 142;
- optional SettingProto wifi_enhanced_auto_join = 143;
- optional SettingProto wifi_network_show_rssi = 144;
- optional SettingProto wifi_scan_interval_when_p2p_connected_ms = 145;
- optional SettingProto wifi_watchdog_on = 146;
- optional SettingProto wifi_watchdog_poor_network_test_enabled = 147;
- optional SettingProto wifi_suspend_optimizations_enabled = 148;
- optional SettingProto wifi_verbose_logging_enabled = 149;
- optional SettingProto wifi_max_dhcp_retry_count = 150;
- optional SettingProto wifi_mobile_data_transition_wakelock_timeout_ms = 151;
- optional SettingProto wifi_device_owner_configs_lockdown = 152;
- optional SettingProto wifi_frequency_band = 153;
+ optional SettingProto wifi_framework_scan_interval_ms = 133 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_idle_ms = 134 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_num_open_networks_kept = 135 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_on = 136 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_scan_always_available = 137 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_wakeup_enabled = 138 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_wakeup_available = 305 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto network_scoring_ui_enabled = 306 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto speed_label_cache_eviction_age_millis = 307 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto recommended_network_evaluator_cache_expiry_ms = 308 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto network_recommendations_enabled = 139 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto network_recommendations_package = 286 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto use_open_wifi_package = 309 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto network_recommendation_request_timeout_ms = 310 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto ble_scan_always_available = 140 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_saved_state = 141 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_supplicant_scan_interval_ms = 142 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_enhanced_auto_join = 143 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_network_show_rssi = 144 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_scan_interval_when_p2p_connected_ms = 145 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_watchdog_on = 146 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_watchdog_poor_network_test_enabled = 147 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_suspend_optimizations_enabled = 148 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_verbose_logging_enabled = 149 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_connected_mac_randomization_enabled = 350 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_max_dhcp_retry_count = 150 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_mobile_data_transition_wakelock_timeout_ms = 151 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_device_owner_configs_lockdown = 152 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_frequency_band = 153 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto wifi_p2p_device_name = 154;
- optional SettingProto wifi_reenable_delay_ms = 155;
- optional SettingProto wifi_ephemeral_out_of_range_timeout_ms = 156;
- optional SettingProto data_stall_alarm_non_aggressive_delay_in_ms = 157;
- optional SettingProto data_stall_alarm_aggressive_delay_in_ms = 158;
- optional SettingProto provisioning_apn_alarm_delay_in_ms = 159;
- optional SettingProto gprs_register_check_period_ms = 160;
- optional SettingProto wtf_is_fatal = 161;
- optional SettingProto mode_ringer = 162;
- optional SettingProto overlay_display_devices = 163;
- optional SettingProto battery_discharge_duration_threshold = 164;
- optional SettingProto battery_discharge_threshold = 165;
- optional SettingProto send_action_app_error = 166;
- optional SettingProto dropbox_age_seconds = 167;
- optional SettingProto dropbox_max_files = 168;
- optional SettingProto dropbox_quota_kb = 169;
- optional SettingProto dropbox_quota_percent = 170;
- optional SettingProto dropbox_reserve_percent = 171;
- optional SettingProto dropbox_tag_prefix = 172;
- optional SettingProto error_logcat_prefix = 173;
- optional SettingProto sys_free_storage_log_interval = 174;
- optional SettingProto disk_free_change_reporting_threshold = 175;
- optional SettingProto sys_storage_threshold_percentage = 176;
- optional SettingProto sys_storage_threshold_max_bytes = 177;
- optional SettingProto sys_storage_full_threshold_bytes = 178;
- optional SettingProto sys_storage_cache_percentage = 311;
- optional SettingProto sys_storage_cache_max_bytes = 312;
- optional SettingProto sync_max_retry_delay_in_seconds = 179;
- optional SettingProto connectivity_change_delay = 180;
- optional SettingProto connectivity_sampling_interval_in_seconds = 181;
- optional SettingProto pac_change_delay = 182;
- optional SettingProto captive_portal_mode = 183;
- optional SettingProto captive_portal_detection_enabled = 313;
+ optional SettingProto wifi_reenable_delay_ms = 155 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_ephemeral_out_of_range_timeout_ms = 156 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto data_stall_alarm_non_aggressive_delay_in_ms = 157 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto data_stall_alarm_aggressive_delay_in_ms = 158 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto provisioning_apn_alarm_delay_in_ms = 159 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto gprs_register_check_period_ms = 160 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wtf_is_fatal = 161 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Ringer mode. A change in this value will not reflect as a change in the
+ // ringer mode.
+ optional SettingProto mode_ringer = 162 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Overlay display devices setting.
+ // The value is a specially formatted string that describes the size and
+ // density of simulated secondary devices.
+ // Format: {width}x{height}/dpi;...
+ optional SettingProto overlay_display_devices = 163 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto battery_discharge_duration_threshold = 164 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto battery_discharge_threshold = 165 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto send_action_app_error = 166 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dropbox_age_seconds = 167 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dropbox_max_files = 168 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dropbox_quota_kb = 169 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dropbox_quota_percent = 170 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dropbox_reserve_percent = 171 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dropbox_tag_prefix = 172 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto error_logcat_prefix = 173 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sys_free_storage_log_interval = 174 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto disk_free_change_reporting_threshold = 175 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sys_storage_threshold_percentage = 176 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sys_storage_threshold_max_bytes = 177 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sys_storage_full_threshold_bytes = 178 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sys_storage_cache_percentage = 311 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sys_storage_cache_max_bytes = 312 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sync_max_retry_delay_in_seconds = 179 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto connectivity_change_delay = 180 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto connectivity_sampling_interval_in_seconds = 181 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pac_change_delay = 182 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captive_portal_mode = 183 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto captive_portal_detection_enabled = 313 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto captive_portal_server = 184;
optional SettingProto captive_portal_https_url = 185;
optional SettingProto captive_portal_http_url = 186;
optional SettingProto captive_portal_fallback_url = 187;
optional SettingProto captive_portal_other_fallback_urls = 314;
- optional SettingProto captive_portal_use_https = 188;
+ optional SettingProto captive_portal_use_https = 188 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto captive_portal_user_agent = 189;
- optional SettingProto nsd_on = 190;
- optional SettingProto set_install_location = 191;
- optional SettingProto default_install_location = 192;
- optional SettingProto inet_condition_debounce_up_delay = 193;
- optional SettingProto inet_condition_debounce_down_delay = 194;
- optional SettingProto read_external_storage_enforced_default = 195;
+ optional SettingProto nsd_on = 190 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Let user pick default install location.
+ optional SettingProto set_install_location = 191 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto default_install_location = 192 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto inet_condition_debounce_up_delay = 193 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto inet_condition_debounce_down_delay = 194 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto read_external_storage_enforced_default = 195 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto http_proxy = 196;
optional SettingProto global_http_proxy_host = 197;
optional SettingProto global_http_proxy_port = 198;
optional SettingProto global_http_proxy_exclusion_list = 199;
optional SettingProto global_http_proxy_pac = 200;
- optional SettingProto set_global_http_proxy = 201;
+ // Enables the UI setting to allow the user to specify the global HTTP proxy
+ // and associated exclusion list.
+ optional SettingProto set_global_http_proxy = 201 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto default_dns_server = 202;
// The requested Private DNS mode and an accompanying specifier.
optional SettingProto private_dns_mode = 315;
optional SettingProto private_dns_specifier = 316;
- optional SettingProto bluetooth_headset_priority_prefix = 203;
- optional SettingProto bluetooth_a2dp_sink_priority_prefix = 204;
- optional SettingProto bluetooth_a2dp_src_priority_prefix = 205;
- optional SettingProto bluetooth_a2dp_supports_optional_codecs_prefix = 287;
- optional SettingProto bluetooth_a2dp_optional_codecs_enabled_prefix = 288;
- optional SettingProto bluetooth_input_device_priority_prefix = 206;
- optional SettingProto bluetooth_map_priority_prefix = 207;
- optional SettingProto bluetooth_map_client_priority_prefix = 208;
- optional SettingProto bluetooth_pbap_client_priority_prefix = 209;
- optional SettingProto bluetooth_sap_priority_prefix = 210;
- optional SettingProto bluetooth_pan_priority_prefix = 211;
- optional SettingProto bluetooth_hearing_aid_priority_prefix = 345;
+ optional SettingProto bluetooth_headset_priority_prefix = 203 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_a2dp_sink_priority_prefix = 204 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_a2dp_src_priority_prefix = 205 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_a2dp_supports_optional_codecs_prefix = 287 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_a2dp_optional_codecs_enabled_prefix = 288 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_input_device_priority_prefix = 206 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_map_priority_prefix = 207 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_map_client_priority_prefix = 208 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_pbap_client_priority_prefix = 209 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_sap_priority_prefix = 210 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_pan_priority_prefix = 211 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_hearing_aid_priority_prefix = 345 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto activity_manager_constants = 317;
optional SettingProto device_idle_constants = 212;
optional SettingProto device_idle_constants_watch = 213;
@@ -295,26 +321,28 @@
optional SettingProto shortcut_manager_constants = 217;
optional SettingProto device_policy_constants = 322;
optional SettingProto text_classifier_constants = 323;
- optional SettingProto window_animation_scale = 218;
- optional SettingProto transition_animation_scale = 219;
- optional SettingProto animator_duration_scale = 220;
- optional SettingProto fancy_ime_animations = 221;
- optional SettingProto compatibility_mode = 222;
- optional SettingProto emergency_tone = 223;
- optional SettingProto call_auto_retry = 224;
- optional SettingProto emergency_affordance_needed = 225;
- optional SettingProto preferred_network_mode = 226;
+ optional SettingProto window_animation_scale = 218 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto transition_animation_scale = 219 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto animator_duration_scale = 220 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto fancy_ime_animations = 221 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto compatibility_mode = 222 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto emergency_tone = 223 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto call_auto_retry = 224 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto emergency_affordance_needed = 225 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto preferred_network_mode = 226 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Name of an application package to be debugged.
optional SettingProto debug_app = 227;
- optional SettingProto wait_for_debugger = 228;
- optional SettingProto enable_gpu_debug_layers = 342;
+ optional SettingProto wait_for_debugger = 228 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enable_gpu_debug_layers = 342 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // App allowed to load GPU debug layers.
optional SettingProto gpu_debug_app = 343;
- optional SettingProto gpu_debug_layers = 344;
- optional SettingProto low_power_mode = 229;
- optional SettingProto low_power_mode_trigger_level = 230;
- optional SettingProto always_finish_activities = 231;
- optional SettingProto dock_audio_media_enabled = 232;
- optional SettingProto encoded_surround_output = 233;
- optional SettingProto audio_safe_volume_state = 234;
+ optional SettingProto gpu_debug_layers = 344 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto low_power_mode = 229 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto low_power_mode_trigger_level = 230 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto always_finish_activities = 231 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dock_audio_media_enabled = 232 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto encoded_surround_output = 233 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto audio_safe_volume_state = 234 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto tzinfo_update_content_url = 235;
optional SettingProto tzinfo_update_metadata_url = 236;
optional SettingProto selinux_update_content_url = 237;
@@ -331,308 +359,349 @@
optional SettingProto lang_id_update_metadata_url = 325;
optional SettingProto smart_selection_update_content_url = 326;
optional SettingProto smart_selection_update_metadata_url = 327;
- optional SettingProto selinux_status = 247;
- optional SettingProto development_force_rtl = 248;
- optional SettingProto low_battery_sound_timeout = 249;
- optional SettingProto wifi_bounce_delay_override_ms = 250;
- optional SettingProto policy_control = 251;
- optional SettingProto zen_mode = 252;
- optional SettingProto zen_mode_ringer_level = 253;
+ optional SettingProto selinux_status = 247 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto development_force_rtl = 248 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto low_battery_sound_timeout = 249 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wifi_bounce_delay_override_ms = 250 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto policy_control = 251 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto zen_mode = 252 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto zen_mode_ringer_level = 253 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto zen_mode_config_etag = 254;
- optional SettingProto heads_up_notifications_enabled = 255;
+ optional SettingProto heads_up_notifications_enabled = 255 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto device_name = 256;
- optional SettingProto network_scoring_provisioned = 257;
- optional SettingProto require_password_to_decrypt = 258;
- optional SettingProto enhanced_4g_mode_enabled = 259;
- optional SettingProto vt_ims_enabled = 260;
- optional SettingProto wfc_ims_enabled = 261;
- optional SettingProto wfc_ims_mode = 262;
- optional SettingProto wfc_ims_roaming_mode = 263;
- optional SettingProto wfc_ims_roaming_enabled = 264;
- optional SettingProto lte_service_forced = 265;
- optional SettingProto ephemeral_cookie_max_size_bytes = 266;
- optional SettingProto enable_ephemeral_feature = 267;
- optional SettingProto instant_app_dexopt_enabled = 328;
- optional SettingProto installed_instant_app_min_cache_period = 268;
- optional SettingProto installed_instant_app_max_cache_period = 289;
- optional SettingProto uninstalled_instant_app_min_cache_period = 290;
- optional SettingProto uninstalled_instant_app_max_cache_period = 291;
- optional SettingProto unused_static_shared_lib_min_cache_period = 292;
- optional SettingProto allow_user_switching_when_system_user_locked = 269;
- optional SettingProto boot_count = 270;
- optional SettingProto safe_boot_disallowed = 271;
- optional SettingProto device_demo_mode = 272;
- optional SettingProto network_access_timeout_ms = 329;
+ optional SettingProto network_scoring_provisioned = 257 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto require_password_to_decrypt = 258 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enhanced_4g_mode_enabled = 259 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto vt_ims_enabled = 260 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wfc_ims_enabled = 261 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wfc_ims_mode = 262 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wfc_ims_roaming_mode = 263 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wfc_ims_roaming_enabled = 264 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lte_service_forced = 265 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto ephemeral_cookie_max_size_bytes = 266 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enable_ephemeral_feature = 267 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto instant_app_dexopt_enabled = 328 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto installed_instant_app_min_cache_period = 268 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto installed_instant_app_max_cache_period = 289 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto uninstalled_instant_app_min_cache_period = 290 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto uninstalled_instant_app_max_cache_period = 291 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto unused_static_shared_lib_min_cache_period = 292 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto allow_user_switching_when_system_user_locked = 269 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto boot_count = 270 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto safe_boot_disallowed = 271 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto device_demo_mode = 272 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto network_access_timeout_ms = 329 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto database_downgrade_reason = 274;
- optional SettingProto database_creation_buildid = 330;
- optional SettingProto contacts_database_wal_enabled = 275;
- optional SettingProto location_settings_link_to_permissions_enabled = 331;
+ optional SettingProto database_creation_buildid = 330 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto contacts_database_wal_enabled = 275 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto location_settings_link_to_permissions_enabled = 331 [ (android.privacy).dest = DEST_AUTOMATIC ];
reserved 332; // Removed backup_refactored_service_disabled
- optional SettingProto euicc_factory_reset_timeout_millis = 333;
- optional SettingProto storage_settings_clobber_threshold = 334;
- optional SettingProto multi_sim_voice_call_subscription = 276;
- optional SettingProto multi_sim_voice_prompt = 277;
- optional SettingProto multi_sim_data_call_subscription = 278;
- optional SettingProto multi_sim_sms_subscription = 279;
- optional SettingProto multi_sim_sms_prompt = 280;
- optional SettingProto new_contact_aggregator = 281;
- optional SettingProto contact_metadata_sync_enabled = 282;
- optional SettingProto enable_cellular_on_boot = 283;
- optional SettingProto max_notification_enqueue_rate = 284;
- optional SettingProto show_notification_channel_warnings = 335;
- optional SettingProto cell_on = 285;
- optional SettingProto show_temperature_warning = 336;
- optional SettingProto warning_temperature = 337;
- optional SettingProto enable_diskstats_logging = 338;
- optional SettingProto enable_cache_quota_calculation = 339;
- optional SettingProto enable_deletion_helper_no_threshold_toggle = 340;
- optional SettingProto notification_snooze_options = 341;
- optional SettingProto enable_gnss_raw_meas_full_tracking = 346;
- optional SettingProto zram_enabled = 347;
- optional SettingProto enable_smart_replies_in_notifications = 348;
- optional SettingProto show_first_crash_dialog = 349;
- optional SettingProto wifi_connected_mac_randomization_enabled = 350;
- optional SettingProto show_restart_in_crash_dialog = 351;
- optional SettingProto show_mute_in_crash_dialog = 352;
- optional SettingProto chained_battery_attribution_enabled = 353;
+ optional SettingProto euicc_factory_reset_timeout_millis = 333 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto storage_settings_clobber_threshold = 334 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto chained_battery_attribution_enabled = 353 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Subscription to be used for voice call on a multi sim device. The
+ // supported values are 0 = SUB1, 1 = SUB2 and etc.
+ optional SettingProto multi_sim_voice_call_subscription = 276 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto multi_sim_voice_prompt = 277 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto multi_sim_data_call_subscription = 278 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto multi_sim_sms_subscription = 279 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto multi_sim_sms_prompt = 280 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Whether to enable new contacts aggregator or not.
+ // 1 = enable, 0 = disable.
+ optional SettingProto new_contact_aggregator = 281 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto contact_metadata_sync_enabled = 282 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enable_cellular_on_boot = 283 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto max_notification_enqueue_rate = 284 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_notification_channel_warnings = 335 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto cell_on = 285 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_temperature_warning = 336 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto warning_temperature = 337 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enable_diskstats_logging = 338 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enable_cache_quota_calculation = 339 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enable_deletion_helper_no_threshold_toggle = 340 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto notification_snooze_options = 341 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enable_gnss_raw_meas_full_tracking = 346 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto zram_enabled = 347 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enable_smart_replies_in_notifications = 348 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_first_crash_dialog = 349 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_restart_in_crash_dialog = 351 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_mute_in_crash_dialog = 352 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Please insert fields in the same order as in
+ // frameworks/base/core/java/android/provider/Settings.java.
// Next tag = 354;
}
message SecureSettingsProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
repeated SettingsOperationProto historical_operations = 1;
optional SettingProto android_id = 2;
- optional SettingProto default_input_method = 3;
- optional SettingProto selected_input_method_subtype = 4;
- optional SettingProto input_methods_subtype_history = 5;
- optional SettingProto input_method_selector_visibility = 6;
- optional SettingProto voice_interaction_service = 7;
- optional SettingProto autofill_service = 8;
+ optional SettingProto default_input_method = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto selected_input_method_subtype = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto input_methods_subtype_history = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto input_method_selector_visibility = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The currently selected voice interaction service flattened ComponentName.
+ optional SettingProto voice_interaction_service = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The currently selected autofill service flattened ComponentName.
+ optional SettingProto autofill_service = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto bluetooth_hci_log = 9;
- optional SettingProto user_setup_complete = 10;
+ optional SettingProto user_setup_complete = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
// Whether the current user has been set up via setup wizard (0 = false,
// 1 = true). This value differs from USER_SETUP_COMPLETE in that it can be
// reset back to 0 in case SetupWizard has been re-enabled on TV devices.
- optional SettingProto tv_user_setup_complete = 170;
- optional SettingProto completed_category_prefix = 11;
- optional SettingProto enabled_input_methods = 12;
- optional SettingProto disabled_system_input_methods = 13;
- optional SettingProto show_ime_with_hard_keyboard = 14;
+ optional SettingProto tv_user_setup_complete = 170 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto completed_category_prefix = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enabled_input_methods = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto disabled_system_input_methods = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_ime_with_hard_keyboard = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto always_on_vpn_app = 15;
- optional SettingProto always_on_vpn_lockdown = 16;
- optional SettingProto install_non_market_apps = 17;
- optional SettingProto unknown_sources_default_reversed = 171;
- optional SettingProto location_mode = 18;
+ optional SettingProto always_on_vpn_lockdown = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto install_non_market_apps = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto unknown_sources_default_reversed = 171 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The degree of location access enabled by the user.
+ optional SettingProto location_mode = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto location_previous_mode = 19;
- optional SettingProto lock_to_app_exit_locked = 20;
- optional SettingProto lock_screen_lock_after_timeout = 21;
- optional SettingProto lock_screen_allow_private_notifications = 172;
- optional SettingProto lock_screen_allow_remote_input = 22;
- optional SettingProto show_note_about_notification_hiding = 23;
- optional SettingProto trust_agents_initialized = 24;
- optional SettingProto parental_control_enabled = 25;
- optional SettingProto parental_control_last_update = 26;
- optional SettingProto parental_control_redirect_url = 27;
- optional SettingProto settings_classname = 28;
- optional SettingProto accessibility_enabled = 29;
- optional SettingProto accessibility_shortcut_enabled = 173;
- optional SettingProto accessibility_shortcut_on_lock_screen = 174;
- optional SettingProto accessibility_shortcut_dialog_shown = 175;
- optional SettingProto accessibility_shortcut_target_service = 176;
- optional SettingProto accessibility_button_target_component = 177;
- optional SettingProto touch_exploration_enabled = 30;
+ // Whether lock-to-app will lock the keyguard when exiting.
+ optional SettingProto lock_to_app_exit_locked = 20 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lock_screen_lock_after_timeout = 21 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lock_screen_allow_private_notifications = 172 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lock_screen_allow_remote_input = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_note_about_notification_hiding = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto trust_agents_initialized = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto parental_control_enabled = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto parental_control_last_update = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto parental_control_redirect_url = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto settings_classname = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_enabled = 29 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_shortcut_enabled = 173 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_shortcut_on_lock_screen = 174 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_shortcut_dialog_shown = 175 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_shortcut_target_service = 176 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Setting specifying the accessibility service or feature to be toggled via
+ // the accessibility button in the navigation bar. This is either a
+ // flattened ComponentName or the class name of a system class implementing
+ // a supported accessibility feature.
+ optional SettingProto accessibility_button_target_component = 177 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto touch_exploration_enabled = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // List of the enabled accessibility providers.
optional SettingProto enabled_accessibility_services = 31;
+ // List of the accessibility services to which the user has granted
+ // permission to put the device into touch exploration mode.
optional SettingProto touch_exploration_granted_accessibility_services = 32;
- optional SettingProto accessibility_speak_password = 33;
- optional SettingProto accessibility_high_text_contrast_enabled = 34;
+ // Whether to speak passwords while in accessibility mode.
+ optional SettingProto accessibility_speak_password = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_high_text_contrast_enabled = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto accessibility_script_injection = 35;
optional SettingProto accessibility_screen_reader_url = 36;
optional SettingProto accessibility_web_content_key_bindings = 37;
- optional SettingProto accessibility_display_magnification_enabled = 38;
- optional SettingProto accessibility_display_magnification_navbar_enabled = 178;
- optional SettingProto accessibility_display_magnification_scale = 39;
- optional SettingProto accessibility_display_magnification_auto_update = 179;
- optional SettingProto accessibility_soft_keyboard_mode = 40;
- optional SettingProto accessibility_captioning_enabled = 41;
- optional SettingProto accessibility_captioning_locale = 42;
- optional SettingProto accessibility_captioning_preset = 43;
- optional SettingProto accessibility_captioning_background_color = 44;
- optional SettingProto accessibility_captioning_foreground_color = 45;
- optional SettingProto accessibility_captioning_edge_type = 46;
- optional SettingProto accessibility_captioning_edge_color = 47;
- optional SettingProto accessibility_captioning_window_color = 48;
- optional SettingProto accessibility_captioning_typeface = 49;
- optional SettingProto accessibility_captioning_font_scale = 50;
- optional SettingProto accessibility_display_inversion_enabled = 51;
- optional SettingProto accessibility_display_daltonizer_enabled = 52;
- optional SettingProto accessibility_display_daltonizer = 53;
- optional SettingProto accessibility_autoclick_enabled = 54;
- optional SettingProto accessibility_autoclick_delay = 55;
- optional SettingProto accessibility_large_pointer_icon = 56;
- optional SettingProto long_press_timeout = 57;
- optional SettingProto multi_press_timeout = 58;
+ optional SettingProto accessibility_display_magnification_enabled = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_display_magnification_navbar_enabled = 178 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_display_magnification_scale = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_display_magnification_auto_update = 179 [deprecated = true];
+ optional SettingProto accessibility_soft_keyboard_mode = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_captioning_enabled = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_captioning_locale = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_captioning_preset = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_captioning_background_color = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_captioning_foreground_color = 45 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_captioning_edge_type = 46 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_captioning_edge_color = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_captioning_window_color = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_captioning_typeface = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_captioning_font_scale = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_display_inversion_enabled = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_display_daltonizer_enabled = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_display_daltonizer = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_autoclick_enabled = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_autoclick_delay = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_large_pointer_icon = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto long_press_timeout = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto multi_press_timeout = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto enabled_print_services = 59;
optional SettingProto disabled_print_services = 60;
- optional SettingProto display_density_forced = 61;
- optional SettingProto tts_default_rate = 62;
- optional SettingProto tts_default_pitch = 63;
- optional SettingProto tts_default_synth = 64;
- optional SettingProto tts_default_locale = 65;
+ optional SettingProto display_density_forced = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto tts_default_rate = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto tts_default_pitch = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto tts_default_synth = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto tts_default_locale = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto tts_enabled_plugins = 66;
- optional SettingProto connectivity_release_pending_intent_delay_ms = 67;
+ optional SettingProto connectivity_release_pending_intent_delay_ms = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto allowed_geolocation_origins = 68;
- optional SettingProto preferred_tty_mode = 69;
- optional SettingProto enhanced_voice_privacy_enabled = 70;
- optional SettingProto tty_mode_enabled = 71;
- optional SettingProto backup_enabled = 72;
- optional SettingProto backup_auto_restore = 73;
- optional SettingProto backup_provisioned = 74;
- optional SettingProto backup_transport = 75;
- optional SettingProto last_setup_shown = 76;
- optional SettingProto search_global_search_activity = 77;
- optional SettingProto search_num_promoted_sources = 78;
- optional SettingProto search_max_results_to_display = 79;
- optional SettingProto search_max_results_per_source = 80;
- optional SettingProto search_web_results_override_limit = 81;
- optional SettingProto search_promoted_source_deadline_millis = 82;
- optional SettingProto search_source_timeout_millis = 83;
- optional SettingProto search_prefill_millis = 84;
- optional SettingProto search_max_stat_age_millis = 85;
- optional SettingProto search_max_source_event_age_millis = 86;
- optional SettingProto search_min_impressions_for_source_ranking = 87;
- optional SettingProto search_min_clicks_for_source_ranking = 88;
- optional SettingProto search_max_shortcuts_returned = 89;
- optional SettingProto search_query_thread_core_pool_size = 90;
- optional SettingProto search_query_thread_max_pool_size = 91;
- optional SettingProto search_shortcut_refresh_core_pool_size = 92;
- optional SettingProto search_shortcut_refresh_max_pool_size = 93;
- optional SettingProto search_thread_keepalive_seconds = 94;
- optional SettingProto search_per_source_concurrent_query_limit = 95;
- optional SettingProto mount_play_notification_snd = 96;
- optional SettingProto mount_ums_autostart = 97;
- optional SettingProto mount_ums_prompt = 98;
- optional SettingProto mount_ums_notify_enabled = 99;
- optional SettingProto anr_show_background = 100;
- optional SettingProto voice_recognition_service = 101;
- optional SettingProto package_verifier_user_consent = 102;
- optional SettingProto selected_spell_checker = 103;
- optional SettingProto selected_spell_checker_subtype = 104;
- optional SettingProto spell_checker_enabled = 105;
- optional SettingProto incall_power_button_behavior = 106;
- optional SettingProto incall_back_button_behavior = 107;
- optional SettingProto wake_gesture_enabled = 108;
- optional SettingProto doze_enabled = 109;
- optional SettingProto doze_always_on = 110;
- optional SettingProto doze_pulse_on_pick_up = 111;
- optional SettingProto doze_pulse_on_long_press = 180;
- optional SettingProto doze_pulse_on_double_tap = 112;
- optional SettingProto ui_night_mode = 113;
- optional SettingProto screensaver_enabled = 114;
- optional SettingProto screensaver_components = 115;
- optional SettingProto screensaver_activate_on_dock = 116;
- optional SettingProto screensaver_activate_on_sleep = 117;
- optional SettingProto screensaver_default_component = 118;
- optional SettingProto nfc_payment_default_component = 119;
- optional SettingProto nfc_payment_foreground = 120;
- optional SettingProto sms_default_application = 121;
- optional SettingProto dialer_default_application = 122;
- optional SettingProto emergency_assistance_application = 123;
- optional SettingProto assist_structure_enabled = 124;
- optional SettingProto assist_screenshot_enabled = 125;
- optional SettingProto assist_disclosure_enabled = 126;
- optional SettingProto enabled_notification_assistant = 127;
- optional SettingProto enabled_notification_listeners = 128;
- optional SettingProto enabled_notification_policy_access_packages = 129;
- optional SettingProto sync_parent_sounds = 130;
- optional SettingProto immersive_mode_confirmations = 131;
- optional SettingProto print_service_search_uri = 132;
- optional SettingProto payment_service_search_uri = 133;
- optional SettingProto autofill_service_search_uri = 181;
- optional SettingProto skip_first_use_hints = 134;
- optional SettingProto unsafe_volume_music_active_ms = 135;
- optional SettingProto lock_screen_show_notifications = 136;
+ optional SettingProto preferred_tty_mode = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enhanced_voice_privacy_enabled = 70 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto tty_mode_enabled = 71 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto backup_enabled = 72 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto backup_auto_restore = 73 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto backup_provisioned = 74 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto backup_transport = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto last_setup_shown = 76 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_global_search_activity = 77 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_num_promoted_sources = 78 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_max_results_to_display = 79 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_max_results_per_source = 80 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_web_results_override_limit = 81 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_promoted_source_deadline_millis = 82 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_source_timeout_millis = 83 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_prefill_millis = 84 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_max_stat_age_millis = 85 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_max_source_event_age_millis = 86 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_min_impressions_for_source_ranking = 87 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_min_clicks_for_source_ranking = 88 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_max_shortcuts_returned = 89 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_query_thread_core_pool_size = 90 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_query_thread_max_pool_size = 91 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_shortcut_refresh_core_pool_size = 92 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_shortcut_refresh_max_pool_size = 93 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_thread_keepalive_seconds = 94 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto search_per_source_concurrent_query_limit = 95 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Whether or not alert sounds are played on StorageManagerService events.
+ optional SettingProto mount_play_notification_snd = 96 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto mount_ums_autostart = 97 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto mount_ums_prompt = 98 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto mount_ums_notify_enabled = 99 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto anr_show_background = 100 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The ComponentName string of the service to be used as the voice
+ // recognition service.
+ optional SettingProto voice_recognition_service = 101 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto package_verifier_user_consent = 102 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto selected_spell_checker = 103 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto selected_spell_checker_subtype = 104 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto spell_checker_enabled = 105 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto incall_power_button_behavior = 106 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto incall_back_button_behavior = 107 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto wake_gesture_enabled = 108 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto doze_enabled = 109 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto doze_always_on = 110 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto doze_pulse_on_pick_up = 111 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto doze_pulse_on_long_press = 180 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto doze_pulse_on_double_tap = 112 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto ui_night_mode = 113 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screensaver_enabled = 114 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screensaver_components = 115 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screensaver_activate_on_dock = 116 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screensaver_activate_on_sleep = 117 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screensaver_default_component = 118 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto nfc_payment_default_component = 119 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto nfc_payment_foreground = 120 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sms_default_application = 121 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dialer_default_application = 122 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto emergency_assistance_application = 123 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto assist_structure_enabled = 124 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto assist_screenshot_enabled = 125 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto assist_disclosure_enabled = 126 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Read only list of the service components that the current user has
+ // explicitly allowed to see and assist with all of the user's
+ // notifications.
+ optional SettingProto enabled_notification_assistant = 127 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enabled_notification_listeners = 128 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto enabled_notification_policy_access_packages = 129 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Defines whether managed profile ringtones should be synced from its
+ // parent profile.
+ optional SettingProto sync_parent_sounds = 130 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto immersive_mode_confirmations = 131 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The query URI to find a print service to install.
+ optional SettingProto print_service_search_uri = 132 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The query URI to find an NFC service to install.
+ optional SettingProto payment_service_search_uri = 133 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The query URI to find an auto fill service to install.
+ optional SettingProto autofill_service_search_uri = 181 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto skip_first_use_hints = 134 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto unsafe_volume_music_active_ms = 135 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lock_screen_show_notifications = 136 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto tv_input_hidden_inputs = 137;
optional SettingProto tv_input_custom_labels = 138;
- optional SettingProto usb_audio_automatic_routing_disabled = 139;
- optional SettingProto sleep_timeout = 140;
- optional SettingProto double_tap_to_wake = 141;
- optional SettingProto assistant = 142;
- optional SettingProto camera_gesture_disabled = 143;
- optional SettingProto camera_double_tap_power_gesture_disabled = 144;
- optional SettingProto camera_double_twist_to_flip_enabled = 145;
- optional SettingProto camera_lift_trigger_enabled = 182;
- optional SettingProto assist_gesture_enabled = 183;
- optional SettingProto assist_gesture_sensitivity = 184;
- optional SettingProto assist_gesture_silence_alerts_enabled = 185;
- optional SettingProto assist_gesture_wake_enabled = 186;
- optional SettingProto assist_gesture_setup_complete = 187;
- optional SettingProto night_display_activated = 146;
- optional SettingProto night_display_auto_mode = 147;
- optional SettingProto night_display_color_temperature = 188;
- optional SettingProto night_display_custom_start_time = 148;
- optional SettingProto night_display_custom_end_time = 149;
- optional SettingProto night_display_last_activated_time = 189;
+ optional SettingProto usb_audio_automatic_routing_disabled = 139 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sleep_timeout = 140 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto double_tap_to_wake = 141 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // The current assistant component. It could be a voice interaction service,
+ // or an activity that handles ACTION_ASSIST, or empty, which means using
+ // the default handling.
+ optional SettingProto assistant = 142 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto camera_gesture_disabled = 143 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto camera_double_tap_power_gesture_disabled = 144 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto camera_double_twist_to_flip_enabled = 145 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto camera_lift_trigger_enabled = 182 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto assist_gesture_enabled = 183 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto assist_gesture_sensitivity = 184 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto assist_gesture_silence_alerts_enabled = 185 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto assist_gesture_wake_enabled = 186 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto assist_gesture_setup_complete = 187 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto night_display_activated = 146 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto night_display_auto_mode = 147 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto night_display_color_temperature = 188 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto night_display_custom_start_time = 148 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto night_display_custom_end_time = 149 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto night_display_last_activated_time = 189 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto brightness_use_twilight = 150;
- optional SettingProto enabled_vr_listeners = 151;
- optional SettingProto vr_display_mode = 152;
- optional SettingProto carrier_apps_handled = 153;
- optional SettingProto managed_profile_contact_remote_search = 154;
- optional SettingProto automatic_storage_manager_enabled = 155;
- optional SettingProto automatic_storage_manager_days_to_retain = 156;
- optional SettingProto automatic_storage_manager_bytes_cleared = 157;
- optional SettingProto automatic_storage_manager_last_run = 158;
- optional SettingProto automatic_storage_manager_turned_off_by_policy = 190;
- optional SettingProto system_navigation_keys_enabled = 159;
+ optional SettingProto enabled_vr_listeners = 151 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto vr_display_mode = 152 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto carrier_apps_handled = 153 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto managed_profile_contact_remote_search = 154 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto automatic_storage_manager_enabled = 155 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto automatic_storage_manager_days_to_retain = 156 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto automatic_storage_manager_bytes_cleared = 157 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto automatic_storage_manager_last_run = 158 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto automatic_storage_manager_turned_off_by_policy = 190 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto system_navigation_keys_enabled = 159 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto downloads_backup_enabled = 160;
optional SettingProto downloads_backup_allow_metered = 161;
optional SettingProto downloads_backup_charging_only = 162;
optional SettingProto automatic_storage_manager_downloads_days_to_retain = 163;
- optional SettingProto qs_tiles = 164;
+ // Holds comma-separated list of ordering of QuickSettings tiles.
+ optional SettingProto qs_tiles = 164 [ (android.privacy).dest = DEST_AUTOMATIC ];
reserved 165; // Removed demo_user_setup_complete
- optional SettingProto instant_apps_enabled = 166;
- optional SettingProto device_paired = 167;
- optional SettingProto package_verifier_state = 191;
- optional SettingProto cmas_additional_broadcast_pkg = 192;
- optional SettingProto notification_badging = 168;
- optional SettingProto qs_auto_added_tiles = 193;
- optional SettingProto lockdown_in_power_menu = 194;
+ optional SettingProto instant_apps_enabled = 166 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto device_paired = 167 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto package_verifier_state = 191 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto cmas_additional_broadcast_pkg = 192 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto notification_badging = 168 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto qs_auto_added_tiles = 193 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lockdown_in_power_menu = 194 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto backup_manager_constants = 169;
- optional SettingProto show_first_crash_dialog_dev_option = 195;
- optional SettingProto bluetooth_on_while_driving = 196;
+ optional SettingProto show_first_crash_dialog_dev_option = 195 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_on_while_driving = 196 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Please insert fields in the same order as in
+ // frameworks/base/core/java/android/provider/Settings.java.
// Next tag = 197
}
message SystemSettingsProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
repeated SettingsOperationProto historical_operations = 1;
- optional SettingProto end_button_behavior = 2;
- optional SettingProto advanced_settings = 3;
- optional SettingProto bluetooth_discoverability = 4;
- optional SettingProto bluetooth_discoverability_timeout = 5;
- optional SettingProto font_scale = 6;
- optional SettingProto system_locales = 7;
- optional SettingProto display_color_mode = 67;
- optional SettingProto screen_off_timeout = 8;
- optional SettingProto screen_brightness = 9;
- optional SettingProto screen_brightness_for_vr = 10;
- optional SettingProto screen_brightness_mode = 11;
- optional SettingProto screen_auto_brightness_adj = 12;
- optional SettingProto mode_ringer_streams_affected = 13;
- optional SettingProto mute_streams_affected = 14;
- optional SettingProto vibrate_on = 15;
- optional SettingProto vibrate_input_devices = 16;
- optional SettingProto volume_ring = 17;
- optional SettingProto volume_system = 18;
- optional SettingProto volume_voice = 19;
- optional SettingProto volume_music = 20;
- optional SettingProto volume_alarm = 21;
- optional SettingProto volume_notification = 22;
- optional SettingProto volume_bluetooth_sco = 23;
- optional SettingProto volume_accessibility = 68;
- optional SettingProto volume_master = 24;
- optional SettingProto master_mono = 25;
+ optional SettingProto end_button_behavior = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto advanced_settings = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_discoverability = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bluetooth_discoverability_timeout = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto font_scale = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto system_locales = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto display_color_mode = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screen_off_timeout = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screen_brightness = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screen_brightness_for_vr = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screen_brightness_mode = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto screen_auto_brightness_adj = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Determines which streams are affected by ringer mode changes. The stream
+ // type's bit will be set to 1 if it should be muted when going into an
+ // inaudible ringer mode.
+ optional SettingProto mode_ringer_streams_affected = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto mute_streams_affected = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto vibrate_on = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto vibrate_input_devices = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto volume_ring = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto volume_system = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto volume_voice = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto volume_music = 20 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto volume_alarm = 21 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto volume_notification = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto volume_bluetooth_sco = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto volume_accessibility = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto volume_master = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto master_mono = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
// Whether silent mode should allow vibration feedback. This is used
// internally in AudioService and the Sound settings activity to coordinate
// decoupling of vibrate and silent modes. This setting will likely be
@@ -641,8 +710,10 @@
// Not used anymore. On devices with vibrator, the user explicitly selects
// silent or vibrate mode. Kept for use by legacy database upgrade code in
// DatabaseHelper.
- optional SettingProto vibrate_in_silent = 26;
- optional SettingProto append_for_last_audible = 27;
+ optional SettingProto vibrate_in_silent = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Appended to various volume related settings to record the previous values
+ // before the settings were affected by a silent/vibrate ringer mode change.
+ optional SettingProto append_for_last_audible = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto ringtone = 28;
optional SettingProto ringtone_cache = 29;
optional SettingProto notification_sound = 30;
@@ -650,44 +721,47 @@
optional SettingProto alarm_alert = 32;
optional SettingProto alarm_alert_cache = 33;
optional SettingProto media_button_receiver = 34;
- optional SettingProto text_auto_replace = 35;
- optional SettingProto text_auto_caps = 36;
- optional SettingProto text_auto_punctuate = 37;
- optional SettingProto text_show_password = 38;
- optional SettingProto show_gtalk_service_status = 39;
- optional SettingProto time_12_24 = 40;
- optional SettingProto date_format = 41;
- optional SettingProto setup_wizard_has_run = 42;
- optional SettingProto accelerometer_rotation = 43;
- optional SettingProto user_rotation = 44;
- optional SettingProto hide_rotation_lock_toggle_for_accessibility = 45;
- optional SettingProto vibrate_when_ringing = 46;
- optional SettingProto dtmf_tone_when_dialing = 47;
- optional SettingProto dtmf_tone_type_when_dialing = 48;
- optional SettingProto hearing_aid = 49;
- optional SettingProto tty_mode = 50;
- optional SettingProto sound_effects_enabled = 51;
- optional SettingProto haptic_feedback_enabled = 52;
- optional SettingProto notification_light_pulse = 53;
- optional SettingProto pointer_location = 54;
- optional SettingProto show_touches = 55;
+ optional SettingProto text_auto_replace = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto text_auto_caps = 36 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto text_auto_punctuate = 37 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto text_show_password = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_gtalk_service_status = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto time_12_24 = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto date_format = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto setup_wizard_has_run = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accelerometer_rotation = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto user_rotation = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto hide_rotation_lock_toggle_for_accessibility = 45 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto vibrate_when_ringing = 46 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dtmf_tone_when_dialing = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto dtmf_tone_type_when_dialing = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto hearing_aid = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto tty_mode = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sound_effects_enabled = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto haptic_feedback_enabled = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto notification_light_pulse = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Show pointer location on screen? 0 = no, 1 = yes.
+ optional SettingProto pointer_location = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_touches = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
// Log raw orientation data from {@link
// com.android.server.policy.WindowOrientationListener} for use with the
// orientationplot.py tool.
// 0 = no, 1 = yes
- optional SettingProto window_orientation_listener_log = 56;
- optional SettingProto lockscreen_sounds_enabled = 57;
- optional SettingProto lockscreen_disabled = 58;
- optional SettingProto sip_receive_calls = 59;
- optional SettingProto sip_call_options = 60;
- optional SettingProto sip_always = 61;
- optional SettingProto sip_address_only = 62;
- optional SettingProto pointer_speed = 63;
- optional SettingProto lock_to_app_enabled = 64;
- optional SettingProto egg_mode = 65;
- optional SettingProto show_battery_percent = 69;
- optional SettingProto when_to_make_wifi_calls = 66;
+ optional SettingProto window_orientation_listener_log = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lockscreen_sounds_enabled = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lockscreen_disabled = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sip_receive_calls = 59 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sip_call_options = 60 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sip_always = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto sip_address_only = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto pointer_speed = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto lock_to_app_enabled = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto egg_mode = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_battery_percent = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto when_to_make_wifi_calls = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Please insert fields in the same order as in
+ // frameworks/base/core/java/android/provider/Settings.java.
// Next tag = 70;
}
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 55e6a74..788d901 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -130,6 +130,8 @@
repeated StickyBroadcastProto sticky_broadcasts = 4;
message MainHandler {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional string handler = 1;
optional .android.os.LooperProto looper = 2;
}
@@ -663,7 +665,7 @@
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
optional .android.os.PowerManagerInternalProto.Wakefulness wakefulness = 1;
- repeated string sleep_tokens = 2;
+ repeated string sleep_tokens = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional bool sleeping = 3;
optional bool shutting_down = 4;
optional bool test_pss_mode = 5;
@@ -671,7 +673,7 @@
optional SleepStatus sleep_status = 27;
message VoiceProto {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+ option (.android.msg_privacy).dest = DEST_EXPLICIT;
optional string session = 1;
optional .android.os.PowerManagerProto.WakeLockProto wakelock = 2;
@@ -725,7 +727,7 @@
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
optional string proc_name = 1;
- optional string file = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
+ optional string file = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional int32 pid = 3;
optional int32 uid = 4;
}
@@ -998,6 +1000,8 @@
optional int64 total_duration_ms = 2;
message PackageTime {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional string package = 1;
optional int64 duration_ms = 2;
}
diff --git a/core/proto/android/server/alarmmanagerservice.proto b/core/proto/android/server/alarmmanagerservice.proto
index 53b4be4..aa2663f 100644
--- a/core/proto/android/server/alarmmanagerservice.proto
+++ b/core/proto/android/server/alarmmanagerservice.proto
@@ -21,12 +21,15 @@
import "frameworks/base/core/proto/android/internal/locallog.proto";
import "frameworks/base/core/proto/android/os/worksource.proto";
import "frameworks/base/core/proto/android/server/forceappstandbytracker.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
package com.android.server;
option java_multiple_files = true;
message AlarmManagerServiceProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int64 current_time = 1;
optional int64 elapsed_realtime = 2;
optional int64 last_time_change_clock_time = 3;
@@ -106,6 +109,8 @@
optional int64 allow_while_idle_min_duration_ms = 35;
message LastAllowWhileIdleDispatch {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 uid = 1;
// In the 'elapsed' timebase.
optional int64 time_ms = 2;
@@ -117,6 +122,8 @@
optional com.android.internal.util.LocalLogProto recent_problems = 37;
message TopAlarm {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 uid = 1;
optional string package_name = 2;
optional FilterStatsProto filter = 3;
@@ -124,6 +131,8 @@
repeated TopAlarm top_alarms = 38;
message AlarmStat {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional BroadcastStatsProto broadcast = 1;
repeated FilterStatsProto filters = 2;
}
@@ -136,6 +145,8 @@
// This is a soft wrapper for alarm clock information. It is not representative
// of an android.app.AlarmManager.AlarmClockInfo object.
message AlarmClockMetadataProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 user = 1;
optional bool is_pending_send = 2;
// This value is UTC wall clock time in milliseconds, as returned by
@@ -145,7 +156,9 @@
// A com.android.server.AlarmManagerService.Alarm object.
message AlarmProto {
- optional string tag = 1;
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional string tag = 1 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional .android.app.AlarmManagerProto.AlarmType type = 2;
// How long until the alarm goes off, in the 'elapsed' timebase. Can be
// negative if 'when' is in the past.
@@ -156,11 +169,13 @@
optional int32 flags = 7;
optional .android.app.AlarmClockInfoProto alarm_clock = 8;
optional .android.app.PendingIntentProto operation = 9;
- optional string listener = 10;
+ optional string listener = 10 [ (.android.privacy).dest = DEST_EXPLICIT ];
}
// A com.android.server.AlarmManagerService.Batch object.
message BatchProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
// Start time in terms of elapsed realtime.
optional int64 start_realtime = 1;
// End time in terms of elapsed realtime.
@@ -171,6 +186,8 @@
// A com.android.server.AlarmManagerService.BroadcastStats object.
message BroadcastStatsProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 uid = 1;
optional string package_name = 2;
// The total amount of time this broadcast was in flight.
@@ -186,6 +203,8 @@
// A com.android.server.AlarmManagerService.Constants object.
message ConstantsProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
// Minimum futurity of a new alarm.
optional int64 min_futurity_duration_ms = 1;
// Minimum alarm recurrence interval.
@@ -202,7 +221,9 @@
// A com.android.server.AlarmManagerService.FilterStats object.
message FilterStatsProto {
- optional string tag = 1;
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional string tag = 1 [ (.android.privacy).dest = DEST_EXPLICIT ];
// The last time this filter when in flight, in terms of elapsed realtime.
optional int64 last_flight_time_realtime = 2;
// The total amount of time this filter was in flight.
@@ -218,9 +239,11 @@
// A com.android.server.AlarmManagerService.IdleDispatchEntry object.
message IdleDispatchEntryProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 uid = 1;
optional string pkg = 2;
- optional string tag = 3;
+ optional string tag = 3 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional string op = 4;
// Time when this entry was created, in terms of elapsed realtime.
optional int64 entry_creation_realtime = 5;
@@ -232,8 +255,10 @@
// A com.android.server.AlarmManagerService.InFlight object.
message InFlightProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 uid = 1;
- optional string tag = 2;
+ optional string tag = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional int64 when_elapsed_ms = 3;
optional .android.app.AlarmManagerProto.AlarmType alarm_type = 4;
optional .android.app.PendingIntentProto pending_intent = 5;
@@ -244,6 +269,8 @@
// A com.android.server.AlarmManagerService.WakeupEvent object.
message WakeupEventProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 uid = 1;
optional string action = 2;
optional int64 when = 3;
diff --git a/core/proto/android/os/batterymanager.proto b/core/proto/android/server/enums.proto
similarity index 61%
rename from core/proto/android/os/batterymanager.proto
rename to core/proto/android/server/enums.proto
index 669bf2d..ef02438 100644
--- a/core/proto/android/os/batterymanager.proto
+++ b/core/proto/android/server/enums.proto
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 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.
@@ -15,15 +15,16 @@
*/
syntax = "proto2";
-package android.os;
+package android.server;
+option java_outer_classname = "ServerProtoEnums";
option java_multiple_files = true;
-message BatteryManagerProto {
- enum PlugType {
- PLUG_TYPE_NONE = 0;
- PLUG_TYPE_AC = 1;
- PLUG_TYPE_USB = 2;
- PLUG_TYPE_WIRELESS = 4;
- }
+enum DeviceIdleModeEnum {
+ // Device idle mode - not active.
+ DEVICE_IDLE_MODE_OFF = 0;
+ // Device idle mode - active in lightweight mode.
+ DEVICE_IDLE_MODE_LIGHT = 1;
+ // Device idle mode - active in full mode.
+ DEVICE_IDLE_MODE_DEEP = 2;
}
diff --git a/core/proto/android/server/forceappstandbytracker.proto b/core/proto/android/server/forceappstandbytracker.proto
index 5657f96..43c869c 100644
--- a/core/proto/android/server/forceappstandbytracker.proto
+++ b/core/proto/android/server/forceappstandbytracker.proto
@@ -16,12 +16,13 @@
syntax = "proto2";
+import "frameworks/base/core/proto/android/server/statlogger.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
package com.android.server;
option java_multiple_files = true;
-import "frameworks/base/libs/incident/proto/android/privacy.proto";
-
// Dump from com.android.server.ForceAppStandbyTracker.
message ForceAppStandbyTrackerProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -53,6 +54,19 @@
// Whether force app standby for small battery device setting is enabled
optional bool force_all_apps_standby_for_small_battery = 7;
- // Whether device is charging
- optional bool is_charging = 8;
+ // Whether device is plugged in to the charger
+ optional bool is_plugged_in = 8;
+
+ // Performance stats.
+ optional StatLoggerProto stats = 9;
+
+ message ExemptedPackage {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional int32 userId = 1;
+ optional string package_name = 2;
+ }
+
+ // Packages that are in the EXEMPT bucket.
+ repeated ExemptedPackage exempted_packages = 10;
}
diff --git a/core/proto/android/server/intentresolver.proto b/core/proto/android/server/intentresolver.proto
index 60c060c..0ada895 100644
--- a/core/proto/android/server/intentresolver.proto
+++ b/core/proto/android/server/intentresolver.proto
@@ -19,9 +19,15 @@
package com.android.server;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
message IntentResolverProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
message ArrayMapEntry {
+ option (.android.msg_privacy).dest = DEST_EXPLICIT;
+
optional string key = 1;
repeated string values = 2;
}
diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto
index babbef0..b5c3ac0 100644
--- a/core/proto/android/server/powermanagerservice.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -21,13 +21,13 @@
import "frameworks/base/core/proto/android/app/enums.proto";
import "frameworks/base/core/proto/android/content/intent.proto";
-import "frameworks/base/core/proto/android/os/batterymanager.proto";
+import "frameworks/base/core/proto/android/os/enums.proto";
import "frameworks/base/core/proto/android/os/looper.proto";
import "frameworks/base/core/proto/android/os/powermanager.proto";
import "frameworks/base/core/proto/android/os/worksource.proto";
import "frameworks/base/core/proto/android/providers/settings.proto";
import "frameworks/base/core/proto/android/server/wirelesschargerdetector.proto";
-import "frameworks/base/core/proto/android/view/display.proto";
+import "frameworks/base/core/proto/android/view/enums.proto";
import "frameworks/base/libs/incident/proto/android/privacy.proto";
message PowerManagerServiceDumpProto {
@@ -80,7 +80,7 @@
// True if the device is plugged into a power source.
optional bool is_powered = 5;
// The current plug type
- optional .android.os.BatteryManagerProto.PlugType plug_type = 6;
+ optional .android.os.BatteryPluggedStateEnum plug_type = 6;
// The current battery level percentage.
optional int32 battery_level = 7;
// The battery level percentage at the time the dream started.
@@ -197,7 +197,7 @@
optional bool is_on_after_release = 2;
}
- optional .android.os.PowerManagerProto.WakeLockLevel lock_level = 1;
+ optional .android.os.WakeLockLevelEnum lock_level = 1;
optional string tag = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional WakeLockFlagsProto flags = 3;
optional bool is_disabled = 4;
@@ -322,7 +322,7 @@
// Use NaN to disable.
optional float temporary_screen_auto_brightness_adjustment_setting_override = 37;
// The screen state to use while dozing.
- optional .android.view.DisplayProto.DisplayState doze_screen_state_override_from_dream_manager = 38;
+ optional .android.view.DisplayStateEnum doze_screen_state_override_from_dream_manager = 38;
// The screen brightness to use while dozing.
optional float dozed_screen_brightness_override_from_dream_manager = 39;
// Screen brightness settings limits.
diff --git a/core/proto/android/server/statlogger.proto b/core/proto/android/server/statlogger.proto
new file mode 100644
index 0000000..2ae526a
--- /dev/null
+++ b/core/proto/android/server/statlogger.proto
@@ -0,0 +1,37 @@
+/*
+ * 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 com.android.server;
+
+option java_multiple_files = true;
+
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+// Dump from StatLogger.
+message StatLoggerProto {
+ option (.android.msg_privacy).dest = DEST_EXPLICIT;
+
+ message Event {
+ optional int32 eventId = 1;
+ optional string label = 2;
+ optional int32 count = 3;
+ optional int64 total_duration_micros = 4;
+ }
+
+ repeated Event events = 1;
+}
diff --git a/core/proto/android/server/wirelesschargerdetector.proto b/core/proto/android/server/wirelesschargerdetector.proto
index 89cf2f8..2118deb 100644
--- a/core/proto/android/server/wirelesschargerdetector.proto
+++ b/core/proto/android/server/wirelesschargerdetector.proto
@@ -19,8 +19,14 @@
option java_multiple_files = true;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
message WirelessChargerDetectorProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
message VectorProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional float x = 1;
optional float y = 2;
optional float z = 3;
diff --git a/core/proto/android/service/battery.proto b/core/proto/android/service/battery.proto
index 42fa72c..34cb229 100644
--- a/core/proto/android/service/battery.proto
+++ b/core/proto/android/service/battery.proto
@@ -20,35 +20,16 @@
option java_multiple_files = true;
option java_outer_classname = "BatteryServiceProto";
-import "frameworks/base/core/proto/android/os/batterymanager.proto";
+import "frameworks/base/core/proto/android/os/enums.proto";
import "frameworks/base/libs/incident/proto/android/privacy.proto";
message BatteryServiceDumpProto {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
- enum BatteryStatus {
- BATTERY_STATUS_INVALID = 0;
- BATTERY_STATUS_UNKNOWN = 1;
- BATTERY_STATUS_CHARGING = 2;
- BATTERY_STATUS_DISCHARGING = 3;
- BATTERY_STATUS_NOT_CHARGING = 4;
- BATTERY_STATUS_FULL = 5;
- }
- enum BatteryHealth {
- BATTERY_HEALTH_INVALID = 0;
- BATTERY_HEALTH_UNKNOWN = 1;
- BATTERY_HEALTH_GOOD = 2;
- BATTERY_HEALTH_OVERHEAT = 3;
- BATTERY_HEALTH_DEAD = 4;
- BATTERY_HEALTH_OVER_VOLTAGE = 5;
- BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6;
- BATTERY_HEALTH_COLD = 7;
- }
-
// If true: UPDATES STOPPED -- use 'reset' to restart
optional bool are_updates_stopped = 1;
// Plugged status of power sources
- optional android.os.BatteryManagerProto.PlugType plugged = 2;
+ optional android.os.BatteryPluggedStateEnum plugged = 2;
// Max current in microamperes. This may be 0 if the device's kernel drivers
// don't support it.
optional int32 max_charging_current = 3;
@@ -58,9 +39,9 @@
// Battery capacity in microampere-hours
optional int32 charge_counter = 5;
// Charging status
- optional BatteryStatus status = 6;
+ optional android.os.BatteryStatusEnum status = 6;
// Battery health
- optional BatteryHealth health = 7;
+ optional android.os.BatteryHealthEnum health = 7;
// True if the battery is present
optional bool is_present = 8;
// Charge level, from 0 through "scale" inclusive
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index 65df89a..5c40e5f 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -25,8 +25,11 @@
import "frameworks/base/core/proto/android/app/notificationmanager.proto";
import "frameworks/base/core/proto/android/content/component_name.proto";
import "frameworks/base/core/proto/android/media/audioattributes.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
message NotificationServiceDumpProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
repeated NotificationRecordProto records = 1;
optional ZenModeProto zen = 2;
@@ -45,6 +48,8 @@
}
message NotificationRecordProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional string key = 1;
enum State {
@@ -54,21 +59,25 @@
}
optional State state = 2;
optional int32 flags = 3;
- optional string channelId = 4;
- optional string sound = 5;
+ optional string channelId = 4 [ (.android.privacy).dest = DEST_EXPLICIT ];
+ optional string sound = 5 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional .android.media.AudioAttributesProto audio_attributes = 6;
optional bool can_vibrate = 7;
optional bool can_show_light = 8;
- optional string group_key = 9;
+ optional string group_key = 9 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional int32 importance = 10;
}
message ListenersDisablingEffectsProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 hint = 1;
repeated ManagedServiceInfoProto listeners = 2;
}
message ManagedServiceInfoProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional android.content.ComponentNameProto component = 1;
optional int32 user_id = 2;
optional string service = 3;
@@ -77,10 +86,14 @@
}
message ManagedServicesProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional string caption = 1;
message ServiceProto {
- repeated string name = 1;
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ repeated string name = 1 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional int32 user_id = 2;
optional bool is_primary = 3;
}
@@ -97,9 +110,13 @@
}
message RankingHelperProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
repeated string notification_signal_extractors = 1;
message RecordProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional string package = 1;
// Default value is UNKNOWN_UID = USER_NULL = -10000.
optional int32 uid = 2;
@@ -118,16 +135,72 @@
repeated RecordProto records_restored_without_uid = 3;
}
-message ZenModeProto {
- enum ZenMode {
- ZEN_MODE_OFF = 0;
- ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
- ZEN_MODE_NO_INTERRUPTIONS = 2;
- ZEN_MODE_ALARMS = 3;
+enum ZenMode {
+ ZEN_MODE_OFF = 0;
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
+ ZEN_MODE_NO_INTERRUPTIONS = 2;
+ ZEN_MODE_ALARMS = 3;
+}
+
+// An android.service.notification.Condition object.
+message ConditionProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional string id = 1;
+ optional string summary = 2;
+ optional string line_1 = 3;
+ optional string line_2 = 4;
+ optional int32 icon = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ enum State {
+ // Indicates that Do Not Disturb should be turned off.
+ STATE_FALSE = 0;
+ // Indicates that Do Not Disturb should be turned on.
+ STATE_TRUE = 1;
+ STATE_UNKNOWN = 2;
+ STATE_ERROR = 3;
}
+ optional State state = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ optional int32 flags = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+}
+
+// An android.service.notification.ZenModeConfig.ZenRule object.
+message ZenRuleProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // Required for automatic (unique).
+ optional string id = 1;
+ // Required for automatic.
+ optional string name = 2;
+ // Required for automatic.
+ optional int64 creation_time_ms = 3 [
+ (android.privacy).dest = DEST_AUTOMATIC
+ ];
+ optional bool enabled = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Package name, only used for manual rules.
+ optional string enabler = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // User manually disabled this instance.
+ optional bool is_snoozing = 6 [
+ (android.privacy).dest = DEST_AUTOMATIC
+ ];
+ optional ZenMode zen_mode = 7 [
+ (android.privacy).dest = DEST_AUTOMATIC
+ ];
+
+ // Required for automatic.
+ optional string condition_id = 8;
+ optional ConditionProto condition = 9;
+ optional android.content.ComponentNameProto component = 10;
+}
+
+// A dump from com.android.server.notification.ZenModeHelper.
+message ZenModeProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional ZenMode zen_mode = 1;
- repeated string enabled_active_conditions = 2;
+ repeated ZenRuleProto enabled_active_conditions = 2;
optional int32 suppressed_effects = 3;
- repeated string suppressors = 4;
+ repeated android.content.ComponentNameProto suppressors = 4;
optional android.app.PolicyProto policy = 5;
}
diff --git a/core/proto/android/service/procstats.proto b/core/proto/android/service/procstats.proto
index 4c11f1e..15ede0c 100644
--- a/core/proto/android/service/procstats.proto
+++ b/core/proto/android/service/procstats.proto
@@ -169,6 +169,9 @@
// USS is memory shared between processes, divided evenly for accounting
optional android.util.AggStats uss = 7;
+
+ // RSS is memory resident for this process
+ optional android.util.AggStats rss = 8;
}
repeated State states = 5;
}
diff --git a/core/proto/android/telephony/enums.proto b/core/proto/android/telephony/enums.proto
new file mode 100644
index 0000000..60f8d8d
--- /dev/null
+++ b/core/proto/android/telephony/enums.proto
@@ -0,0 +1,38 @@
+/*
+ * 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.telephony;
+
+option java_outer_classname = "TelephonyProtoEnums";
+option java_multiple_files = true;
+
+// Data conn. power states, primarily used by android/telephony/DataConnectionRealTimeInfo.java.
+enum DataConnectionPowerStateEnum {
+ DATA_CONNECTION_POWER_STATE_LOW = 1;
+ DATA_CONNECTION_POWER_STATE_MEDIUM = 2;
+ DATA_CONNECTION_POWER_STATE_HIGH = 3;
+ DATA_CONNECTION_POWER_STATE_UNKNOWN = 2147483647; // Java Integer.MAX_VALUE;
+}
+
+// Signal strength levels, primarily used by android/telephony/SignalStrength.java.
+enum SignalStrengthEnum {
+ SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
+ SIGNAL_STRENGTH_POOR = 1;
+ SIGNAL_STRENGTH_MODERATE = 2;
+ SIGNAL_STRENGTH_GOOD = 3;
+ SIGNAL_STRENGTH_GREAT = 4;
+}
diff --git a/core/proto/android/telephony/signalstrength.proto b/core/proto/android/telephony/signalstrength.proto
deleted file mode 100644
index 366f1d1..0000000
--- a/core/proto/android/telephony/signalstrength.proto
+++ /dev/null
@@ -1,34 +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.
- */
-
-syntax = "proto2";
-option java_package = "android.telephony";
-option java_multiple_files = true;
-
-package android.telephony;
-
-/**
- * An android.telephony.SignalStrength object.
- */
-message SignalStrengthProto {
- enum StrengthName {
- SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
- SIGNAL_STRENGTH_POOR = 1;
- SIGNAL_STRENGTH_MODERATE = 2;
- SIGNAL_STRENGTH_GOOD = 3;
- SIGNAL_STRENGTH_GREAT = 4;
- }
-}
diff --git a/core/proto/android/util/event_log_tags.proto b/core/proto/android/util/event_log_tags.proto
index cb039be..457219f 100644
--- a/core/proto/android/util/event_log_tags.proto
+++ b/core/proto/android/util/event_log_tags.proto
@@ -19,17 +19,25 @@
option java_multiple_files = true;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
// Proto representation of event.logtags.
// Usually sit in /system/etc/event-log-tags.
message EventLogTagMapProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
repeated EventLogTag event_log_tags = 1;
}
message EventLogTag {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional uint32 tag_number = 1; // keyed by tag number.
optional string tag_name = 2;
message ValueDescriptor {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional string name = 1;
enum DataType {
@@ -55,4 +63,4 @@
optional DataUnit unit = 3;
}
repeated ValueDescriptor value_descriptors = 3;
-}
\ No newline at end of file
+}
diff --git a/core/proto/android/view/display.proto b/core/proto/android/view/display.proto
index cac0830..30046c3 100644
--- a/core/proto/android/view/display.proto
+++ b/core/proto/android/view/display.proto
@@ -20,24 +20,6 @@
option java_multiple_files = true;
message DisplayProto {
- enum DisplayState {
- // The display state is unknown.
- DISPLAY_STATE_UNKNOWN = 0;
- // The display state is off.
- DISPLAY_STATE_OFF = 1;
- // The display state is on.
- DISPLAY_STATE_ON = 2;
- // The display is dozing in a low power state; it is still on but is
- // optimized for showing system-provided content while the device is
- // non-interactive.
- DISPLAY_STATE_DOZE = 3;
- // The display is dozing in a suspended low power state; it is still on
- // but is optimized for showing static system-provided content while the
- // device is non-interactive.
- DISPLAY_STATE_DOZE_SUSPEND = 4;
- // The display is on and optimized for VR mode.
- DISPLAY_STATE_VR = 5;
- }
enum ColorMode {
COLOR_MODE_INVALID = -1;
COLOR_MODE_BT601_625 = 1;
diff --git a/core/proto/android/view/displaycutout.proto b/core/proto/android/view/displaycutout.proto
index ff13fab..ee258b7 100644
--- a/core/proto/android/view/displaycutout.proto
+++ b/core/proto/android/view/displaycutout.proto
@@ -17,11 +17,14 @@
syntax = "proto2";
import "frameworks/base/core/proto/android/graphics/rect.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
package android.view;
option java_multiple_files = true;
message DisplayCutoutProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional .android.graphics.RectProto insets = 1;
optional .android.graphics.RectProto bounds = 2;
}
diff --git a/core/proto/android/view/enums.proto b/core/proto/android/view/enums.proto
new file mode 100644
index 0000000..10785ce
--- /dev/null
+++ b/core/proto/android/view/enums.proto
@@ -0,0 +1,44 @@
+/*
+ * 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.view;
+
+option java_outer_classname = "ViewProtoEnums";
+option java_multiple_files = true;
+
+// Screen states, primarily used by android/view/Display.java.
+enum DisplayStateEnum {
+ // The display state is unknown.
+ DISPLAY_STATE_UNKNOWN = 0;
+ // The display state is off.
+ DISPLAY_STATE_OFF = 1;
+ // The display state is on.
+ DISPLAY_STATE_ON = 2;
+ // The display is dozing in a low power state; it is still on but is
+ // optimized for showing system-provided content while the device is
+ // non-interactive.
+ DISPLAY_STATE_DOZE = 3;
+ // The display is dozing in a suspended low power state; it is still on
+ // but is optimized for showing static system-provided content while the
+ // device is non-interactive.
+ DISPLAY_STATE_DOZE_SUSPEND = 4;
+ // The display is on and optimized for VR mode.
+ DISPLAY_STATE_VR = 5;
+ // The display is in a suspended full power state; it is still on but the
+ // CPU is not updating it.
+ DISPLAY_STATE_ON_SUSPEND = 6;
+}
diff --git a/core/proto/android/view/surfacecontrol.proto b/core/proto/android/view/surfacecontrol.proto
index 9288b4f..665d688 100644
--- a/core/proto/android/view/surfacecontrol.proto
+++ b/core/proto/android/view/surfacecontrol.proto
@@ -19,10 +19,14 @@
option java_multiple_files = true;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
/**
* Represents a {@link android.view.SurfaceControl} object.
*/
message SurfaceControlProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 hash_code = 1;
- optional string name = 2;
+ optional string name = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0861e710..e5ba6d7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -580,6 +580,7 @@
<protected-broadcast android:name="android.app.action.TRANSFER_OWNERSHIP_COMPLETE" />
<protected-broadcast android:name="android.app.action.AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE" />
<protected-broadcast android:name="android.app.action.DATA_SHARING_RESTRICTION_CHANGED" />
+ <protected-broadcast android:name="android.app.action.STATSD_STARTED" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
@@ -1456,6 +1457,12 @@
android:label="@string/permlab_nfc"
android:protectionLevel="normal" />
+ <!-- Allows applications to receive NFC transaction events.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.NFC_TRANSACTION_EVENT"
+ android:protectionLevel="normal" />
+
<!-- @SystemApi Allows an internal user to use privileged ConnectivityManager APIs.
@hide -->
<permission android:name="android.permission.CONNECTIVITY_INTERNAL"
@@ -1952,12 +1959,6 @@
<permission android:name="android.permission.START_ANY_ACTIVITY"
android:protectionLevel="signature" />
- <!-- Allows an application to start an activity as another app, provided that app has been
- granted a permissionToken from the ActivityManagerService.
- @hide -->
- <permission android:name="android.permission.START_ACTIVITY_AS_CALLER"
- android:protectionLevel="signature" />
-
<!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
API is no longer supported. -->
<permission android:name="android.permission.RESTART_PACKAGES"
@@ -2722,6 +2723,15 @@
<permission android:name="android.permission.BIND_AUTOFILL_SERVICE"
android:protectionLevel="signature" />
+ <!-- Alternative version of android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE.
+ This permission was renamed during the O previews but it was supported on the final O
+ release, so we need to carry it over.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_AUTOFILL"
+ android:protectionLevel="signature" />
+
<!-- Must be required by an {@link android.service.autofill.AutofillFieldClassificationService}
to ensure that only the system can bind to it.
@hide This is not a third-party API (intended for OEMs and system apps).
@@ -2729,6 +2739,14 @@
<permission android:name="android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE"
android:protectionLevel="signature" />
+ <!-- Must be required by a android.service.textclassifier.TextClassifierService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_TEXTCLASSIFIER_SERVICE"
+ android:protectionLevel="signature" />
+
<!-- Must be required by hotword enrollment application,
to ensure that only the system can interact with it.
@hide <p>Not for use by third-party applications.</p> -->
@@ -3740,15 +3758,6 @@
<permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"
android:protectionLevel="signature|development|instant|appop" />
- <!-- Allows a regular application to use {@link android.app.Service#startForeground
- Service.startForeground}.
- <p>Protection level: normal
- -->
- <permission android:name="android.permission.FOREGROUND_SERVICE"
- android:description="@string/permdesc_foregroundService"
- android:label="@string/permlab_foregroundService"
- android:protectionLevel="normal|instant" />
-
<!-- @hide Allows system components to access all app shortcuts. -->
<permission android:name="android.permission.ACCESS_SHORTCUTS"
android:protectionLevel="signature" />
@@ -3975,6 +3984,7 @@
android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
android:excludeFromRecents="true"
android:process=":ui"
+ android:label="@string/harmful_app_warning_title"
android:exported="false">
</activity>
diff --git a/core/res/res/anim/activity_close_exit.xml b/core/res/res/anim/activity_close_exit.xml
index 143bedb..d87f100 100644
--- a/core/res/res/anim/activity_close_exit.xml
+++ b/core/res/res/anim/activity_close_exit.xml
@@ -34,11 +34,11 @@
android:toTop="95.9%"
android:toRight="100%"
android:toBottom="100%"
- android:interpolator="@interpolator/exaggerated_ease"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
android:duration="425"/>
<alpha
android:fromAlpha="1.0"
android:toAlpha="1.0"
android:interpolator="@interpolator/fast_out_linear_in"
android:duration="425"/>
-</set>
\ No newline at end of file
+</set>
diff --git a/core/res/res/anim/activity_open_enter.xml b/core/res/res/anim/activity_open_enter.xml
index f9381b4..cb03070 100644
--- a/core/res/res/anim/activity_open_enter.xml
+++ b/core/res/res/anim/activity_open_enter.xml
@@ -32,6 +32,6 @@
android:toTop="0%"
android:toRight="100%"
android:toBottom="100%"
- android:interpolator="@interpolator/exaggerated_ease"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
android:duration="425"/>
-</set>
\ No newline at end of file
+</set>
diff --git a/core/res/res/drawable/red_shield.xml b/core/res/res/drawable/red_shield.xml
new file mode 100644
index 0000000..7f425c7
--- /dev/null
+++ b/core/res/res/drawable/red_shield.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="34dp"
+ android:height="37dp"
+ android:viewportWidth="34"
+ android:viewportHeight="37">
+
+ <group
+ android:translateX="-3.000000"
+ android:translateY="-2.000000">
+ <path
+ android:fillType="evenOdd"
+ android:strokeWidth="1"
+ android:pathData="M 0 0 H 40 V 40 H 0 V 0 Z" />
+ <path
+ android:fillColor="#D0021B"
+ android:fillType="evenOdd"
+ android:strokeWidth="1"
+ android:pathData="M35.5858891,6.865 C27.841629,3.02166667 19.6666667,2 19.6666667,2 C19.6666667,2
+11.4917044,3.02166667 3.74744428,6.865 C3.25808614,8.915 3,11.0533333
+3,13.2533333 C3,15.515 3.27484498,17.715 3.79269315,19.8216667
+C4.89374895,24.3033333 7.09753645,28.355 10.1023965,31.6783333
+C12.7385621,34.5983333 15.9964806,36.955 19.6666667,38.5433333
+C23.3368527,36.955 26.5947712,34.5983333 29.2326127,31.6783333
+C32.2357969,28.355 34.4395844,24.3033333 35.5423161,19.8216667
+C36.0584884,17.715 36.3333333,15.515 36.3333333,13.2533333
+C36.3333333,11.0533333 36.0769231,8.915 35.5858891,6.865 M21.3333333,27.8333333
+L18,27.8333333 L18,24.5 L21.3333333,24.5 L21.3333333,27.8333333
+L21.3333333,27.8333333 Z M21.3333333,22 L18,22 L18,12 L21.3333333,12
+L21.3333333,22 L21.3333333,22 Z" />
+ </group>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/interpolator/emphasized_deceleration.xml b/core/res/res/interpolator/emphasized_deceleration.xml
deleted file mode 100644
index 60c315c..0000000
--- a/core/res/res/interpolator/emphasized_deceleration.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2017 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0.1"
- android:controlY1="0.8"
- android:controlX2="0.2"
- android:controlY2="1"/>
\ No newline at end of file
diff --git a/core/res/res/interpolator/exaggerated_ease.xml b/core/res/res/interpolator/fast_out_extra_slow_in.xml
similarity index 87%
rename from core/res/res/interpolator/exaggerated_ease.xml
rename to core/res/res/interpolator/fast_out_extra_slow_in.xml
index 4961c1c..f160574 100644
--- a/core/res/res/interpolator/exaggerated_ease.xml
+++ b/core/res/res/interpolator/fast_out_extra_slow_in.xml
@@ -16,4 +16,4 @@
-->
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0,0 C 0.05, 0, 0.133333, 0.08, 0.166666, 0.4 C 0.225, 0.94, 0.25, 1, 1, 1"/>
+ android:pathData="M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1"/>
diff --git a/core/res/res/layout/harmful_app_warning_dialog.xml b/core/res/res/layout/harmful_app_warning_dialog.xml
new file mode 100644
index 0000000..d41691f
--- /dev/null
+++ b/core/res/res/layout/harmful_app_warning_dialog.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, Google Inc.
+ *
+ * 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.
+ */
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/harmful_app_padding_top"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/harmful_app_name_padding_bottom"
+ android:paddingLeft="@dimen/harmful_app_name_padding_left"
+ android:paddingRight="@dimen/harmful_app_name_padding_right"
+ android:paddingTop="@dimen/harmful_app_name_padding_top"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:layout_width="@dimen/harmful_app_icon_size"
+ android:layout_height="@dimen/harmful_app_icon_size"
+ android:scaleType="fitCenter"
+ android:src="@drawable/red_shield"/>
+
+ <TextView
+ android:id="@+id/app_name_text"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:textColor="@color/primary_text_material_light"
+ android:textSize="@dimen/text_size_subhead_material"
+ android:paddingLeft="@dimen/harmful_app_icon_name_padding">
+ </TextView>
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/harmful_app_message_padding_left"
+ android:paddingRight="@dimen/harmful_app_message_padding_right"
+ android:paddingBottom="@dimen/harmful_app_message_padding_bottom"
+ android:lineSpacingMultiplier="@dimen/harmful_app_message_line_spacing_modifier"
+ android:textSize="@dimen/text_size_body_1_material"/>
+ </LinearLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index 3b89f0d..1be915e 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -28,18 +28,18 @@
android:layout_marginBottom="4dip"
android:background="@drawable/list_divider_material" />
- <!-- Icon will be inserted here. -->
-
- <!-- The title and summary have some gap between them,
- and this 'group' should be centered vertically. -->
<LinearLayout
android:id="@+id/content"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="?attr/dropdownListPreferredItemHeight"
android:paddingEnd="16dip"
android:duplicateParentState="true" >
- <LinearLayout
+ <!-- Icon will be inserted here. -->
+
+ <!-- The title and summary have some gap between them,
+ and this 'group' should be centered vertically. -->
+ <RelativeLayout
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="wrap_content"
@@ -71,7 +71,7 @@
android:duplicateParentState="true"
android:textAlignment="viewStart" />
- </LinearLayout>
+ </RelativeLayout>
<ImageView
android:id="@+id/submenuarrow"
@@ -81,8 +81,9 @@
android:layout_marginStart="8dp"
android:scaleType="center"
android:visibility="gone" />
- </LinearLayout>
- <!-- Checkbox, and/or radio button will be inserted here. -->
+ <!-- Checkbox, and/or radio button will be inserted here. -->
+
+ </LinearLayout>
</com.android.internal.view.menu.ListMenuItemView>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 1bb3417..f3db598 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Jou organisasie bestuur hierdie toestel en kan netwerkverkeer monitor. Tik vir besonderhede."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Jou toestel sal uitgevee word"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Die administrasieprogram kan nie gebruik word nie. Jou toestel sal nou uitgevee word.\n\nKontak jou organisasie se administrateur as jy vrae het."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Druk is gedeaktiveer deur <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Ek"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tablet-opsies"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV-opsies"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Noodgeval"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Foutverslag"</string>
<string name="global_action_logout" msgid="935179188218826050">"Beëindig sessie"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Skermkiekie"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Neem foutverslag"</string>
<string name="bugreport_message" msgid="398447048750350456">"Dit sal inligting oor die huidige toestand van jou toestel insamel om as \'n e-posboodskap te stuur. Dit sal \'n tydjie neem vandat die foutverslag begin is totdat dit reg is om gestuur te word; wees asseblief geduldig."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiewe verslag"</string>
@@ -262,8 +264,10 @@
<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">"Veiligmodus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Skakel oor na persoonlik"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Skakel oor na werk"</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">"Kontakte"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"in te gaan by jou kontakte"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Gee <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> toegang tot jou kontakte"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Laat die program toe om toegang tot die foonfunksies van die toestel te verkry. Hierdie toestemming laat die program toe om te bepaal wat die foonnommer en toestel-IDs is, of die oproep aan die gang is, en die afgeleë nommer wat deur \'n oproep verbind word."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"roeteer oproepe deur die stelsel"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Laat die program toe om sy oproepe deur die stelsel te stuur om die oproepervaring te verbeter."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"lees foonnommers"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Laat die program toe om toegang tot die toestel se foonnommers te kry."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"verhoed dat tablet slaap"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Vinger is te stadig beweer. Probeer asseblief weer."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nie herken nie"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Vingerafdrukhardeware is nie beskikbaar nie."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Vingerafdruk kan nie gestoor word nie. Verwyder asseblief \'n bestaande vingerafdruk."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vingerafdrukuittelling is bereik. Probeer weer."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Vingerafdrukhandeling is gekanselleer."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Te veel pogings. Probeer later weer."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Te veel pogings. Vingerafdruksensor is gedeaktiveer."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probeer weer."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Maak oop"</string>
<string name="sms" msgid="4560537514610063430">"SMS"</string>
<string name="add_contact" msgid="7867066569670597203">"Voeg by"</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">"Bergingspasie word min"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Sommige stelselfunksies werk moontlik nie"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nie genoeg berging vir die stelsel nie. Maak seker jy het 250 MB spasie beskikbaar en herbegin."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Oop Wi-Fi-netwerk beskikbaar</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Koppel aan oop Wi-Fi-netwerk"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Koppel tans aan oop Wi‑Fi-netwerk"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Aan Wi-Fi-netwerk gekoppel"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Kon nie aan Wi-Fi-netwerk koppel nie"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi sal outomaties aanskakel"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Wanneer jy naby \'n gestoorde hoëgehaltenetwerk is"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Moenie weer aanskakel nie"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi is outomaties aangeskakel"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Jy is naby \'n gestoorde netwerk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Meld aan by Wi-Fi-netwerk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Meld by netwerk aan"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> oor gespesifiseerde limiet."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Agtergronddata is beperk"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Tik om beperking te verwyder."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Groot datagebruik"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Jou datagebruik was die laaste paar dae groter as normaalweg. Tik om die gebruik en instellings te bekyk."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Sekuriteitsertifikaat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Die sertifikaat is geldig."</string>
<string name="issued_to" msgid="454239480274921032">"Uitgereik aan:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (volgende wekker)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Totdat jy Moenie Steur Nie afskakel"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Totdat jy dit afskakel"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Totdat jy Moenie Steur Nie afskakel"</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">"Vou in"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Alle tale"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Allle streke"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Soek"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Skakel werkmodus aan?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Dit sal jou werkprofiel, insluitend programme, agtergrondsinkronisering en verwante kenmerke, aanskakel"</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">"Skakel aan"</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">"Jy het nuwe boodskappe"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Maak SMS-program oop om te bekyk"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Sommige funksies kan beperk wees"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Kon nie die kortpad teruglaai nie omdat die program nie rugsteun en teruglaai steun nie"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Kon nie teruglaai nie omdat programondertekening nie ooreenstem nie"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Kon nie kortpad teruglaai nie"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Kortpad is gedeaktiveer"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> wil <xliff:g id="APP_2">%2$s</xliff:g>-skyfies wys"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Wysig"</string>
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index ee287c3..0dbda7f 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"የቴሌቪዥን አማራጮች"</string>
@@ -263,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"ወደ የግል ቀይር"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"ወደ ሥራ ቀይር"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> እውቂያዎችዎን እንዲደርስ ይፍቀዱለት"</string>
@@ -416,6 +419,10 @@
<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>
@@ -485,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"በጣም ብዙ ሙከራዎች። የጣት አሻራ ዳሳሽ ተሰናክሏል።"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"እንደገና ይሞክሩ።"</string>
@@ -990,6 +1000,12 @@
<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">"ለስርዓቱ የሚሆን በቂ ቦታ የለም። 250 ሜባ ነጻ ቦታ እንዳለዎት ያረጋግጡና ዳግም ያስጀምሩ።"</string>
@@ -1115,6 +1131,8 @@
<item quantity="other">የሚገኙ የWi-Fi አውታረ መረቦችን ክፈት</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"ከክፍት የWi‑Fi አውታረ መረብ ጋር ያገናኙ"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"ከክፍት የWi‑Fi አውታረ መረብ ጋር በመገናኘት ላይ"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"ከWi‑Fi አውታረ መረብ ጋር ተገናኝቷል"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ከWi‑Fi አውታረ መረብ ጋር መገናኘት አልተቻለም"</string>
@@ -1412,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"የደህንነት ዕውቅና ማረጋገጫ"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ይህ የዐዕውቅና ማረጋገጫ ትክክል ነው።"</string>
<string name="issued_to" msgid="454239480274921032">"ለ፡ ተዘጋጀ"</string>
@@ -1688,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"አትረብሽን እስኪያጠፉ ድረስ"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"እስኪያጠፉት ድረስ"</string>
<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>
@@ -1737,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"የሥራ ሁነታ ይጥፋ?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"ይህ የእርስዎን የሥራ መገለጫ መተግበሪያዎችን፣ የበስተጀርባ ስምረት እና ተዛማጅ ባህሪያትን ጨምሮ እንዲበሩ ያደርጋቸዋል"</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>
@@ -1811,7 +1837,12 @@
<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>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"አራግፍ"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"የሆነው ሆኖ አስጀምር"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"ጎጂ መተግበሪያ ይራገፍ?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> የ<xliff:g id="APP_2">%2$s</xliff:g> ቁራጮችን ማሳየት ይፈልጋል"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"አርትዕ"</string>
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index e929bf8..065869c 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -189,6 +189,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"خيارات التلفزيون"</string>
@@ -225,6 +226,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"لقطة شاشة"</string>
<string name="bugreport_title" msgid="2667494803742548533">"إعداد تقرير بالأخطاء"</string>
<string name="bugreport_message" msgid="398447048750350456">"سيجمع هذا معلومات حول حالة جهازك الحالي لإرسالها كرسالة إلكترونية، ولكنه سيستغرق وقتًا قليلاً من بدء عرض تقرير بالأخطاء. وحتى يكون جاهزًا للإرسال، يُرجى الانتظار."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"تقرير تفاعلي"</string>
@@ -274,8 +276,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"التبديل إلى الشخصي"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"التبديل إلى العمل"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"السماح لتطبيق <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> بالوصول إلى جهات الاتصال"</string>
@@ -427,6 +431,10 @@
<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>
@@ -496,10 +504,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"تم إجراء عدد كبير جدًا من المحاولات. لذا تم تعطيل مستشعر بصمات الإصبع."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"أعد المحاولة."</string>
@@ -1069,6 +1080,12 @@
<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>
@@ -1202,6 +1219,8 @@
<item quantity="one">تتوفر شبكة Wi-Fi واحدة مفتوحة</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"الاتصال بشبكة Wi-Fi المفتوحة"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"جارٍ الاتصال بشبكة Wi-Fi المفتوحة"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"تم الاتصال بشبكة Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"تعذَّر الاتصال بشبكة Wi‑Fi"</string>
@@ -1211,6 +1230,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"تم تفعيل شبكة Wi-Fi تلقائيًا."</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"أنت قريب من شبكة محفوظة: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>."</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"تسجيل الدخول إلى شبكة Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"تسجيل الدخول إلى الشبكة"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1501,6 +1522,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"شهادة الأمان"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"هذه الشهادة صالحة."</string>
<string name="issued_to" msgid="454239480274921032">"إصدار لـ:"</string>
@@ -1817,7 +1840,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"حتى يتم تعطيل \"عدم الإزعاج\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"لحين الإيقاف"</string>
<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>
@@ -1870,9 +1893,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"هل تريد تشغيل وضع العمل؟"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"سيؤدي هذا إلى تشغيل الملف الشخصي للعمل، بما في ذلك التطبيقات ومزامنة الخلفية والميزات ذات الصلة"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"ربما تكون بعض الوظائف مُقيّدة."</string>
@@ -1947,6 +1976,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"يريد تطبيق <xliff:g id="APP_0">%1$s</xliff:g> عرض شرائح تطبيق <xliff:g id="APP_2">%2$s</xliff:g>."</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"تعديل"</string>
</resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 8069d6c..5255a12 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Təşkilat bu cihazı idarə edir və şəbəkənin ötürülməsinə nəzarət edə bilər. Detallar üçün klikləyin."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Cihazınız təmizlənəcəkdir"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Bu admin tətbiqini istifadə etmək mümkün deyil. Cihaz indi təmizlənəcək.\n\nSualınız varsa, təşkilatın admini ilə əlaqə saxlayın."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Çap <xliff:g id="OWNER_APP">%s</xliff:g> tərəfindən deaktiv edildi."</string>
<string name="me" msgid="6545696007631404292">"Mən"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Planşet seçimləri"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV seçimləri"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Təcili"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Baq hesabatı"</string>
<string name="global_action_logout" msgid="935179188218826050">"Sessiyanı sonlandırın"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Skrinşot"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Baqı xəbər verin"</string>
<string name="bugreport_message" msgid="398447048750350456">"Bu, sizin hazırkı cihaz durumu haqqında məlumat toplayacaq ki, elektron məktub şəklində göndərsin. Baq raportuna başlamaq üçün bir az vaxt lazım ola bilər, bir az səbr edin."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"İnteraktiv hesabat"</string>
@@ -262,8 +264,8 @@
<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">"Təhlükəsiz rejim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistemi"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Şəxsi profilə keçirin"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"İş profilinə keçirin"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Şəxsi profilə keçin"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"İş profilinə keçin"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktlar"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"kontaktlarınıza daxil olun"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> tətbiqinə kontaktlara daxil olmaq icazəsi verin"</string>
@@ -415,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Tətbiqə cihazın telefon funksiyalarına giriş icazəsi verir. Belə icazəli tətbiq bu telefonun nömrəsini və cihaz İD\'ni, zəngin aktiv olub-olmadığını və zəng edilən nömrəni müəyyən edə bilər."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"zəngləri sistem üzərindən yönləndirin"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Tətbiqə, zəng təcrübəsini yaxşılaşdırmaq üçün, zəngləri sistem üzərindən yönləndirməyə icazə verilir."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"telefon nömrələrini oxuyun"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Tətbiqə cihazın telefon nömrələrinə daxil olmağa icazə verir."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"planşetin yuxu rejiminin qarşısını almaq"</string>
@@ -484,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Barmağınızı çox yavaş hərəkət etdirdiniz. Lütfən, yenidən cəhd edin."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Tanınmır"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Barmaq izi üçün avadanlıq yoxdur."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Barmaq izi saxlana bilməz. Lütfən, mövcud barmaq izini silin."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmaq izinin vaxtı başa çatdı. Yenidən cəhd edin."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Barmaq izi əməliyyatı ləğv edildi."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Barmaq izi əməliyyatı istifadəçi tərəfindən ləğv edildi."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Cəhdlər çox oldu. Sonraya saxlayın."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Həddindən çox cəhd. Barmaq izi sensoru deaktiv edilib."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Yenidən cəhd edin."</string>
@@ -989,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Açın"</string>
<string name="sms" msgid="4560537514610063430">"Mesaj"</string>
<string name="add_contact" msgid="7867066569670597203">"Əlavə edin"</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">"Yaddaş yeri bitir"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Bəzi sistem funksiyaları işləməyə bilər"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Sistem üçün yetərincə yaddaş ehtiyatı yoxdur. 250 MB yaddaş ehtiyatının olmasına əmin olun və yenidən başladın."</string>
@@ -1114,6 +1128,8 @@
<item quantity="one">Əlçatan açıq Wi-Fi şəbəkəsi</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Açıq Wi‑Fi şəbəkəsinə qoşulun"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Açıq Wi‑Fi şəbəkəsinə qoşulur"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi şəbəkəsinə qoşuldu"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi şəbəkəsinə qoşulmaq mümkün deyil"</string>
@@ -1123,6 +1139,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi avtomatik olaraq aktiv ediləcək"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Yadda saxlanmış yüksək keyfiyyətli şəbəkələr yaxınlıqda olduqda"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Yenidən aktiv etməyin"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi avtomatik aktiv edildi"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Yadda saxlanmış şəbəkəyə yaxınsınız: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi şəbəkəsinə daxil ol"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Şəbəkəyə daxil olun"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1427,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> müəyyən edilmiş limit aşır."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Arxaplan datası məhdudlaşdırıldı"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Məhdudiyyəti aradan qaldırmaq üçün tıklayın."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Geniş data istifadəsi"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Son bir neçə gün ərzində olan data istifadəniz normadan çoxdur. İstifadəyə və ayarlara baxmaq üçün klikləyin."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Təhlükəsizlik sertifikatı"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Bu sertifikat etibarlıdır."</string>
<string name="issued_to" msgid="454239480274921032">"Verilib:"</string>
@@ -1685,7 +1705,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Saat <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> qədər"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> radəsinə qədər (növbəti siqnal)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"\"Narahat etməyin\" seçiminini deaktiv edənə kimi"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Deaktiv edənə qədər"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\"Narahat etməyin\" seçiminini deaktiv edənə kimi"</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">"Dağıt"</string>
@@ -1734,9 +1754,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Bütün dillər"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Bütün bölgələr"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Axtarın"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"İş rejimi aktiv edilsin?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Bununla tətbiq, arax fon sinxronizasiyası və əlaqəli funksiyalar daxil olmaqla iş profili aktiv ediləcək"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"İş profili aktiv edilsin?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"İş tətbiqləri, bildirişləri, data və digər iş profili funksiyaları aktiv ediləcək"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivləşdirin"</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">"Yeni mesajlarınız var"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Baxmaq üçün SMS tətbiqini açın"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Bir neçə funksionallıq məhdudlaşdırıla bilər"</string>
@@ -1807,6 +1831,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Qısayolu bərpa etmək mümkün olmadı, çünki tətbiq yedəkləməni və bərpa etməyi dəstəkləmir"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Tətbiqin imza uyğunsuzluğu səbəbilə qısayolu bərpa etmək mümkün olmadı"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Qısayolu bərpa etmək mümkün olmadı"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Qısayol deaktiv edildi"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> <xliff:g id="APP_2">%2$s</xliff:g> tətbiqindən bölmələr göstərmək istəyir"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Redaktə edin"</string>
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index bb5a404..8cc35d4 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -183,6 +183,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organizacija upravlja ovim uređajem i može da nadgleda mrežni saobraćaj. Dodirnite za detalje."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Uređaj će biti obrisan"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Ne možete da koristite ovu aplikaciju za administratore. Uređaj će sada biti obrisan.\n\nAko imate pitanja, kontaktirajte administratora organizacije."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcije za tablet"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opcije za TV"</string>
@@ -219,6 +220,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Hitni poziv"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Izveštaj o grešci"</string>
<string name="global_action_logout" msgid="935179188218826050">"Završi sesiju"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Snimak ekrana"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Napravi izveštaj o grešci"</string>
<string name="bugreport_message" msgid="398447048750350456">"Ovim će se prikupiti informacije o trenutnom stanju uređaja kako bi bile poslate u poruci e-pošte. Od započinjanja izveštaja o grešci do trenutka za njegovo slanje proći će neko vreme; budite strpljivi."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv. izveštaj"</string>
@@ -265,8 +267,10 @@
<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">"Bezbedni režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Pređi na Lični profil"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Pređi na profil za Work"</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">"Kontakti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupi kontaktima"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Dozvolite da <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> pristupa kontaktima"</string>
@@ -418,6 +422,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Dozvoljava aplikaciji da pristupa funkcijama telefona na uređaju. Ova dozvola omogućava aplikaciji da utvrdi broj telefona i ID-ove uređaja, zatim da li je poziv aktivan, kao i broj daljinskog uređaja sa kojim je uspostavljen poziv."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"preusmeravanje poziva preko sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Dozvoljava aplikaciji da preusmerava pozive preko sistema da bi poboljšala doživljaj pozivanja."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"čitanje brojeva telefona"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Dozvoljava aplikaciji da pristupa brojevima telefona na uređaju."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"sprečavanje prelaska tableta u stanje spavanja"</string>
@@ -487,10 +495,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Previše sporo ste pomerili prst. Probajte ponovo."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nije prepoznat"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otiske prstiju nije dostupan."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Nije moguće sačuvati otisak prsta. Uklonite neki od postojećih otisaka prstiju."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Probajte ponovo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Probajte ponovo kasnije."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Previše pokušaja. Senzor za otisak prsta je onemogućen."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probajte ponovo."</string>
@@ -1009,6 +1020,12 @@
<string name="browse" msgid="1245903488306147205">"Otvori"</string>
<string name="sms" msgid="4560537514610063430">"Pošalji SMS"</string>
<string name="add_contact" msgid="7867066569670597203">"Dodaj"</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">"Memorijski prostor je na izmaku"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Neke sistemske funkcije možda ne funkcionišu"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nema dovoljno memorijskog prostora za sistem. Uverite se da imate 250 MB slobodnog prostora i ponovo pokrenite."</string>
@@ -1136,6 +1153,8 @@
<item quantity="other">Otvorene Wi-Fi mreže su dostupne</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Povežite se sa otvorenom Wi‑Fi mrežom"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Povezujete se sa otvorenom Wi‑Fi mrežom"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Povezali ste se sa Wi‑Fi mrežom"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Povezivanje sa Wi‑Fi mrežom nije uspelo"</string>
@@ -1145,6 +1164,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi će se automatski uključiti"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kada ste u blizini sačuvane mreže visokog kvaliteta"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ne uključuj ponovo"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi je automatski uključen"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"U blizini ste sačuvane mreže: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijavljivanje na Wi-Fi mrežu"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijavite se na mrežu"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1432,6 +1453,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> preko navedenog ograničenja."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Pozadinski podaci su ograničeni"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Dodirnite za uklanjanje ograničenja."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Velika potrošnja podataka"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Potrošnja podataka tokom poslednjih par dana je veća nego obično. Dodirnite da biste pregledali potrošnju i podešavanja."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Bezbednosni sertifikat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Ovaj sertifikat je važeći."</string>
<string name="issued_to" msgid="454239480274921032">"Izdato za:"</string>
@@ -1718,7 +1741,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (sledeći alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Dok ne isključite režim Ne uznemiravaj"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Dok ne isključite"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dok ne isključite režim Ne uznemiravaj"</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">"Skupi"</string>
@@ -1768,9 +1791,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Svi jezici"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Svi regioni"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pretraži"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Uključiti režim za Work?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Ovo će uključiti profil za Work, uključujući aplikacije, sinhronizaciju u pozadini i srodne funkcije."</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">"Uključi"</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">"Imate nove poruke"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite aplikaciju za SMS da biste pregledali"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Neke funkcije su možda ograničene"</string>
@@ -1842,6 +1871,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Vraćanje prečice nije uspelo jer aplikacija ne podržava pravljenje rezervne kopije i vraćanje"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Vraćanje prečice nije uspelo jer se potpisi aplikacija ne podudaraju"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Vraćanje prečice nije uspelo"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Prečica je onemogućena"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Aplikacija <xliff:g id="APP_0">%1$s</xliff:g> želi da prikazuje isečke iz aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Izmeni"</string>
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index b5e28b3..64ee9d7 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -185,6 +185,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Параметры ТБ"</string>
@@ -221,6 +222,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"SOS-выклік"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Справаздача пра памылкі"</string>
<string name="global_action_logout" msgid="935179188218826050">"Скончыць сеанс"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Здымак экрана"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Справаздача пра памылку"</string>
<string name="bugreport_message" msgid="398447048750350456">"Будзе збiрацца iнфармацыя пра бягучы стан прылады, якая будзе адпраўляцца на электронную пошту. Стварэнне справаздачы пра памылкi зойме некаторы час."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Інтэрактыўная справаздача"</string>
@@ -268,8 +270,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"Пераключыцца на асабісты"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Пераключыцца на працоўны"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Дазволіць <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> атрымліваць доступ да вашых кантактаў"</string>
@@ -421,6 +425,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Дазваляе прыкладанням атрымлiваць доступ да функцый тэлефона на прыладзе. Дзякуючы гэтаму дазволу прыкладанне можа вызначаць iдэнтыфiкатары нумару тэлефона i прылады, незалежна ад таго, цi актыўны выклiк, i аддалены нумар, на якi робiцца выклiк."</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>
@@ -490,10 +498,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Занадта шмат спроб. Сканер адбіткаў пальцаў адключаны."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Паспрабуйце яшчэ раз."</string>
@@ -1029,6 +1040,12 @@
<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">"Не хапае сховішча для сістэмы. Пераканайцеся, што ў вас ёсць 250 МБ свабоднага месца, і перазапусціце."</string>
@@ -1158,6 +1175,8 @@
<item quantity="other">адкрытай сеткі Wi-Fi даступна</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Падключыцеся да адкрытай сеткі Wi-Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ідзе падключэнне да адкрытай сеткі Wi‑Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Выканана падключэнне да адкрытай сеткі Wi‑Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не атрымалася падключыцца да адкрытай сеткі Wi‑Fi"</string>
@@ -1167,6 +1186,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi уключыўся аўтаматычна"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Вы знаходзіцеся побач з захаванай сеткай: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Уваход у сетку Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Увайдзіце ў сетку"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1455,6 +1476,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Аб\'ём <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="ssl_certificate" msgid="6510040486049237639">"Сертыфікат бяспекі"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Гэты сертыфікат сапраўдны."</string>
<string name="issued_to" msgid="454239480274921032">"Каму выдадзена:"</string>
@@ -1751,7 +1774,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Пакуль вы не выключыце рэжым \"Не турбаваць\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Пакуль не выключыце"</string>
<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>
@@ -1802,9 +1825,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Уключыць працоўны рэжым?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Гэта прывядзе да ўключэння вашага працоўнага профілю, у тым ліку праграм, фонавай сінхранізацыі і звязаных з імі функцый"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Частка функц. можа быць абмеж."</string>
@@ -1877,6 +1906,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Праграма <xliff:g id="APP_0">%1$s</xliff:g> запытвае дазвол на паказ зрэзаў праграмы <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Рэдагаваць"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index e069c4e..0904e77 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -181,6 +181,7 @@
<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="printing_disabled_by" msgid="8936832919072486965">"Отпечатването е деактивиранo от <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Аз"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Опции за таблета"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Опции за телевизора"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Екранна снимка"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Сигнал за програмна грешка"</string>
<string name="bugreport_message" msgid="398447048750350456">"По този начин ще се събере информация за текущото състояние на устройството ви, която да се изпрати като имейл съобщение. След стартирането на процеса ще мине известно време, докато сигналът за програмна грешка бъде готов за подаване. Моля, имайте търпение."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивен сигнал"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"Превключване към личния потребителски профил"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Превключване към служебния пoтребителски профил"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Разрешете на <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> да осъществява достъп до контактите ви"</string>
@@ -415,6 +419,10 @@
<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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Твърде много опити. Сензорът за отпечатъци е деактивиран."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Опитайте отново."</string>
@@ -989,6 +1000,12 @@
<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">"За системата няма достатъчно място в хранилището. Уверете се, че имате свободни 250 МБ, и рестартирайте."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Има достъпна отворена Wi-Fi мрежа</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Свързване с отворена Wi‑Fi мрежа"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Установява се връзка с отворена Wi‑Fi мрежа"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Установихте връзка с Wi-Fi мрежата"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не можа да се установи връзка с Wi‑Fi мрежата"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi-Fi се включи автоматично"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Намирате се в района на запазена мрежа: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Влизане в Wi-Fi мрежа"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Вход в мрежата"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"Сертификат за сигурност"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Този сертификат е валиден."</string>
<string name="issued_to" msgid="454239480274921032">"Издаден на:"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Докато не изключите „Не безпокойте“"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"До изключване"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Включване на работния режим?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Това действие ще включи служебния ви потребителски профил, включително приложенията, синхронизирането на заден план и свързаните функции"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Някои функции може да са огранич."</string>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> иска да показва части от <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Редактиране"</string>
</resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 9b1f6c3..ecadbbf 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"টিভি বিকল্পগুলি"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"স্ক্রিনশট নিন"</string>
<string name="bugreport_title" msgid="2667494803742548533">"ত্রুটির অভিযোগ করুন"</string>
<string name="bugreport_message" msgid="398447048750350456">"এটি একটি ই-মেল মেসেজ পাঠানোর জন্য আপনার ডিভাইসের বর্তমান অবস্থা সম্পর্কে তথ্য সংগ্রহ করবে৷ ত্রুটির প্রতিবেদন শুরুর সময় থেকে এটি পাঠানোর জন্য প্রস্তুত হতে কিছুটা সময় নেবে; অনুগ্রহ করে ধৈর্য রাখুন৷"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ইন্টারেক্টিভ প্রতিবেদন"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"ব্যক্তিগততে পাল্টান"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"কর্মস্থানে পাল্টান"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> কে আপনার পরিচিতিগুলি অ্যাক্সেস করতে দিন"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"অ্যাপ্লিকেশানটিকে ডিভাইসের ফোন বৈশিষ্ট্যগুলিকে অ্যাক্সেস করার অনুমতি দেয়৷ এই অনুমতিটি অ্যাপ্লিকেশানটিকে একটি কল সক্রিয় থাকা অবস্থায় এবং দূরবর্তী নম্বর একটি কল দ্বারা সংযুক্ত থাকাকালীনও ফোন নম্বর এবং ডিভাইসের IDগুলি নির্ধারণ করার অনুমতি দেয়৷"</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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"বহুবার চেষ্টা করেছেন। আঙ্গুলের ছাপ নেওয়ার সেন্সর অক্ষম করা হয়েছে।"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"আবার চেষ্টা করুন৷"</string>
@@ -989,6 +1000,12 @@
<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>
@@ -1114,6 +1131,8 @@
<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>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"ওয়াই-ফাই নিজে থেকে চালু করা হয়েছে"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"আপনি একটি সেভ করা নেটওয়ার্কের কাছেই আছেন: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<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) -->
@@ -1410,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"নির্দিষ্ট সীমার থেকে <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="ssl_certificate" msgid="6510040486049237639">"নিরাপত্তার সার্টিফিকেট"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"শংসাপত্রটি বৈধ৷"</string>
<string name="issued_to" msgid="454239480274921032">"এর জন্য ইস্যু করা হয়েছে:"</string>
@@ -1686,7 +1709,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"যতক্ষণ না পর্যন্ত আপনি \'বিরক্ত করবেন না\' বন্ধ করছেন"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"যতক্ষণ না আপনি বন্ধ করছেন"</string>
<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>
@@ -1735,9 +1758,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"কর্মস্থলের মোড চালু করবেন?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"এটি অ্যাপ, পটভূমি সিঙ্ক, এবং সম্পর্কিত বৈশিষ্ট্যগুলি সহ কর্মস্থলের প্রোফাইলটিকে চালু করবে"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"কিছু ক্রিয়াকলাপ সীমিত হতে পারে"</string>
@@ -1808,6 +1837,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> অ্যাপটি <xliff:g id="APP_2">%2$s</xliff:g> এর অংশ দেখাতে চায়"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"এডিট করুন"</string>
</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index c79566b..f143d4e 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -183,6 +183,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Vaša organizacija upravlja ovim uređajem i može pratiti mrežni saobraćaj. Dodirnite za detalje."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Uređaj će biti izbrisan"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Nije moguće koristiti aplikaciju administratora. Potpuno će se izbrisati podaci na vašem uređaju.\n\nAko imate pitanja, obratite se administratoru vaše organizacije."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcije tableta"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opcije za TV"</string>
@@ -219,6 +220,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Hitno"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Izvještaj o greškama"</string>
<string name="global_action_logout" msgid="935179188218826050">"Završi sesiju"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Snimak ekrana"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Kreirajte izvještaj o greškama"</string>
<string name="bugreport_message" msgid="398447048750350456">"Ovim će se prikupljati informacije o trenutnom stanju uređaja, koji će biti poslani kao e-poruka. Može malo potrajati dok se izvještaj o greškama ne kreira i bude spreman za slanje. Budite strpljivi."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktivni izvještaj"</string>
@@ -265,8 +267,10 @@
<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">"Siguran način rada"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Prebacite se na lični"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Prebacite se na radni"</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">"Kontakti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupa vašim kontaktima"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Dozvolite aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> pristup vašim kontaktima"</string>
@@ -418,6 +422,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Omogućava aplikaciji pristup telefonskim funkcijama uređaja. Ovo odobrenje omogućava aplikaciji određivanje telefonskog i identifikacionog broja uređaja, bez obzira da li je poziv aktivan i da li je uspostavljena veza sa pozivanim brojem."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"usmjeravanje poziva preko sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Dopušta aplikaciji da pozive usmjeri preko sistema radi poboljšanja iskustva pozivanja."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"čitanje telefonskih brojeva"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Dozvoljava aplikaciji pristup telefonskim brojevima uređaja."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"sprečavanje tableta da uđe u režim mirovanja"</string>
@@ -487,10 +495,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Prst je uklonjen presporo. Pokušajte ponovo."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nije prepoznat"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otisak prsta nije dostupan."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisak prsta se ne može pohraniti. Uklonite postojeći otisak prsta."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Pokušajte ponovo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Previše pokušaja. Senzor za otisak prsta je onemogućen."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Pokušajte ponovo."</string>
@@ -1009,6 +1020,12 @@
<string name="browse" msgid="1245903488306147205">"Otvorite"</string>
<string name="sms" msgid="4560537514610063430">"Poruka"</string>
<string name="add_contact" msgid="7867066569670597203">"Dodajte"</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">"Ponestaje prostora za pohranu"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Neke funkcije sistema možda neće raditi"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nema dovoljno prostora za sistem. Obezbijedite 250MB slobodnog prostora i ponovo pokrenite uređaj."</string>
@@ -1138,6 +1155,8 @@
<item quantity="other">Otvorene Wi-Fi mreže su dostupne</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Povežite se na otvorenu Wi‑Fi mrežu"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Povezivanje na otvorenu Wi‑Fi mrežu"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Povezani ste na Wi‑Fi mrežu"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nije se moguće povezati na Wi‑Fi mrežu"</string>
@@ -1147,6 +1166,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi veza će se automatski uključiti"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kada ste u blizini sačuvane mreže visokog kvaliteta"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Nemoj ponovo uključiti"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi veza se automatski uključila"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"U blizini ste sačuvane mreže: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijavljivanje na Wi-Fi mrežu"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijava na mrežu"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1434,6 +1455,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> preko navedenog ograničenja."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Pozadinski podaci su ograničeni"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Dodirnite da biste uklonili ograničenja."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Velik prijenos podataka"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Prijenos podataka tokom prethodnih nekoliko dana je bio veći nego inače. Dodirnite za prikaz potrošnje i postavki."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Sigurnosni certifikat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Ovaj certifikat je važeći."</string>
<string name="issued_to" msgid="454239480274921032">"Primalac:"</string>
@@ -1720,7 +1743,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (sljedeći alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Dok ne isključite opciju Ne ometaj"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Dok ne isključite"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dok ne isključite opciju Ne ometaj"</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">"Skupi"</string>
@@ -1770,9 +1793,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Svi jezici"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Sve regije"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pretraga"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Želite uključiti radni način?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Ovim će se uključiti vaš radni profil, uključujući aplikacije, sinhronizacija u pozadini i povezane funkcije"</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">"Uključi"</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">"Imate nove poruke"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite SMS aplikaciju da biste pregledali poruke"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Neke funkcije mogu biti ograničene"</string>
@@ -1844,6 +1873,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Prečica nije uspješno vraćena jer aplikacija ne podržava izradu sigurnosne kopije i vraćanje"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Prečica nije uspješno vraćena zbog nepodudaranja potpisa aplikacije"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Prečica nije uspješno vraćena"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Prečica je onemogućena"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Aplikacija <xliff:g id="APP_0">%1$s</xliff:g> želi prikazati isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Uredi"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index ea09008..bf91550 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"La teva organització gestiona aquest dispositiu i és possible que supervisi el trànsit de xarxa. Toca per obtenir més informació."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"El contingut del dispositiu s\'esborrarà"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"No es pot utilitzar l\'aplicació d\'administració. S\'esborraran les dades del dispositiu.\n\nSi tens cap dubte, contacta amb l\'administrador de la teva organització."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"<xliff:g id="OWNER_APP">%s</xliff:g> ha desactivat la impressió."</string>
<string name="me" msgid="6545696007631404292">"Mi"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcions de la tauleta"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opcions del televisor"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Emergències"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Informe d\'error"</string>
<string name="global_action_logout" msgid="935179188218826050">"Finalitza la sessió"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Crea informe d\'errors"</string>
<string name="bugreport_message" msgid="398447048750350456">"Es recopilarà informació sobre l\'estat actual del dispositiu i se t\'enviarà per correu electrònic. Passaran uns quants minuts des de l\'inici de l\'informe d\'errors fins al seu enviament, per la qual cosa et recomanem que tinguis paciència."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactiu"</string>
@@ -262,8 +264,10 @@
<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">"Mode segur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Canvia al perfil personal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Canvia al perfil professional"</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">"Contactes"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"accedir als contactes"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Permet que <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> accedeixi als contactes"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permet que l\'aplicació accedeixi a les funcions de telèfon del dispositiu. Aquest permís permet que l\'aplicació determini el número de telèfon i els identificadors del dispositiu, si hi ha una trucada activa i el número remot connectat amb una trucada."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"encaminar trucades a través del sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Permet que l\'aplicació encamini les trucades a través del sistema per millorar-ne l\'experiència."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"llegir els números de telèfon"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Permet que l\'aplicació accedeixi als números de telèfon del dispositiu."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evita que la tauleta entri en mode de repòs"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"El dit s\'ha mogut massa lentament. Torna-ho a provar."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"No s\'ha reconegut"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El maquinari per a empremtes digitals no està disponible."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empremta digital no es pot desar. Suprimeix-ne una."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"S\'ha cancel·lat l\'operació d\'empremta digital."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"S\'han produït massa intents. Torna-ho a provar més tard."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"S\'han fet massa intents. S\'ha desactivat el sensor d\'empremtes digitals."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Torna-ho a provar."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Obre"</string>
<string name="sms" msgid="4560537514610063430">"Missatge"</string>
<string name="add_contact" msgid="7867066569670597203">"Afegeix"</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">"L\'espai d\'emmagatzematge s\'està esgotant"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"És possible que algunes funcions del sistema no funcionin"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"No hi ha prou espai d\'emmagatzematge per al sistema. Comprova que tinguis 250 MB d\'espai lliure i reinicia."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Xarxa Wi-Fi oberta disponible</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Connecta\'t a una xarxa Wi-Fi oberta"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"S\'està connectant a una xarxa Wi-Fi oberta"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"S\'ha connectat a la xarxa Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"No s\'ha pogut connectar a una xarxa Wi-Fi"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"La Wi-Fi s\'activarà automàticament"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Quan siguis a prop d\'una xarxa de qualitat desada"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"No tornis a activar"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"La Wi‑Fi s\'ha activat automàticament"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Ets a prop d\'una xarxa desada: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Inicia la sessió a la xarxa Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Inicia la sessió a la xarxa"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> per sobre del límit especif."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Dades en segon pla restringides"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Toca per suprimir la restricció."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Ús de dades excessiu"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"L\'ús de dades dels últims dies és superior a l\'habitual. Toca per veure\'n l\'ús i la configuració."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificat de seguretat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Aquest certificat és vàlid."</string>
<string name="issued_to" msgid="454239480274921032">"Emès per a:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Fins a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Fins a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (propera alarma)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Fins que desactivis el mode No molestis"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Fins que es desactivi"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Fins que desactivis el mode No molestis"</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">"Replega"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Tots els idiomes"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Totes les regions"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Cerca"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Vols activar el mode de feina?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"S\'activarà el teu perfil professional, incloses les aplicacions, la sincronització en segon pla i les funcions relacionades"</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">"Activa"</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">"Tens missatges nous"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Obre l\'aplicació d\'SMS per veure\'ls"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Algunes funcions es limitaran"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"No s\'ha pogut restaurar la drecera perquè l\'aplicació no permet la còpia de seguretat ni la restauració"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"No s\'ha pogut restaurar la drecera perquè la signatura de l\'aplicació no coincideix"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"No s\'ha pogut restaurar la drecera"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"S\'ha desactivat la drecera"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> vol mostrar porcions de l\'aplicació <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Edita"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 6b5f1c8..32d4294 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -185,6 +185,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Toto zařízení je spravováno vaší organizací, která může sledovat síťový provoz. Podrobnosti zobrazíte klepnutím."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Zařízení bude vymazáno"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Aplikaci pro správu nelze použít. Zařízení nyní bude vymazáno.\n\nV případě dotazů vám pomůže administrátor organizace."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Aplikace <xliff:g id="OWNER_APP">%s</xliff:g> tisk zakazuje."</string>
<string name="me" msgid="6545696007631404292">"Já"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Možnosti tabletu"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Možnosti televize"</string>
@@ -269,8 +270,10 @@
<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">"Nouzový režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Přepnout na osobní profil"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Přepnout na pracovní profil"</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">"Kontakty"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"přístup ke kontaktům"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Povolte aplikaci <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> přístup ke kontaktům"</string>
@@ -422,6 +425,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Umožňuje aplikaci získat přístup k telefonním funkcím zařízení. Toto oprávnění umožňuje aplikaci zjistit telefonní číslo telefonu, identifikační čísla zařízení, zda zrovna probíhá hovor, a vzdálené číslo, ke kterému je hovor připojen."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"směrování volání prostřednictvím systému"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Umožňuje aplikaci směrovat volání prostřednictvím systému za účelem vylepšení funkcí volání."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"přístup k telefonním číslům"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Umožňuje aplikaci přístup k telefonním číslům v zařízení."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"bránění přechodu tabletu do režimu spánku"</string>
@@ -491,10 +498,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Pohyb prstem byl příliš pomalý. Zkuste to znovu."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nerozpoznáno"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Není k dispozici hardware ke snímání otisků prstů."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisk prstu nelze uložit. Odstraňte existující otisk prstu."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit sejmutí otisku prstu vypršel. Zkuste to znovu."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operace otisku prstu byla zrušena."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Příliš mnoho pokusů. Zkuste to později."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Příliš mnoho pokusů. Snímač otisků prstů byl deaktivován."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Zkuste to znovu."</string>
@@ -1030,6 +1040,12 @@
<string name="browse" msgid="1245903488306147205">"Otevřít"</string>
<string name="sms" msgid="4560537514610063430">"Zpráva"</string>
<string name="add_contact" msgid="7867066569670597203">"Přidat"</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">"V úložišti je málo místa"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Některé systémové funkce nemusí fungovat"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Pro systém není dostatek místa v úložišti. Uvolněte alespoň 250 MB místa a restartujte zařízení."</string>
@@ -1159,6 +1175,8 @@
<item quantity="one">K dispozici je veřejná síť Wi-Fi</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Připojení k otevřené síti Wi-Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Připojování k otevřené síti Wi-Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Připojeno k síti Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Připojení k síti Wi-Fi se nezdařilo"</string>
@@ -1458,6 +1476,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> nad stanoveným limitem."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Data na pozadí jsou omezena"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Klepnutím odstraníte omezení."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Velké využití dat"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Za posledních několik dní máte větší využití dat než obvykle. Klepnutím zobrazíte využití a nastavení."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certifikát zabezpečení"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Tento certifikát je platný."</string>
<string name="issued_to" msgid="454239480274921032">"Vydáno pro:"</string>
@@ -1754,7 +1774,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (příští budík)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Dokud nevypnete režim Nerušit"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Dokud tuto funkci nevypnete"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokud nevypnete režim Nerušit"</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">"Sbalit"</string>
@@ -1805,9 +1825,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Všechny jazyky"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Všechny oblasti"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Vyhledávání"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Zapnout pracovní režim?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Zapne se pracovní profil, včetně aplikací, synchronizace na pozadí a souvisejících funkcí"</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">"Zapnout"</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">"Máte nové zprávy"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Zobrazíte je v aplikaci pro SMS"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Funkce mohou být omezeny"</string>
@@ -1881,7 +1907,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Zkratku nelze obnovit, protože se neshoduje podpis aplikace"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Zkratku nelze obnovit"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Zkratka nefunguje"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Odinstalovat"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Přesto spustit"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Odinstalovat škodlivou aplikaci?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Aplikace <xliff:g id="APP_0">%1$s</xliff:g> chce zobrazovat ukázky z aplikace <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Upravit"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 90b7e5e..df0f578 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Din organisation administrerer denne enhed og kan overvåge netværkstrafik. Tryk for at se oplysninger."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Enheden slettes"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Administrationsappen kan ikke bruges. Enheden vil nu blive ryddet. \n\nKontakt din organisations administrator, hvis du har nogen spørgsmål."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Udskrivning er deaktiveret af <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Mig"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Valgmuligheder for tabletcomputeren"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Tv-indstillinger"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Nødopkald"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Fejlrapport"</string>
<string name="global_action_logout" msgid="935179188218826050">"Afslut sessionen"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Lav fejlrapport"</string>
<string name="bugreport_message" msgid="398447048750350456">"Der indsamles oplysninger om din enheds aktuelle status, der efterfølgende sendes i en e-mail. Der går lidt tid, fra fejlrapporten påbegyndes, til den er klar til at blive sendt. Tak for tålmodigheden."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv rapport"</string>
@@ -262,8 +264,10 @@
<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">"Sikker tilstand"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Skift til Tilpasset"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Skift til arbejde"</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">"Kontaktpersoner"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"have adgang til dine kontaktpersoner"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Giv <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> adgang til dine kontaktpersoner"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Tillader, at appen kan få adgang til telefonfunktionerne på enheden. Med denne tilladelse kan appen fastslå telefonnummeret og enheds-id\'erne, hvorvidt et opkald er aktivt samt det eksterne nummer, der oprettes forbindelse til via et opkald."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"dirigere opkald gennem systemet"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Tillader appen at dirigere sine opkald gennem systemet for at forbedre opkaldsoplevelsen."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"læse telefonnumre"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Tillader, at appen får adgang til telefonnumrene på denne enhed."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"afholde tabletcomputeren fra at gå i dvale"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Du bevægede fingeren for langsomt. Prøv igen."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ikke genkendt"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardwaren til fingeraftryk er ikke tilgængelig."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeraftrykket kan ikke gemmes. Fjern et eksisterende fingeraftryk."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Registrering af fingeraftryk fik timeout. Prøv igen."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeraftrykshandlingen blev annulleret."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Du har prøvet for mange gange. Prøv igen senere."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Du har brugt for mange forsøg. Fingeraftrykslæseren er deaktiveret."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Prøv igen."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Åbn"</string>
<string name="sms" msgid="4560537514610063430">"Besked"</string>
<string name="add_contact" msgid="7867066569670597203">"Tilføj"</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">"Der er snart ikke mere lagerplads"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Nogle systemfunktioner virker måske ikke"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Der er ikke nok ledig lagerplads til systemet. Sørg for, at du har 250 MB ledig plads, og genstart."</string>
@@ -1114,6 +1131,8 @@
<item quantity="other">Åbne Wi-Fi-netværk er tilgængelige</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Opret forbindelse til et åbent Wi-Fi-netværk"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Opretter forbindelse til et åbent Wi‑Fi-netværk"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Forbundet til Wi-Fi-netværket"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Der kan ikke oprettes forbindelse til Wi-Fi-netværket"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi aktiveres automatisk"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Når du er i nærheden af et gemt netværk af høj kvalitet"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Aktivér ikke igen"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi blev automatisk aktiveret"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Du er i nærheden af et gemt netværk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Log ind på Wi-Fi-netværk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Log ind på netværk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> over den angivne grænse."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Baggrundsdata er begrænsede"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Tryk for at fjerne begrænsning."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Stort dataforbrug"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Dit dataforbrug i løbet af de seneste 7 dage er større end normalt. Tryk for at se forbrug og indstillinger."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Sikkerhedscertifikat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Dette certifikat er gyldigt."</string>
<string name="issued_to" msgid="454239480274921032">"Udstedt til:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Indtil <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Indtil <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (næste alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Indtil du deaktiverer \"Forstyr ikke\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Indtil du deaktiverer"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Indtil du slår \"Forstyr ikke\" fra"</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">"Skjul"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Alle sprog"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Alle områder"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Søg"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Aktivér arbejdstilstand?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Dette vil aktivere din arbejdsprofil, bl.a. apps, baggrundssynkronisering og relaterede funktioner"</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">"Slå til"</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">"Du har nye beskeder"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Åbn sms-appen for at se beskeden"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Nogle funktioner er begrænsede"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Genvejen kunne ikke gendannes, da appen ikke understøtter backup og gendannelse"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Genvejen kunne ikke gendannes på grund af uoverensstemmelse i appsignatur"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Genvejen kunne ikke gendannes"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Genvejen er deaktiveret"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> anmoder om tilladelse til at vise eksempler fra <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Rediger"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b94cc90..f2a96a9 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Deine Organisation verwaltet dieses Gerät und überprüft unter Umständen den Netzwerkverkehr. Tippe hier, um weitere Informationen zu erhalten."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Die Daten auf deinem Gerät werden gelöscht."</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Die Admin-App kann nicht verwendet werden. Die Daten auf deinem Gerät werden nun gelöscht.\n\nBitte wende dich an den Administrator deiner Organisation."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Drucken wurde von <xliff:g id="OWNER_APP">%s</xliff:g> deaktiviert."</string>
<string name="me" msgid="6545696007631404292">"Eigene"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tablet-Optionen"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV-Optionen"</string>
@@ -217,8 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Notfall"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Fehlerbericht"</string>
<string name="global_action_logout" msgid="935179188218826050">"Sitzung beenden"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Fehlerbericht abrufen"</string>
<string name="bugreport_message" msgid="398447048750350456">"Bei diesem Fehlerbericht werden Daten zum aktuellen Status deines Geräts erfasst und als E-Mail versandt. Vom Start des Berichts bis zu seinem Versand kann es eine Weile dauern. Bitte habe etwas Geduld."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiver Bericht"</string>
@@ -264,8 +264,10 @@
<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">"Abgesicherter Modus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Zu \"Privat\" wechseln"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Zu \"Arbeit\" wechseln"</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">"Kontakte"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"auf deine Kontakte zugreifen"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> Zugriff auf deine Kontakte erlauben"</string>
@@ -417,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ermöglicht der App, auf die Telefonfunktionen des Geräts zuzugreifen. Die Berechtigung erlaubt der App, die Telefonnummer und Geräte-IDs zu erfassen, festzustellen, ob gerade ein Gespräch geführt wird, und die Rufnummer verbundener Anrufer zu lesen."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"Anrufe über das System durchführen"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Ermöglicht der App, Anrufe über das System durchzuführen, um die Anrufqualität zu verbessern."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"Telefonnummern vorlesen"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Ermöglicht der App, auf die Telefonnummern auf dem Gerät zuzugreifen."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Ruhezustand des Tablets deaktivieren"</string>
@@ -486,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger zu langsam bewegt. Versuche es erneut."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nicht erkannt"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerabdruckhardware nicht verfügbar"</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerabdruck kann nicht gespeichert werden. Entferne einen vorhandenen Fingerabdruck."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Zeitüberschreitung für Fingerabdruck. Versuche es erneut."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerabdruckvorgang abgebrochen"</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zu viele Versuche. Versuche es später erneut."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Zu viele Versuche. Der Fingerabdrucksensor wurde deaktiviert."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Bitte versuche es erneut."</string>
@@ -991,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Öffnen"</string>
<string name="sms" msgid="4560537514610063430">"SMS"</string>
<string name="add_contact" msgid="7867066569670597203">"Hinzufügen"</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">"Der Speicherplatz wird knapp"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Einige Systemfunktionen funktionieren möglicherweise nicht."</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Der Speicherplatz reicht nicht für das System aus. Stelle sicher, dass 250 MB freier Speicherplatz vorhanden sind, und starte das Gerät dann neu."</string>
@@ -1116,6 +1131,8 @@
<item quantity="one">Verfügbares WLAN öffnen</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Mit offenem WLAN verbinden"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Verbindung mit offenem WLAN wird hergestellt"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Mit WLAN verbunden"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"WLAN-Verbindung konnte nicht hergestellt werden"</string>
@@ -1125,10 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"WLAN wird automatisch aktiviert"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Wenn du in der Nähe eines sicheren gespeicherten Netzwerks bist"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Nicht wieder aktivieren"</string>
- <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
- <skip />
- <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
- <skip />
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"WLAN automatisch aktiviert"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Du bist in der Nähe eines gespeicherten Netzwerks: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"In WLAN anmelden"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Im Netzwerk anmelden"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1415,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> über dem vorgegebenen Limit"</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Hintergrunddaten beschränkt"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Zum Entfernen der Beschränkung tippen."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Hohe Datennutzung"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Du hast in den letzten Tagen mehr Daten verbraucht als üblich. Tippe, um deine Datennutzung und deine Einstellungen anzuzeigen."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Sicherheitszertifikat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Dies ist ein gültiges Zertifikat."</string>
<string name="issued_to" msgid="454239480274921032">"Ausgestellt für:"</string>
@@ -1691,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Bis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Bis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nächste Weckzeit)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Bis zur Deaktivierung von \"Nicht stören\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Bis zur Deaktivierung"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Bis zur Deaktivierung von \"Nicht stören\""</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">"Minimieren"</string>
@@ -1740,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Alle Sprachen"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Alle Regionen"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Suche"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Arbeitsmodus aktivieren?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Dadurch wird dein Arbeitsprofil aktiviert, darunter Apps, Synchronisierung im Hintergrund und verknüpfte Funktionen"</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">"Aktivieren"</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">"Du hast neue Nachrichten"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Zum Ansehen SMS-App öffnen"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Einige Funktionen sind evtl. eingeschränkt"</string>
@@ -1814,10 +1837,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Verknüpfung konnte nicht wiederhergestellt werden, weil die App-Signatur nicht übereinstimmt"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Verknüpfung konnte nicht wiederhergestellt werden"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Verknüpfung ist deaktiviert"</string>
- <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> möchte Teile von <xliff:g id="APP_2">%2$s</xliff:g> anzeigen"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Bearbeiten"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 9aa3eb5..e0058c6 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -181,6 +181,7 @@
<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="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">"Επιλογές tablet"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Επιλογές τηλεόρασης"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Στιγμιότυπο οθόνης"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Λήψη αναφοράς σφάλματος"</string>
<string name="bugreport_message" msgid="398447048750350456">"Θα συλλέξει πληροφορίες σχετικά με την τρέχουσα κατάσταση της συσκευής σας και θα τις στείλει μέσω μηνύματος ηλεκτρονικού ταχυδρομείου. Απαιτείται λίγος χρόνος για τη σύνταξη της αναφοράς σφάλματος και την αποστολή της. Κάντε λίγη υπομονή."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Διαδραστική αναφορά"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"Μετάβαση σε προσωπικό προφίλ"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Μετάβαση σε προφίλ εργασίας"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στις επαφές σας"</string>
@@ -415,6 +419,10 @@
<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">"αποτρέπει την μετάβαση του tablet σε κατάσταση αδράνειας"</string>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Πάρα πολλές προσπάθειες. Ο αισθητήρας δακτυλικών αποτυπωμάτων απενεργοποιήθηκε."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Δοκιμάστε ξανά."</string>
@@ -989,6 +1000,12 @@
<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">"Δεν υπάρχει αρκετός αποθηκευτικός χώρος για το σύστημα. Βεβαιωθείτε ότι διαθέτετε 250 MB ελεύθερου χώρου και κάντε επανεκκίνηση."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Υπάρχει διαθέσιμο ανοικτό δίκτυο Wi-Fi</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Σύνδεση σε ανοιχτό δίκτυο Wi‑Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Σύνδεση σε ανοιχτό δίκτυο Wi‑Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Ολοκληρώθηκε η σύνδεση στο δίκτυο Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Δεν ήταν δυνατή η σύνδεση σε δίκτυο Wi‑Fi"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Το Wi‑Fi ενεργοποιήθηκε αυτόματα"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Βρίσκεστε κοντά σε αποθηκευμένο δίκτυο: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Συνδεθείτε στο δίκτυο Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Σύνδεση στο δίκτυο"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"Πιστοποιητικό ασφαλείας"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Αυτό το πιστοποιητικό είναι έγκυρο."</string>
<string name="issued_to" msgid="454239480274921032">"Εκδόθηκε σε:"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Μέχρι να απενεργοποιήσετε \"Μην ενοχλείτε\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Μέχρι την απενεργοποίηση"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Ενεργοπ. λειτουργ. εργασίας;"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Με αυτή την ενέργεια θα ενεργοποιηθεί το προφίλ εργασίας σας, συμπεριλαμβανομένων των εφαρμογών, του συγχρονισμού στο παρασκήνιο και σχετικών λειτουργιών"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Μερ. λειτ. ίσως είναι περιορ."</string>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Η εφαρμογή <xliff:g id="APP_0">%1$s</xliff:g> θέλει να εμφανίζει τμήματα της εφαρμογής <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Επεξεργασία"</string>
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 2910067..0f774d6 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Your organisation manages this device and may monitor network traffic. Tap for details."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Your device will be erased"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Me"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tablet options"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV options"</string>
@@ -263,8 +264,8 @@
<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">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Switch to personal profile"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Switch to work profile"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to access your contacts"</string>
@@ -416,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"route calls through the system"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Allows the app to route its calls through the system in order to improve the calling experience."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"read phone numbers"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Allows the app to access the phone numbers of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
@@ -485,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger moved too slow. Please try again."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Not recognised"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Fingerprint operation cancelled by user."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Too many attempts. Fingerprint sensor disabled."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
@@ -990,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Open"</string>
<string name="sms" msgid="4560537514610063430">"Message"</string>
<string name="add_contact" msgid="7867066569670597203">"Add"</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">"Storage space running out"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Some system functions may not work"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Not enough storage for the system. Make sure that you have 250 MB of free space and restart."</string>
@@ -1115,6 +1128,8 @@
<item quantity="one">Open Wi-Fi network available</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Connect to open Wi‑Fi network"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connecting to open Wi‑Fi network"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Connected to Wi‑Fi network"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Could not connect to Wi‑Fi network"</string>
@@ -1412,6 +1427,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> over specified limit."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Background data restricted"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Tap to remove restriction."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Large data usage"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Your data usage over the last few days is larger than normal. Tap to view usage and settings."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Security certificate"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"This certificate is valid."</string>
<string name="issued_to" msgid="454239480274921032">"Issued to:"</string>
@@ -1688,7 +1705,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Until you turn off Do not disturb"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Until you turn off"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do not disturb"</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">"Collapse"</string>
@@ -1737,9 +1754,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"All regions"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Turn on work mode?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"This will turn on your work profile, including apps, background sync and related features"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Turn on work profile?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Your work apps, notifications, data and other work profile features will be turned on"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</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">"You have new messages"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string>
@@ -1811,7 +1832,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Shortcut is disabled"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstall"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Launch anyway"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstall harmful app?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> wants to show <xliff:g id="APP_2">%2$s</xliff:g> slices"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Edit"</string>
</resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 2910067..0f774d6 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Your organisation manages this device and may monitor network traffic. Tap for details."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Your device will be erased"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Me"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tablet options"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV options"</string>
@@ -263,8 +264,8 @@
<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">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Switch to personal profile"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Switch to work profile"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to access your contacts"</string>
@@ -416,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"route calls through the system"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Allows the app to route its calls through the system in order to improve the calling experience."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"read phone numbers"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Allows the app to access the phone numbers of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
@@ -485,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger moved too slow. Please try again."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Not recognised"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Fingerprint operation cancelled by user."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Too many attempts. Fingerprint sensor disabled."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
@@ -990,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Open"</string>
<string name="sms" msgid="4560537514610063430">"Message"</string>
<string name="add_contact" msgid="7867066569670597203">"Add"</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">"Storage space running out"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Some system functions may not work"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Not enough storage for the system. Make sure that you have 250 MB of free space and restart."</string>
@@ -1115,6 +1128,8 @@
<item quantity="one">Open Wi-Fi network available</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Connect to open Wi‑Fi network"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connecting to open Wi‑Fi network"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Connected to Wi‑Fi network"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Could not connect to Wi‑Fi network"</string>
@@ -1412,6 +1427,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> over specified limit."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Background data restricted"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Tap to remove restriction."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Large data usage"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Your data usage over the last few days is larger than normal. Tap to view usage and settings."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Security certificate"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"This certificate is valid."</string>
<string name="issued_to" msgid="454239480274921032">"Issued to:"</string>
@@ -1688,7 +1705,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Until you turn off Do not disturb"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Until you turn off"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do not disturb"</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">"Collapse"</string>
@@ -1737,9 +1754,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"All regions"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Turn on work mode?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"This will turn on your work profile, including apps, background sync and related features"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Turn on work profile?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Your work apps, notifications, data and other work profile features will be turned on"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</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">"You have new messages"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string>
@@ -1811,7 +1832,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Shortcut is disabled"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstall"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Launch anyway"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstall harmful app?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> wants to show <xliff:g id="APP_2">%2$s</xliff:g> slices"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Edit"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 2910067..0f774d6 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Your organisation manages this device and may monitor network traffic. Tap for details."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Your device will be erased"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Me"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tablet options"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV options"</string>
@@ -263,8 +264,8 @@
<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">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Switch to personal profile"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Switch to work profile"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to access your contacts"</string>
@@ -416,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"route calls through the system"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Allows the app to route its calls through the system in order to improve the calling experience."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"read phone numbers"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Allows the app to access the phone numbers of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
@@ -485,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger moved too slow. Please try again."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Not recognised"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Fingerprint operation cancelled by user."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Too many attempts. Fingerprint sensor disabled."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
@@ -990,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Open"</string>
<string name="sms" msgid="4560537514610063430">"Message"</string>
<string name="add_contact" msgid="7867066569670597203">"Add"</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">"Storage space running out"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Some system functions may not work"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Not enough storage for the system. Make sure that you have 250 MB of free space and restart."</string>
@@ -1115,6 +1128,8 @@
<item quantity="one">Open Wi-Fi network available</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Connect to open Wi‑Fi network"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connecting to open Wi‑Fi network"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Connected to Wi‑Fi network"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Could not connect to Wi‑Fi network"</string>
@@ -1412,6 +1427,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> over specified limit."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Background data restricted"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Tap to remove restriction."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Large data usage"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Your data usage over the last few days is larger than normal. Tap to view usage and settings."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Security certificate"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"This certificate is valid."</string>
<string name="issued_to" msgid="454239480274921032">"Issued to:"</string>
@@ -1688,7 +1705,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Until you turn off Do not disturb"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Until you turn off"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do not disturb"</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">"Collapse"</string>
@@ -1737,9 +1754,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"All regions"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Turn on work mode?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"This will turn on your work profile, including apps, background sync and related features"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Turn on work profile?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Your work apps, notifications, data and other work profile features will be turned on"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</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">"You have new messages"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string>
@@ -1811,7 +1832,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Shortcut is disabled"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstall"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Launch anyway"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstall harmful app?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> wants to show <xliff:g id="APP_2">%2$s</xliff:g> slices"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Edit"</string>
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 2910067..0f774d6 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Your organisation manages this device and may monitor network traffic. Tap for details."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Your device will be erased"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Me"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tablet options"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV options"</string>
@@ -263,8 +264,8 @@
<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">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Switch to personal profile"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Switch to work profile"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to access your contacts"</string>
@@ -416,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"route calls through the system"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Allows the app to route its calls through the system in order to improve the calling experience."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"read phone numbers"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Allows the app to access the phone numbers of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
@@ -485,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger moved too slow. Please try again."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Not recognised"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Fingerprint operation cancelled by user."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Too many attempts. Fingerprint sensor disabled."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
@@ -990,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Open"</string>
<string name="sms" msgid="4560537514610063430">"Message"</string>
<string name="add_contact" msgid="7867066569670597203">"Add"</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">"Storage space running out"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Some system functions may not work"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Not enough storage for the system. Make sure that you have 250 MB of free space and restart."</string>
@@ -1115,6 +1128,8 @@
<item quantity="one">Open Wi-Fi network available</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Connect to open Wi‑Fi network"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connecting to open Wi‑Fi network"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Connected to Wi‑Fi network"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Could not connect to Wi‑Fi network"</string>
@@ -1412,6 +1427,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> over specified limit."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Background data restricted"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Tap to remove restriction."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Large data usage"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Your data usage over the last few days is larger than normal. Tap to view usage and settings."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Security certificate"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"This certificate is valid."</string>
<string name="issued_to" msgid="454239480274921032">"Issued to:"</string>
@@ -1688,7 +1705,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Until you turn off Do not disturb"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Until you turn off"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do not disturb"</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">"Collapse"</string>
@@ -1737,9 +1754,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"All regions"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Turn on work mode?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"This will turn on your work profile, including apps, background sync and related features"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Turn on work profile?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Your work apps, notifications, data and other work profile features will be turned on"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</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">"You have new messages"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string>
@@ -1811,7 +1832,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Shortcut is disabled"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstall"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Launch anyway"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstall harmful app?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> wants to show <xliff:g id="APP_2">%2$s</xliff:g> slices"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Edit"</string>
</resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 5f7f19c..8160f0d 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Your organization manages this device and may monitor network traffic. Tap for details."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Your device will be erased"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organizations admin."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Me"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tablet options"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV options"</string>
@@ -263,8 +264,8 @@
<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">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Switch to personal profile"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Switch to work profile"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Allow <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> to access your contacts"</string>
@@ -416,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active, and the remote number connected by a call."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"route calls through the system"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Allows the app to route its calls through the system in order to improve the calling experience."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"read phone numbers"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Allows the app to access the phone numbers of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
@@ -485,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Finger moved too slow. Please try again."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Not recognized"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerprint hardware not available."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint time out reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation canceled."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Fingerprint operation canceled by user."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Too many attempts. Fingerprint sensor disabled."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
@@ -990,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Open"</string>
<string name="sms" msgid="4560537514610063430">"Message"</string>
<string name="add_contact" msgid="7867066569670597203">"Add"</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">"Storage space running out"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Some system functions may not work"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Not enough storage for the system. Make sure you have 250MB of free space and restart."</string>
@@ -1115,6 +1128,8 @@
<item quantity="one">Open Wi-Fi network available</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Connect to open Wi‑Fi network"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connecting to open Wi‑Fi network"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Connected to Wi‑Fi network"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Could not connect to Wi‑Fi network"</string>
@@ -1412,6 +1427,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> over specified limit."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Background data restricted"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Tap to remove restriction."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Large data usage"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Your data usage over the last few days is larger than normal. Tap to view usage and settings."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Security certificate"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"This certificate is valid."</string>
<string name="issued_to" msgid="454239480274921032">"Issued to:"</string>
@@ -1688,7 +1705,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Until you turn off Do Not Disturb"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Until you turn off"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do Not Disturb"</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">"Collapse"</string>
@@ -1737,9 +1754,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"All regions"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Turn on work mode?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"This will turn on your work profile, including apps, background sync, and related features"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Turn on work profile?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Your work apps, notifications, data, and other work profile features will be turned on"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</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">"You have new messages"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string>
@@ -1811,7 +1832,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Couldn’t restore shortcut because of app signature mismatch"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Couldn’t restore shortcut"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Shortcut is disabled"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstall"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Launch anyway"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstall harmful app?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> wants to show <xliff:g id="APP_2">%2$s</xliff:g> slices"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Edit"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 1fe3c9a..6af7eda 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Tu organización administra este dispositivo y es posible que controle el tráfico de red. Presiona para obtener más información."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Se borrarán los datos del dispositivo"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"No se puede usar la app de administración. Ahora se borrará tu dispositivo.\n\nSi tienes preguntas, comunícate con el administrador de tu organización."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"<xliff:g id="OWNER_APP">%s</xliff:g> inhabilitó la impresión."</string>
<string name="me" msgid="6545696007631404292">"Yo"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opciones de tablet"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opciones de TV"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Emergencias"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Informe de errores"</string>
<string name="global_action_logout" msgid="935179188218826050">"Finalizar sesión"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Iniciar informe de errores"</string>
<string name="bugreport_message" msgid="398447048750350456">"Se recopilará información sobre el estado actual de tu dispositivo, que se enviará por correo. Pasarán unos minutos desde que se inicie el informe de errores hasta que se envíe, por lo que te recomendamos que tengas paciencia."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactivo"</string>
@@ -262,8 +264,10 @@
<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">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Cambiar al perfil personal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Cambiar al perfil de trabajo"</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">"Contactos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceder a los contactos"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Permite que <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda a tus contactos"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que la aplicación acceda a las funciones de teléfono del dispositivo. La aplicación puede utilizar este permiso para descubrir identificadores de dispositivos y números de teléfono, para saber si una llamada está activa y para conocer el número remoto con el que se ha establecido conexión mediante una llamada."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"Transmite llamadas a través del sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Permite que la app transmita las llamadas a través del sistema para mejorar la experiencia de llamadas."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"leer números de teléfono"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Le permite a la app acceder a los números de teléfono del dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evitar que el tablet entre en estado de inactividad"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Moviste el dedo muy lento. Vuelve a intentarlo."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"No reconocido"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El hardware para detectar huellas digitales no está disponible."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"No se puede almacenar la huella digital. Elimina una de las existentes."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Finalizó el tiempo de espera para la huella digital. Vuelve a intentarlo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Se canceló la operación de huella digital."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Vuelve a intentarlo más tarde."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Realizaste demasiados intentos. Se inhabilitó el sensor de huellas digitales."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Vuelve a intentarlo."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Abrir"</string>
<string name="sms" msgid="4560537514610063430">"Mensaje"</string>
<string name="add_contact" msgid="7867066569670597203">"Agregar"</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">"Queda poco espacio de almacenamiento"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Es posible que algunas funciones del sistema no estén disponibles."</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"No hay espacio suficiente para el sistema. Asegúrate de que haya 250 MB libres y reinicia el dispositivo."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Abrir red de Wi-Fi disponible</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Conectarse a una red Wi-Fi abierta"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Conectándose a una red Wi-Fi abierta"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Se conectó a la red Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"No fue posible conectarse a la red Wi‑Fi"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Se activará la conexión Wi-Fi automáticamente"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Cuando estés cerca de una red guardada de alta calidad"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"No volver a activar"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Se activó el Wi-Fi automáticamente"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Estás cerca de una red guardada: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Accede a una red Wi-Fi."</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Acceder a la red"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Límite superado en <xliff:g id="SIZE">%s</xliff:g>"</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Datos de referencia restringidos"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Presiona y quita la restricción."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Uso de datos elevado"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Tu uso de datos fue más elevado de lo normal en los últimos días. Presiona para ver detalles sobre el uso y la configuración."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificado de seguridad"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Este certificado es válido."</string>
<string name="issued_to" msgid="454239480274921032">"Emitido a:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hasta la(s) <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Hasta la hora <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Hasta que desactives No molestar"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Hasta que lo desactives"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hasta que desactives No molestar"</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">"Contraer"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos los idiomas"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Todas las regiones"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Búsqueda"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"¿Activar modo de trabajo?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Esta acción activará tu perfil de trabajo, incluidas las apps, la sincronización en segundo plano y las funciones relacionadas"</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">"Activar"</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">"Tienes mensajes nuevos"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Abrir app de SMS para ver el mensaje"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Funciones limitadas"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Error al restablecer el acceso directo porque la app no admite la opción de copia de seguridad y restauración"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Error al restablecer el acceso directo por falta de coincidencia con la firma de apps"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Error al restablecer el acceso directo"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Se inhabilitó el acceso directo"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> quiere mostrar fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Editar"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index cf25ed3..d1a2fa3 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Tu organización administra este dispositivo y puede supervisar el tráfico de red. Toca la notificación para obtener más información."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Tu dispositivo se borrará"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"No se puede utilizar la aplicación de administración. Se borrarán los datos del dispositivo. \n\nSi tienes alguna pregunta, ponte en contacto con el administrador de tu organización."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"<xliff:g id="OWNER_APP">%s</xliff:g> ha inhabilitado la impresión."</string>
<string name="me" msgid="6545696007631404292">"Yo"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opciones del tablet"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opciones de la TV"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Emergencia"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Informe de error"</string>
<string name="global_action_logout" msgid="935179188218826050">"Finalizar sesión"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Crear informe de errores"</string>
<string name="bugreport_message" msgid="398447048750350456">"Se recopilará información sobre el estado actual de tu dispositivo y se enviará por correo electrónico. Pasarán unos minutos desde que empiece a generarse el informe de errores hasta que se envíe."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactivo"</string>
@@ -262,8 +264,10 @@
<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">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Cambiar a perfil personal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Cambiar a perfil de trabajo"</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">"Contactos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceder a tus contactos"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Permite que <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda a tus contactos"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que la aplicación acceda a las funciones de teléfono del dispositivo. La aplicación puede utilizar este permiso para descubrir identificadores de dispositivos y números de teléfono, para saber si una llamada está activa y para conocer el número remoto con el que se ha establecido conexión mediante una llamada."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"direccionar llamadas a través del sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Permite a la aplicación direccionar sus llamadas hacia el sistema para mejorar la calidad de estas."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"leer números de teléfono"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Permite que la aplicación acceda a los números de teléfono del dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir que el tablet entre en modo de suspensión"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Has movido el dedo demasiado despacio. Vuelve a intentarlo."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"No reconocido"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El hardware de huella digital no está disponible."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"No se puede almacenar la huella digital. Elimina una ya creada."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Se ha alcanzado el tiempo de espera de la huella digital. Vuelve a intentarlo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Se ha cancelado la operación de huella digital."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Vuelve a intentarlo más tarde."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Demasiados intentos. Se ha inhabilitado el sensor de huellas digitales."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Vuelve a intentarlo."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Abrir"</string>
<string name="sms" msgid="4560537514610063430">"Mensaje"</string>
<string name="add_contact" msgid="7867066569670597203">"Añadir"</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">"Queda poco espacio"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Es posible que algunas funciones del sistema no funcionen."</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"No hay espacio suficiente para el sistema. Comprueba que haya 250 MB libres y reinicia el dispositivo."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Red Wi-Fi abierta disponible</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Conectarse a una red Wi-Fi abierta"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Conectándose a una red Wi-Fi abierta"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Conectado a la red Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"No se ha podido conectar a la red Wi-Fi"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"La conexión Wi‑Fi se activará automáticamente"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Cuando estés cerca de una red de alta calidad guardada"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"No volver a activar"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi activada automáticamente"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Estás cerca de una red guardada: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Iniciar sesión en red Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Iniciar sesión en la red"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Límite superado en <xliff:g id="SIZE">%s</xliff:g>"</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Datos en segundo plano restringidos"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Toca para quitar la restricción."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Uso de datos elevado"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Tu uso de datos ha sido más elevado de lo normal en los últimos días. Toca para ver detalles sobre el uso y ajustes."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificado de seguridad"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Este certificado es válido."</string>
<string name="issued_to" msgid="454239480274921032">"Emitido para:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hasta las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Hasta las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Hasta que desactives el modo No molestar"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Hasta que se desactive"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hasta que desactives la opción No molestar"</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">"Contraer"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos los idiomas"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Todas las regiones"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Buscar"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"¿Activar modo de trabajo?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Se activará tu perfil de trabajo, incluidas las aplicaciones, la sincronización en segundo plano y las funciones relacionadas"</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">"Activar"</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">"Tienes mensajes nuevos"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Abre la aplicación de SMS para ver el mensaje"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Algunas funciones limitadas"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"No se ha podido restaurar el acceso directo porque la aplicación no es compatible con la función de copia de seguridad y restauración"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"No se ha podido restaurar el acceso directo porque la firma de la aplicación no coincide"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"No se ha podido restaurar el acceso directo"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"El acceso directo está inhabilitado"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> quiere mostrar fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Editar"</string>
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index c0821c7..29d600f 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Teie organisatsioon haldab seda seadet ja võib jälgida võrguliiklust. Puudutage üksikasjade vaatamiseks."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Seade kustutatakse"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Administraatori rakendust ei saa kasutada. Teie seade kustutatakse.\n\nKüsimuste korral pöörduge organisatsiooni administraatori poole."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Rakendus <xliff:g id="OWNER_APP">%s</xliff:g> on printimise keelanud."</string>
<string name="me" msgid="6545696007631404292">"Mina"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tahvelarvuti valikud"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Teleri valikud"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Hädaabi"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Veaaruanne"</string>
<string name="global_action_logout" msgid="935179188218826050">"Seansi lõpp"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Ekraanipilt"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Veaaruande võtmine"</string>
<string name="bugreport_message" msgid="398447048750350456">"Nii kogutakse teavet teie seadme praeguse oleku kohta, et saata see meilisõnumina. Enne kui saate veaaruande ära saata, võtab selle loomine natuke aega; varuge kannatust."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interakt. aruanne"</string>
@@ -262,8 +264,10 @@
<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">"Turvarežiim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-süsteem"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Lülita isiklikule profiilile"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Lülita tööprofiilile"</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">"Kontaktid"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"juurdepääs kontaktidele"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Lubage rakendusele <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> juurdepääs kontaktidele"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Annab rakendusele juurdepääsu seadme telefonifunktsioonidele. See luba võimaldab rakendusel määrata telefoninumbri ja seadme ID-d ning kontrollida, kas kõne on aktiivne ja kaugnumber on kõne kaudu telefoniga ühendatud."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"kõnede marsruutimine süsteemi kaudu"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Võimaldab rakendusel kõnesid süsteemi kaudu marsruutida, et helistamiskogemust täiustada."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"lugeda telefoninumbreid"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Rakendusel lubatakse juurde pääseda seadme telefoninumbritele."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"tahvelarvuti uinumise vältimine"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Sõrm liikus liiga aeglaselt. Proovige uuesti."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ei tuvastatud"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Sõrmejälje riistvara pole saadaval."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sõrmejälge ei saa salvestada. Eemaldage olemasolev sõrmejälg."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sõrmejälje riistvara taimeri ajalõpp. Proovige uuesti."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Sõrmejälje toiming tühistati."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Liiga palju katseid. Proovige hiljem uuesti."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Liiga palju katseid. Sõrmejäljeandur on keelatud."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Proovige uuesti."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Ava"</string>
<string name="sms" msgid="4560537514610063430">"Saada sõnum"</string>
<string name="add_contact" msgid="7867066569670597203">"Lisa"</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">"Talletusruum saab täis"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Mõned süsteemifunktsioonid ei pruugi töötada"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Süsteemis pole piisavalt talletusruumi. Veenduge, et seadmes oleks 250 MB vaba ruumi, ja käivitage seade uuesti."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Avatud WiFi-võrk on saadaval</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Looge ühendus avatud WiFi-võrguga"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ühenduse loomine avatud WiFi-võrguga"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Ühendatud WiFi-võrguga"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"WiFi-võrguga ei õnnestunud ühendust luua"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"WiFi lülitub sisse automaatselt"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kui olete kvaliteetse salvestatud võrgu läheduses"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ära lülita tagasi sisse"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"WiFi lülitati automaatselt sisse"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Teie lähedal on salvestatud võrk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Logi sisse WiFi-võrku"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Võrku sisselogimine"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> üle määratud piirmäära."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Taustandmed on piiratud"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Puudut. piirangu eemaldamiseks."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Suur andmekasutus"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Teie andmekasutus on viimastel päevadel tavapärasest suurem. Puudutage kasutuse ja seadete vaatamiseks."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Turvasertifikaat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"See sertifikaat on kehtiv."</string>
<string name="issued_to" msgid="454239480274921032">"Väljastatud subjektile:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Kuni <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Kuni <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (järgmine äratus)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Kuni lülitate välja valiku Mitte segada"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Kuni välja lülitate"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Kuni lülitate välja valiku Mitte segada"</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">"Ahendamine"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Kõik keeled"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Kõik piirkonnad"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Otsing"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Kas lülitada töörežiim sisse?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"See lülitab sisse teie tööprofiili, sh rakendused, taustal sünkroonimise ja seotud funktsioonid"</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">"Lülita sisse"</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">"Teile on uusi sõnumeid"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Avage vaatamiseks SMS-rakendus"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Funktsioon võib olla piiratud"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Otseteed ei õnnestunud taastada, kuna rakendus ei toeta varundamist ega taastamist"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Otseteed ei õnnestunud taastada, kuna rakenduse allkiri ei ühti"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Otseteed ei õnnestunud taastada"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Otsetee on keelatud"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Rakendus <xliff:g id="APP_0">%1$s</xliff:g> soovib näidata rakenduse <xliff:g id="APP_2">%2$s</xliff:g> lõike"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Muutmine"</string>
</resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 960dfd8..2436326 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Erakundeak kudeatzen du gailua eta baliteke sareko trafikoa gainbegiratzea. Sakatu hau xehetasunak ikusteko."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Gailuko datuak ezabatu egingo dira"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Ezin da erabili administratzeko aplikazioa. Ezabatu egingo da gailuko eduki guztia.\n\nZalantzarik baduzu, jarri erakundeko administratzailearekin harremanetan."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"<xliff:g id="OWNER_APP">%s</xliff:g> aplikazioak desgaitu egin du inprimatzeko aukera."</string>
<string name="me" msgid="6545696007631404292">"Ni"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tabletaren aukerak"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Telebistaren aukerak"</string>
@@ -217,8 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Larrialdi-deiak"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Akatsen txostena"</string>
<string name="global_action_logout" msgid="935179188218826050">"Amaitu saioa"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Pantaila-argazkia"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Sortu akatsen txostena"</string>
<string name="bugreport_message" msgid="398447048750350456">"Gailuaren uneko egoerari buruzko informazioa bilduko da, mezu elektroniko gisa bidaltzeko. Minutu batzuk igaroko dira akatsen txostena sortzen hasten denetik bidaltzeko prest egon arte. Itxaron, mesedez."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Txosten dinamikoa"</string>
@@ -264,8 +264,10 @@
<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">"Modu segurua"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistema"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Aldatu profil pertsonalera"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Aldatu laneko profilera"</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">"Kontaktuak"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"atzitu kontaktuak"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Baimendu kontaktuak atzitzea <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> aplikazioari"</string>
@@ -417,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Gailuaren telefono-eginbideak atzitzeko baimena ematen die aplikazioei. Baimen horrek aplikazioari telefono-zenbakia eta gailu IDak zein diren, deirik aktibo dagoen eta deia zer zenbakirekin konektatuta dagoen zehazteko baimena ematen die aplikazioei."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"bideratu deiak sistemaren bidez"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Deiak sistemaren bidez bideratzea baimentzen die aplikazioei, deien zerbitzua ahal bezain ona izan dadin."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"irakurri telefono-zenbakiak"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Gailuaren telefono-zenbakiak atzitzea baimentzen die aplikazioei."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"eragotzi tableta inaktibo ezartzea"</string>
@@ -438,9 +444,9 @@
<string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"Telebistaren ordu-zona aldatzea baimentzen die aplikazioei."</string>
<string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Telefonoaren ordu-zona aldatzea baimentzen die aplikazioei."</string>
<string name="permlab_getAccounts" msgid="1086795467760122114">"bilatu gailuko kontuak"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Tabletak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak har daitezke barne."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Tabletak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak har daitezke barnean."</string>
<string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Telebistak ezagutzen dituen kontuen zerrenda lortzea baimentzen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak sar daitezke."</string>
- <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak har daitezke barne."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak har daitezke barnean."</string>
<string name="permlab_accessNetworkState" msgid="4951027964348974773">"ikusi sareko konexioak"</string>
<string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Sareko konexioei buruzko informazioa ikusteko baimena ematen die aplikazioei; adibidez, zer sare dauden eta zeintzuk dauden konektatuta."</string>
<string name="permlab_createNetworkSockets" msgid="7934516631384168107">"izan sarerako sarbide osoa"</string>
@@ -486,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Mantsoegi mugitu duzu hatza. Saiatu berriro."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ez da ezagutzen"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hatz-markaren hardwarea ez dago erabilgarri."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ezin da gorde hatz-marka digitala. Kendu lehendik gordeta duzunetako bat."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Hatz-marka digitalak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hatz-markaren eragiketa bertan behera utzi da."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Saiakera gehiegi egin dituzu. Desgaitu egin da hatz-marken sentsorea."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Saiatu berriro."</string>
@@ -991,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Ireki"</string>
<string name="sms" msgid="4560537514610063430">"Bidali mezua"</string>
<string name="add_contact" msgid="7867066569670597203">"Gehitu"</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">"Memoria betetzen ari da"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Sistemaren funtzio batzuek ez dute agian funtzionatuko"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Sisteman ez dago behar adina memoria. Ziurtatu gutxienez 250 MB erabilgarri dituzula eta, ondoren, berrabiarazi gailua."</string>
@@ -1116,6 +1131,8 @@
<item quantity="one">Wi-Fi sare irekia erabilgarri</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Konektatu Wi‑Fi sare irekira"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Wi‑Fi sare irekira konektatzen"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi sare irekira konektatuta"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Ezin izan da konektatu Wi‑Fi sare irekira"</string>
@@ -1125,10 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi konexioa automatikoki aktibatuko da"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Gordeta daukazun kalitate handiko sare batetik gertu zaudenean"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ez aktibatu berriro"</string>
- <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
- <skip />
- <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
- <skip />
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Automatikoki aktibatu da Wi‑Fi konexioa"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Gordetako sare honetatik gertu zaude: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Hasi saioa Wi-Fi sarean"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Hasi saioa sarean"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Zehaztutako muga baino <xliff:g id="SIZE">%s</xliff:g> gehiago."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Atzeko planoko datuak murriztuta"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Sakatu murriztapena kentzeko."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Datu asko erabili dira"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Ohikoa baino datu kopuru handiagoa erabili duzu azken egunetan. Sakatu erabilera eta ezarpenak ikusteko."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Segurtasun-ziurtagiria"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Ziurtagiria baliozkoa da."</string>
<string name="issued_to" msgid="454239480274921032">"Honi jaulkia:"</string>
@@ -1692,7 +1709,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> arte"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> arte (hurrengo alarma)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"\"Ez molestatu\" desaktibatzen duzun arte"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Desaktibatu arte"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\"Ez molestatu\" desaktibatzen duzun arte"</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">"Tolestu"</string>
@@ -1741,9 +1758,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Hizkuntza guztiak"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Lurralde guztiak"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Bilaketa"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Laneko modua aktibatu?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Laneko profila aktibatuko da, aplikazioak, atzeko planoko sinkronizazioa eta erlazionatutako eginbideak barne"</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">"Aktibatu"</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">"Mezu berriak dituzu"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Mezuak ikusteko, ireki SMS mezuen aplikazioa"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Funtzioak mugatuta egon litezke"</string>
@@ -1815,10 +1838,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ezin izan da leheneratu lasterbidea aplikazioaren sinadurak ez datozelako bat"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Ezin izan da leheneratu lasterbidea"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Desgaituta dago lasterbidea"</string>
- <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> aplikazioak <xliff:g id="APP_2">%2$s</xliff:g> aplikazioaren zatiak erakutsi nahi ditu"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Editatu"</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 0458336..9f9d335 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"گزینههای تلویزیون"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"عکس صفحهنمایش"</string>
<string name="bugreport_title" msgid="2667494803742548533">"گرفتن گزارش اشکال"</string>
<string name="bugreport_message" msgid="398447048750350456">"این گزارش اطلاعات مربوط به وضعیت دستگاه کنونی شما را جمعآوری میکند تا به صورت یک پیام رایانامه ارسال شود. از زمان شروع گزارش اشکال تا آماده شدن برای ارسال اندکی زمان میبرد؛ لطفاً شکیبا باشید."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"گزارش تعاملی"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"رفتن به نمایه شخصی"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"رفتن به نمایه کاری"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"به <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> امکان دهید به مخاطبین شما دسترسی پیدا کند"</string>
@@ -415,6 +419,10 @@
<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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"تلاشهای بسیاری زیادی انجام شده است. حسگر اثر انگشت غیرفعال شد."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوباره امتحان کنید."</string>
@@ -989,6 +1000,12 @@
<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>
@@ -1114,6 +1131,8 @@
<item quantity="other">شبکه Wi-Fi باز در دسترس</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"اتصال به شبکه Wi‑Fi باز"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"درحال اتصال به شبکه Wi‑Fi باز"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"به شبکه Wi‑Fi متصل شد"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"به شبکه Wi-Fi متصل نشد"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi بهصورت خودکار روشن شد"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"نزدیک شبکه ذخیرهشدهای هستید: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ورود به شبکه Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ورود به سیستم شبکه"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"گواهی امنیتی"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"این گواهی معتبر است."</string>
<string name="issued_to" msgid="454239480274921032">"صادر شده برای:"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"تا زمانی که «مزاحم نشوید» را خاموش کنید"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"تا زمانیکه آن را خاموش کنید"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"حالت کار روشن شود؟"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"با این کار، نمایه کاری شما روشن میشود (ازجمله برنامهها، همگامسازی پسزمینه و قابلیتهای مرتبط)"</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>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> میخواهد تکههای <xliff:g id="APP_2">%2$s</xliff:g> را نشان دهد"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"ویرایش"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index d6d1315..e5ed2a3 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organisaatiosi hallinnoi tätä laitetta ja voi tarkkailla verkkoliikennettä. Katso lisätietoja napauttamalla."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Laitteen tiedot poistetaan"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Hallintasovellusta ei voi käyttää. Laitteen tiedot poistetaan.\n\nPyydä ohjeita järjestelmänvalvojaltasi."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"<xliff:g id="OWNER_APP">%s</xliff:g> on poistanut tulostuksen käytöstä."</string>
<string name="me" msgid="6545696007631404292">"Minä"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tablet-laitteen asetukset"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Televisioasetukset"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Hätäpuhelu"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Virheraportti"</string>
<string name="global_action_logout" msgid="935179188218826050">"Lopeta käyttökerta"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Kuvakaappaus"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Luo virheraportti"</string>
<string name="bugreport_message" msgid="398447048750350456">"Toiminto kerää tietoja laitteen tilasta ja lähettää ne sähköpostitse. Virheraportti on valmis lähetettäväksi hetken kuluttua - kiitos kärsivällisyydestäsi."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiivinen"</string>
@@ -262,8 +264,10 @@
<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">"Suojattu tila"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Siirry henkilökohtaiseen profiiliin"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Siirry työprofiiliin"</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">"Kontaktit"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"käyttää yhteystietoja"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Anna sovellukselle <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> yhteystietojesi käyttöoikeus."</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Antaa sovelluksen käyttää laitteen puhelinominaisuuksia. Sovellus voi määrittää puhelinnumeron ja laitteen tunnuksen, puhelun tilan sekä soitetun numeron."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"ohjata puhelut järjestelmän kautta"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Tämä sallii sovelluksen ohjata puhelut järjestelmän kautta, mikä auttaa parantamaan puhelujen laatua."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"lukea puhelinnumeroita"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Anna sovelluksen käyttää laitteella olevia puhelinnumeroita."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"estä tablet-laitetta menemästä virransäästötilaan"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Liikutit sormea liian hitaasti. Yritä uudelleen."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ei tunnistettu"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Sormenjälkilaitteisto ei ole käytettävissä."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sormenjälkeä ei voida tallentaa. Poista aiemmin lisätty sormenjälki."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sormenjälkitunnistimen toiminta aikakatkaistiin. Yritä uudelleen."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Sormenjälkitoiminto peruutettiin."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Liian monta yritystä. Yritä myöhemmin uudelleen."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Liian monta yritystä. Sormenjälkitunnistin poistettu käytöstä."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Yritä uudelleen."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Avaa"</string>
<string name="sms" msgid="4560537514610063430">"Viesti"</string>
<string name="add_contact" msgid="7867066569670597203">"Lisää"</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">"Tallennustila loppumassa"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Kaikki järjestelmätoiminnot eivät välttämättä toimi"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Tallennustila ei riitä. Varmista, että vapaata tilaa on 250 Mt, ja käynnistä uudelleen."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Avoin Wi-Fi-verkko käytettävissä</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Yhdistä avoimeen Wi‑Fi-verkkoon"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Yhdistetään avoimeen Wi‑Fi-verkkoon"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Yhdistetty Wi-Fi-verkkoon"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi-verkkoon yhdistäminen epäonnistui"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi käynnistyy automaattisesti"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kun olet lähellä laadukasta tallennettua verkkoa"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Älä käynnistä uudelleen"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi otettiin käyttöön automaattisesti"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Olet lähellä tallennettua verkkoa: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Kirjaudu Wi-Fi-verkkoon"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Kirjaudu verkkoon"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> yli asetetun rajan"</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Rajoitettu taustadatan käyttö"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Poista rajoitus napauttamalla."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Suuri datan käyttö"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Olet käyttänyt normaalia enemmän dataa viime päivinä. Napauta nähdäksesi käyttö ja asetukset."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Suojausvarmenne"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Varmenne on voimassa."</string>
<string name="issued_to" msgid="454239480274921032">"Varmenteen saaja:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Kunnes kello on <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> asti (seuraava hälytys)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Kunnes poistat Älä häiritse ‑tilan käytöstä"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Kunnes poistat sen käytöstä"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Kunnes poistat Varattu-tilan käytöstä."</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">"Kutista"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Kaikki kielet"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Kaikki alueet"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Haku"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Otetaanko työtila käyttöön?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Ottaa käyttöön työprofiilin, esimerkiksi sovelluksia, taustasynkronoinnin ja muita ominaisuuksia."</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">"Ota käyttöön"</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">"Sinulle on uusia viestejä"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Katso avaamalla tekstiviestisovellus."</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Toimintorajoitus mahdollinen"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Pikakuvakkeen palautus epäonnistui, koska sovellus ei tue varmuuskopiointia eikä palauttamista."</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Pikakuvakkeen palautus epäonnistui sovelluksen allekirjoituksen yhteensopimattomuuden vuoksi."</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Pikakuvakkeen palautus epäonnistui."</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Pikakuvake on poistettu käytöstä."</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> haluaa näyttää osia sovelluksesta <xliff:g id="APP_2">%2$s</xliff:g>."</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Muokkaa"</string>
</resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index a53fac7..9fd7fe6 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"A túa organización xestiona este dispositivo e pode controlar o tráfico de rede. Toca para obter máis detalles."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Borrarase o teu dispositivo"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Non se pode utilizar a aplicación de administración. Borrarase o teu dispositivo.\n\nSe tes preguntas, contacta co administrador da túa organización."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"<xliff:g id="OWNER_APP">%s</xliff:g> desactivou a impresión."</string>
<string name="me" msgid="6545696007631404292">"Eu"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcións da tableta"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opcións da televisión"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Urxencias"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Informe de erros"</string>
<string name="global_action_logout" msgid="935179188218826050">"Finalizar a sesión"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Crear informe de erros"</string>
<string name="bugreport_message" msgid="398447048750350456">"Este informe recompilará información acerca do estado actual do teu dispositivo para enviala en forma de mensaxe de correo electrónico. O informe de erros tardará un pouco en completarse desde o seu inicio ata que estea preparado para enviarse, polo que che recomendamos que teñas paciencia."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactivo"</string>
@@ -262,8 +264,10 @@
<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">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Cambiar ao perfil persoal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Cambiar ao perfil de traballo"</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">"Contactos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceder aos teus contactos"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Permitir que a aplicación <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acceda aos teus contactos"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite á aplicación acceder ás funcións de teléfono do dispositivo. Con este permiso a aplicación pode determinar o número de teléfono e os ID do dispositivo, se unha chamada está activa e o número remoto conectado mediante unha chamada."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"dirixir as chamadas a través do sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Permite á aplicación dirixir as súas chamadas a través do sistema para mellorar a túa experiencia durante as chamadas."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"ler números de teléfono"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Permite que a aplicación acceda aos números de teléfono do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evitar que a tableta entre en modo de inactividade"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"O dedo moveuse demasiado lento. Téntao de novo."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Non se recoñece"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impresión dixital non dispoñible."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Non se pode almacenar a impresión dixital. Elimina unha impresión dixital existente."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Esgotouse o tempo de espera da impresión dixital. Téntao de novo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Cancelouse a operación da impresión dixital."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Téntao de novo máis tarde."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Demasiados intentos. Desactivouse o sensor de impresión dixital."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Téntao de novo."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Abrir"</string>
<string name="sms" msgid="4560537514610063430">"Mensaxe"</string>
<string name="add_contact" msgid="7867066569670597203">"Engadir"</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">"Estase esgotando o espazo de almacenamento"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"É posible que algunhas funcións do sistema non funcionen"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Non hai almacenamento suficiente para o sistema. Asegúrate de ter un espazo libre de 250 MB e reinicia o dispositivo."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Abrir rede wifi dispoñible</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Conéctate a unha rede wifi aberta"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Conectándose á rede wifi aberta"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Conectouse á rede wifi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Non se puido conectar á rede wifi"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"A wifi activarase automaticamente"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Cando esteas preto dunha rede gardada de alta calidade"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Non volver activar"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Activouse a wifi automaticamente"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Estás preto dunha rede gardada: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Inicia sesión na rede wifi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Inicia sesión na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1410,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> supera o límite especificado."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Datos en segundo plano limitados"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Toca para eliminar a restrición."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Uso de datos elevado"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Nos últimos días estás usando máis datos do habitual. Toca para ver o uso e a configuración."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificado de seguranza"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Este certificado é válido."</string>
<string name="issued_to" msgid="454239480274921032">"Emitido para:"</string>
@@ -1686,7 +1709,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Ata as <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Ata as <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Ata que desactives o modo Non molestar"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Ata a desactivación"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Ata que desactives o modo Non molestar"</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">"Contraer"</string>
@@ -1735,9 +1758,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Todas as rexións"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Buscar"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Activar o modo de traballo?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Así activarase o teu perfil de traballo, mesmo as aplicacións, a sincronización en segundo plano e as funcións relacionadas"</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">"Activar"</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">"Tes mensaxes novas"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Abre a aplicación de SMS para ver as mensaxes"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Pode haber funcións limitadas"</string>
@@ -1808,6 +1837,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Non se puido restaurar o atallo porque a aplicación non é compatible coa restauración e a copia de seguranza"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Non se puido restaurar o atallo porque a sinatura da aplicación non coincide"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Non se puido restaurar o atallo"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Desactivouse o atallo"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"A aplicación <xliff:g id="APP_0">%1$s</xliff:g> quere mostrar partes de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Editar"</string>
</resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 2af95ce..0ed3d6d 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV વિકલ્પો"</string>
@@ -217,8 +218,7 @@
<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="global_action_screenshot" msgid="8329831278085426283">"સ્ક્રીનશૉટ"</string>
<string name="bugreport_title" msgid="2667494803742548533">"બગ રિપોર્ટ લો"</string>
<string name="bugreport_message" msgid="398447048750350456">"આ, એક ઇ-મેઇલ સંદેશ તરીકે મોકલવા માટે, તમારા વર્તમાન ઉપકરણ સ્થિતિ વિશેની માહિતી એકત્રિત કરશે. એક બગ રિપોર્ટ પ્રારંભ કરીને તે મોકલવા માટે તૈયાર ન થઈ જાય ત્યાં સુધી તેમાં થોડો સમય લાગશે; કૃપા કરીને ધીરજ રાખો."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ક્રિયાપ્રતિક્રિયાત્મક રિપોર્ટ"</string>
@@ -264,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"વ્યક્તિગત પર સ્વિચ કરો"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"કાર્ય પર સ્વિચ કરો"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ને તમારા સંપર્કોને ઍક્સેસ કરવાની મંજૂરી આપો"</string>
@@ -417,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"એપ્લિકેશનને ફોન સુવિધાઓને ઍક્સેસ કરવાની મંજૂરી આપે છે. આ પરવાનગી એપ્લિકેશનને ફોન નંબર અને ઉપકરણ ID, કૉલ સક્રિય છે અને કોઈ કૉલ દ્વારા કનેક્ટ થયેલ રિમોટ નંબર નિર્ધારિત કરવાની મંજૂરી આપે છે."</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>
@@ -486,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ઘણા વધુ પ્રયત્નો. ફિંગરપ્રિન્ટ સેન્સર અક્ષમ કરવામાં આવ્યું છે."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ફરી પ્રયાસ કરો."</string>
@@ -991,6 +1000,12 @@
<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">"સિસ્ટમ માટે પર્યાપ્ત સ્ટોરેજ નથી. ખાતરી કરો કે તમારી પાસે 250MB ખાલી સ્થાન છે અને ફરીથી પ્રારંભ કરો."</string>
@@ -1116,6 +1131,8 @@
<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>
@@ -1125,10 +1142,8 @@
<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_wakeup_enabled_title" msgid="6534603733173085309">"વાઇ-ફાઇ આપમેળે ચાલુ થયું"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"તમે એક સાચવેલ નેટવર્કની નજીકમાં છો: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<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) -->
@@ -1416,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"ઉલ્લેખિત મર્યાદાથી <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="ssl_certificate" msgid="6510040486049237639">"સુરક્ષા પ્રમાણપત્ર"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"આ પ્રમાણપત્ર માન્ય છે."</string>
<string name="issued_to" msgid="454239480274921032">"આને રજૂ:"</string>
@@ -1692,7 +1709,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"તમે ખલેલ પાડશો નહીં બંધ ન કરો ત્યાં સુધી"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"તમે બંધ ન કરો ત્યાં સુધી"</string>
<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>
@@ -1741,9 +1758,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"કાર્ય મોડ ચાલુ કરીએ?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"આનાથી ઍપ્લિકેશનો, બૅકગ્રાઉન્ડ સિંક અને તે સંબંધિત સુવિધાઓ સહિતની તમારી કાર્યાલયની પ્રોફાઇલ ચાલુ થઈ જશે"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"કેટલીક કાર્યક્ષમતા મર્યાદિત હોઈ શકે છે"</string>
@@ -1815,10 +1838,12 @@
<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 (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g>એ <xliff:g id="APP_2">%2$s</xliff:g> સ્લાઇસ બતાવવા માગે છે"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"ફેરફાર કરો"</string>
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 251ec84..d9f592c 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"टीवी के विकल्प"</string>
@@ -217,8 +218,7 @@
<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="global_action_screenshot" msgid="8329831278085426283">"स्क्रीनशॉट"</string>
<string name="bugreport_title" msgid="2667494803742548533">"गड़बड़ी की रिपोर्ट लें"</string>
<string name="bugreport_message" msgid="398447048750350456">"इससे ईमेल भेजने के लिए, आपके डिवाइस की मौजूदा स्थिति से जुड़ी जानकारी इकट्ठा की जाएगी. गड़बड़ी की रिपोर्ट बनना शुरू होने से लेकर भेजने के लिए तैयार होने तक कुछ समय लगेगा; कृपया इंतज़ार करें."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"सहभागी रिपोर्ट"</string>
@@ -264,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"व्यक्तिगत प्रोफ़ाइल में स्विच करें"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"कार्य प्रोफ़ाइल में स्विच करें"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> को अपने संपर्क तक पहुंचने दें"</string>
@@ -417,6 +419,10 @@
<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>
@@ -486,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"बहुत अधिक कोशिशें. फ़िंगरप्रिंट सेंसर अक्षम है."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन: प्रयास करें."</string>
@@ -991,6 +1000,12 @@
<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">"सिस्टम के लिए ज़रूरी मेमोरी नहीं है. पक्का करें कि आपके पास 250एमबी की खाली जगह है और फिर से शुरू करें."</string>
@@ -1116,6 +1131,8 @@
<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>
@@ -1125,10 +1142,8 @@
<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_wakeup_enabled_title" msgid="6534603733173085309">"वाई-फ़ाई अपने आप चालू हो गया है"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"आप एक सेव किए गए नेटवर्क के पास हैं: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<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) -->
@@ -1415,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"सुरक्षा प्रमाणपत्र"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"यह प्रमाणपत्र मान्य है."</string>
<string name="issued_to" msgid="454239480274921032">"इन्हें जारी किया गया:"</string>
@@ -1691,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"जब तक कि आप परेशान ना करें को बंद नहीं कर देते"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"जब तक आप बंद नहीं करते"</string>
<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>
@@ -1740,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"कार्य मोड चालू करें?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"इससे आपकी कार्य प्रोफ़ाइल चालू हो जाएगी, जिसमें ऐप्लिकेशन, बैकग्राउंड सिंक और संबंधित सुविधाएं शामिल हैं"</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>
@@ -1814,10 +1837,12 @@
<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 (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g>, <xliff:g id="APP_2">%2$s</xliff:g> के हिस्से (स्लाइस) दिखाना चाहता है"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"बदलाव करें"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index bbe7ca9..767cbac 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -183,6 +183,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Vaša organizacija upravlja ovim uređajem i može nadzirati mrežni promet. Dodirnite za pojedinosti."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Uređaj će se izbrisati"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Administratorska aplikacija ne može se upotrebljavati. Uređaj će se izbrisati.\n\nAko imate pitanja, obratite se administratoru organizacije."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Ispis je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcije tabletnog uređaja"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opcije televizora"</string>
@@ -219,6 +220,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Hitno"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Izvješće o bugovima"</string>
<string name="global_action_logout" msgid="935179188218826050">"Završi sesiju"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Snimka zaslona"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Izvješće o programskoj pogrešci"</string>
<string name="bugreport_message" msgid="398447048750350456">"Time će se prikupiti podaci o trenutačnom stanju vašeg uređaja koje ćete nam poslati u e-poruci. Za pripremu izvješća o programskoj pogrešci potrebno je nešto vremena pa vas molimo za strpljenje."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktivno izvješće"</string>
@@ -265,8 +267,10 @@
<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">"Siguran način rada"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Prijeđite na osobni"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Prijeđite na radni"</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">"Kontakti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupati vašim kontaktima"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Dopustite aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da pristupa vašim kontaktima"</string>
@@ -418,6 +422,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Aplikaciji omogućuje pristup telefonskim značajkama uređaja. Ta dozvola aplikaciji omogućuje utvrđivanje telefonskog broja i ID-ova uređaja, je li poziv aktivan te udaljeni broj koji je povezan pozivom."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"preusmjeravati pozive putem sustava"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Omogućuje aplikaciji da preusmjerava pozive putem sustava radi poboljšanja doživljaja."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"čitati telefonske brojeve"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Aplikaciji omogućuje da pristupi telefonskim brojevima na uređaju."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"spriječi mirovanje tabletnog uređaja"</string>
@@ -487,10 +495,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Presporo pomicanje prsta. Pokušajte ponovo."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nije prepoznat"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otisak prsta nije dostupan."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisak prsta nije pohranjen. Uklonite postojeći otisak prsta."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Isteklo je vrijeme čekanja za otisak prsta. Pokušajte ponovo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja otiska prsta otkazana je."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Senzor otiska prsta onemogućen je zbog previše pokušaja."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Pokušajte ponovo."</string>
@@ -1009,6 +1020,12 @@
<string name="browse" msgid="1245903488306147205">"Otvori"</string>
<string name="sms" msgid="4560537514610063430">"Poruka"</string>
<string name="add_contact" msgid="7867066569670597203">"Dodaj"</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">"Ponestaje prostora za pohranu"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Neke sistemske funkcije možda neće raditi"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nema dovoljno pohrane za sustav. Oslobodite 250 MB prostora i pokrenite uređaj ponovo."</string>
@@ -1136,6 +1153,8 @@
<item quantity="other">Dostupne su otvorene Wi-Fi mreže</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Povezivanje s otvorenom Wi‑Fi mrežom"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Povezivanje s otvorenom Wi‑Fi mrežom"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Povezano s Wi-Fi mrežom"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nije uspjelo povezivanje s Wi-Fi mrežom"</string>
@@ -1145,6 +1164,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi će se uključiti automatski"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kada ste u blizini spremljene mreže visoke kvalitete"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Više ne uključuj"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi je uključen automatski"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Nalazite se u blizini spremljene mreže: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijava na Wi-Fi mrežu"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijava na mrežu"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1432,6 +1453,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Veličina <xliff:g id="SIZE">%s</xliff:g> prelazi navedeno ograničenje."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Pozadinski podaci ograničeni"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Dodirnite i uklonite ograničenje"</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Velika potrošnja podat. prometa"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Vaša potrošnja podatkovnog prometa u zadnjih je nekoliko dana veća nego obično. Dodirnite da biste vidjeli potrošnju i postavke."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Sigurnosni certifikat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Ovaj je certifikat valjan."</string>
<string name="issued_to" msgid="454239480274921032">"Izdano za:"</string>
@@ -1718,7 +1741,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (sljedeći alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Dok ne isključite \"Ne ometaj\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Dok ne isključite"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dok ne isključite \"Ne ometaj\""</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">"Sažmi"</string>
@@ -1768,9 +1791,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Svi jezici"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Sve regije"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pretraži"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Uključiti radni način?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Time će se uključiti vaš radni profil, uključujući aplikacije, sinkronizaciju u pozadini i povezane značajke"</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">"Uključi"</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">"Imate nove poruke"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite SMS aplikaciju da biste pregledali poruke"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Funkcije mogu biti ograničene"</string>
@@ -1842,6 +1871,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Vraćanje prečaca nije uspjelo jer aplikacija ne podržava sigurnosno kopiranje i vraćanje"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Vraćanje prečaca nije uspjelo zbog nepodudaranja potpisa aplikacije"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Vraćanje prečaca nije uspjelo"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Prečac je onemogućen"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> želi prikazivati isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Uređivanje"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 2dbe49d..e072b70 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Ezt az eszközt szervezete kezeli, és lehetséges, hogy a hálózati forgalmat is figyelik. További részletekért koppintson."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"A rendszer törölni fogja eszközét"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"A rendszergazdai alkalmazás nem használható. A rendszer most törli az eszközt.\n\nKérdéseivel forduljon szervezete rendszergazdájához."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"A(z) <xliff:g id="OWNER_APP">%s</xliff:g> letiltotta a nyomtatást."</string>
<string name="me" msgid="6545696007631404292">"Saját"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Táblagép beállításai"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Tévébeállítások"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Segélyhívás"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Programhiba bejelentése"</string>
<string name="global_action_logout" msgid="935179188218826050">"Munkamenet befejezése"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Képernyőkép"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Hibajelentés készítése"</string>
<string name="bugreport_message" msgid="398447048750350456">"Ezzel információt fog gyűjteni az eszköz jelenlegi állapotáról, amelyet a rendszer e-mailben fog elküldeni. Kérjük, legyen türelemmel, amíg a hibajelentés elkészül, és küldhető állapotba kerül."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktív jelentés"</string>
@@ -262,8 +264,10 @@
<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">"Biztonsági üzemmód"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Átváltás személyes profilra"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Átváltás munkaprofilra"</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">"Névjegyek"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"hozzáférés a névjegyekhez"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Engedélyezi a(z) <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> számára, hogy hozzáférjen a névjegyekhez"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lehetővé teszi az alkalmazás számára, hogy hozzáférjen az eszköz telefonálási funkcióihoz. Az engedéllyel rendelkező alkalmazás meghatározhatja a telefonszámot és eszközazonosítókat, hogy egy hívás aktív-e, valamint híváskor a másik fél telefonszámát."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"rendszeren keresztüli hívásirányítás"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"A telefonálási élmény javítása érdekében lehetővé teszi az alkalmazás számára a rendszeren keresztüli hívásirányítást."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"telefonszámok olvasása"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Engedélyezi az alkalmazás számára az eszköz telefonszámaihoz való hozzáférést."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"táblagép alvás üzemmódjának megakadályozása"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Túl lassan húzta az ujját. Próbálkozzon újra."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nem sikerült felismerni"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Az ujjlenyomathoz szükséges hardver nem érhető el."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Az ujjlenyomat nem tárolható. Távolítson el egy meglévő ujjlenyomatot."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Az ujjlenyomat-beolvasási műveletkor időtúllépés történt. Próbálkozzon újra."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ujjlenyomattal kapcsolatos művelet megszakítva"</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Túl sok próbálkozás. Próbálja újra később."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Túl sok próbálkozás. Ujjlenyomat-érzékelő letiltva."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Próbálkozzon újra."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Megnyitás"</string>
<string name="sms" msgid="4560537514610063430">"Üzenet"</string>
<string name="add_contact" msgid="7867066569670597203">"Hozzáadás"</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">"Kevés a szabad terület"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Előfordulhat, hogy néhány rendszerfunkció nem működik."</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nincs elegendő tárhely a rendszerhez. Győződjön meg arról, hogy rendelkezik 250 MB szabad területtel, majd kezdje elölről."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Nyílt Wi-Fi hálózat érhető el</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Nyílt Wi-Fi-hálózathoz kapcsolódhat"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Kapcsolódás nyílt Wi‑Fi-hálózathoz…"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Sikeres kapcsolódás a Wi-Fi-hálózathoz"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nem sikerült kapcsolódni a Wi‑Fi-hálózathoz"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"A Wi-Fi automatikusan bekapcsol"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Amikor jó minőségű mentett hálózat közelében tartózkodik"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ne kapcsolódjon vissza"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi automatikusan bekapcsolva"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Ön a következő mentett hálózat közelében tartózkodik: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Bejelentkezés Wi-Fi hálózatba"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Bejelentkezés a hálózatba"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g>-tal túllépte a korlátot."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Háttéradatok korlátozva"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Koppintson az eltávolításhoz."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Nagymértékű adathasználat"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Adathasználata az elmúlt napokban nagyobb a szokásosnál. Koppintson az adathasználati adatok és a beállítások megtekintéséhez."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Biztonsági tanúsítvány"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"A tanúsítvány érvényes."</string>
<string name="issued_to" msgid="454239480274921032">"Kiállítva a következőnek:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Eddig: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Eddig: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ez a következő ébresztés)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Amíg ki nem kapcsolja a „Ne zavarjanak” lehetőséget"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Kikapcsolásig"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Amíg ki nem kapcsolja a „Ne zavarjanak” lehetőséget"</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">"Összecsukás"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Minden nyelv"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Minden régió"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Keresés"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Bekapcsolja a munka módot?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Bekapcsolja a munkaprofilt, beleértve az alkalmazásokat, a háttérben való szinkronizálást és a kapcsolódó funkciókat"</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">"Bekapcsolás"</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">"Új üzenetei érkeztek"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"SMS-alkalmazás megnyitása a megtekintéshez"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Egyes funkciók korlátozva lehetnek"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nem sikerült visszaállítani a parancsikont, mert az alkalmazás nem támogatja a biztonsági mentést és visszaállítást"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nem sikerült visszaállítani a parancsikont, mert az alkalmazás-aláírás nem egyezik"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nem sikerült visszaállítani a parancsikont"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"A parancsikon le van tiltva"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"A(z) <xliff:g id="APP_0">%1$s</xliff:g> alkalmazás részleteket szeretne megjeleníteni a(z) <xliff:g id="APP_2">%2$s</xliff:g> alkalmazásból"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Szerkesztés"</string>
</resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 1218b48..0b7b7d09 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Հեռուստացույցի ընտրանքներ"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Էկրանի պատկեր"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Գրել սխալի զեկույց"</string>
<string name="bugreport_message" msgid="398447048750350456">"Սա տեղեկություններ կհավաքագրի ձեր սարքի առկա կարգավիճակի մասին և կուղարկի այն էլեկտրոնային նամակով: Որոշակի ժամանակ կպահանջվի վրիպակի մասին զեկուցելու պահից սկսած մինչ ուղարկելը: Խնդրում ենք փոքր-ինչ համբերատար լինել:"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Ինտերակտիվ զեկույց"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"Անցնել անհատական պրոֆիլին"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Անցնել աշխատանքային պրոֆիլին"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Թույլ տալ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> հավելվածին օգտագործել ձեր կոնտակտները"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Թույլ է տալիս հավելվածին օգտագործել սարքի հեռախոսային գործիքները: Այս թույլտվությունը հավելվածին հնարավորություն է տալիս որոշել հեռախոսահամարը և սարքի ID-ները, արդյոք զանգը ակտիվ է և միացված զանգի հեռակա հեռախոսահամարը:"</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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Չափից շատ փորձ եք կատարել: Մատնահետքերի սկաներն անջատվել է:"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Փորձեք նորից:"</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Բացել"</string>
<string name="sms" msgid="4560537514610063430">"SMS գրել"</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">"Համակարգի համար բավարար հիշողություն չկա: Համոզվեք, որ ունեք 250ՄԲ ազատ տարածություն և վերագործարկեք:"</string>
@@ -1114,6 +1131,8 @@
<item quantity="other">Հասանելի են չպաշտպանված Wi-Fi ցանցեր</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Միացեք բաց Wi‑Fi ցանցին"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Միացում բաց Wi‑Fi ցանցին"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Միացել է Wi‑Fi ցանցին"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Չհաջողվեց միանալ Wi‑Fi ցանցին"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi-ը միացել է ավտոմատ կերպով"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Դուք գտնվում եք պահված ցանցի մոտակայքում՝ <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Մուտք գործեք Wi-Fi ցանց"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Մուտք գործեք ցանց"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"Անվտանգության վկայական"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Այս վկայականը վավեր է:"</string>
<string name="issued_to" msgid="454239480274921032">"Թողարկվել է`"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Մինչև չանջատեք «Չանհանգստացնել» գործառույթը"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Մինչև դուք չանջատեք"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Միացնե՞լ աշխատանքային ռեժիմը։"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Սա կմիացնի ձեր աշխատանքային պրոֆիլը, այդ թվում նաև հավելվածները, ֆոնային համաժամեցումը և առնչվող գործառույթները"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Որոշ գործառույթներ կարող են սահմանափակված լինել"</string>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> հավելվածն ուզում է ցուցադրել հատվածներ <xliff:g id="APP_2">%2$s</xliff:g> հավելվածից"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Փոփոխել"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index e3df0c8..a93d333 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organisasi mengelola perangkat ini dan mungkin memantau traffic jaringan. Tap untuk melihat detailnya."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Perangkat akan dihapus"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Aplikasi admin tidak dapat digunakan. Kini, perangkat Anda akan dihapus.\n\nJika ada pertanyaan, hubungi admin organisasi."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Fitur pencetakan dinonaktifkan oleh <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Saya"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opsi tablet"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opsi TV"</string>
@@ -263,8 +264,8 @@
<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">"Mode aman"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Beralih ke Pribadi"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Beralih ke Kantor"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Beralih ke profil pribadi"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Beralih ke profil kerja"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontak"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"mengakses kontak"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Izinkan <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> mengakses kontak"</string>
@@ -416,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Memungkinkan aplikasi mengakses fitur telepon perangkat. Izin ini memungkinkan aplikasi menentukan nomor telepon dan ID perangkat, apakah suatu panggilan aktif atau tidak, dan nomor jarak jauh yang tersambung oleh sebuah panggilan."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"sambungkan panggilan telepon melalui sistem"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Mengizinkan aplikasi menyambungkan panggilan telepon melalui sistem untuk menyempurnakan pengalaman menelepon."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"membaca nomor telepon"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Mengizinkan aplikasi mengakses nomor telepon perangkat."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"cegah tablet dari tidur"</string>
@@ -485,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Jari digerakkan terlalu lambat. Coba lagi."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Tidak dikenali"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware sidik jari tidak tersedia."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sidik jari tidak dapat disimpan. Hapus sidik jari yang ada."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Waktu sidik jari habis. Coba lagi."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operasi sidik jari dibatalkan."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Operasi sidik jari dibatalkan oleh pengguna."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Terlalu banyak upaya. Coba lagi nanti."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Terlalu sering dicoba. Sensor sidik jari dinonaktifkan."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Coba lagi."</string>
@@ -990,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Buka"</string>
<string name="sms" msgid="4560537514610063430">"Pesan"</string>
<string name="add_contact" msgid="7867066569670597203">"Tambahkan"</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">"Ruang penyimpanan hampir habis"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Beberapa fungsi sistem mungkin tidak dapat bekerja"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Penyimpanan tidak cukup untuk sistem. Pastikan Anda memiliki 250 MB ruang kosong, lalu mulai ulang."</string>
@@ -1115,6 +1128,8 @@
<item quantity="one">Jaringan Wi-Fi terbuka tersedia</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Hubungkan ke jaringan Wi-Fi terbuka"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Menghubungkan ke jaringan Wi-Fi terbuka"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Terhubung ke jaringan Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Tidak dapat menghubungkan ke jaringan Wi‑Fi"</string>
@@ -1412,6 +1427,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> melebihi batas yang ditentukan."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Data latar belakang dibatasi"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Ketuk untuk menghapus batasan."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Penggunaan data yang besar"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Penggunaan data selama beberapa hari terakhir lebih besar dari biasanya. Tap untuk melihat penggunaan dan setelan."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Sertifikat keamanan"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Sertifikat ini valid."</string>
<string name="issued_to" msgid="454239480274921032">"Diterbitkan ke:"</string>
@@ -1688,7 +1705,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Hingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarm berikutnya)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Hingga Anda menonaktifkan status Jangan Ganggu"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Sampai Anda menonaktifkannya"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hingga status Jangan Ganggu dinonaktifkan"</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">"Ciutkan"</string>
@@ -1737,9 +1754,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Semua bahasa"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Semua wilayah"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Telusuri"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Aktifkan mode kerja?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Tindakan ini akan mengaktifkan profil kerja, termasuk aplikasi, sinkronisasi latar belakang, dan fitur terkait"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Aktifkan profil kerja?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Aplikasi kerja, notifikasi, data, dan fitur profil kerja lainnya akan diaktifkan"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Aktifkan"</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">"Ada pesan baru"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Buka aplikasi SMS untuk melihat"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Beberapa fungsi mungkin terbatas"</string>
@@ -1811,7 +1832,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Tidak dapat memulihkan pintasan karena tanda tangan aplikasi tidak cocok"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Tidak dapat memulihkan pintasan."</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Pintasan dinonaktifkan"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Uninstal"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Tetap luncurkan"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Uninstal aplikasi berbahaya?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> ingin menampilkan potongan <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Edit"</string>
</resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 40bf34c..b5462eb 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Fyrirtækið þitt stjórnar þessu tæki og kann að fylgjast með netnotkun. Ýttu hér til að fá upplýsingar."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Tækið verður hreinsað"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Ekki er hægt að nota stjórnunarforritið. Tækinu verður eytt.\n\nEf spurningar vakna skaltu hafa samband við kerfisstjóra fyrirtækisins."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"<xliff:g id="OWNER_APP">%s</xliff:g> lokaði á prentun."</string>
<string name="me" msgid="6545696007631404292">"Ég"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Valkostir spjaldtölvu"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Sjónvarpsvalkostir"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Neyðarsímtal"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Villutilkynning"</string>
<string name="global_action_logout" msgid="935179188218826050">"Ljúka lotu"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Skjámynd"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Útbúa villutilkynningu"</string>
<string name="bugreport_message" msgid="398447048750350456">"Þetta safnar upplýsingum um núverandi stöðu tækisins til að senda með tölvupósti. Það tekur smástund frá því villutilkynningin er ræst og þar til hún er tilbúin til sendingar – sýndu biðlund."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Gagnvirk skýrsla"</string>
@@ -262,8 +264,10 @@
<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">"Örugg stilling"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android kerfið"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Skipta yfir í persónulegt snið"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Skipta yfir í vinnusnið"</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">"Tengiliðir"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"fá aðgang að tengiliðunum þínum"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Veita <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> aðgang að tengiliðunum þínum"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Leyfir forriti að fá aðgang að símaeiginleikum tækisins. Þessi heimild gerir forritinu kleift að komast að símanúmeri og auðkennum tækisins, hvort símtal er í gangi og símanúmeri viðmælanda í símtali."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"senda símtöl gegnum kerfið"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Heimilar forritinu að senda símtöl sín gegnum kerfið til að bæta gæði símtalsins."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"lesa símanúmer"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Veitir forritinu aðgang að símanúmerum tækisins."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"koma í veg fyrir að spjaldtölvan fari í biðstöðu"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Fingurinn hreyfðist of hægt. Reyndu aftur."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Þekktist ekki"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingrafarsvélbúnaður ekki til staðar."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ekki er hægt að vista fingrafarið. Fjarlægðu eitthvert af fingraförunum sem fyrir eru."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tímamörk runnu út fyrir fingrafar. Reyndu aftur."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hætt við fingrafarsaðgerð."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Of margar tilraunir. Reyndu aftur síðar."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Of margar tilraunir. Fingrafaralesari gerður óvirkur."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Reyndu aftur."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Opna"</string>
<string name="sms" msgid="4560537514610063430">"Skilaboð"</string>
<string name="add_contact" msgid="7867066569670597203">"Bæta við"</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">"Geymslurýmið er senn á þrotum"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Sumir kerfiseiginleikar kunna að vera óvirkir"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Ekki nægt geymslurými fyrir kerfið. Gakktu úr skugga um að 250 MB séu laus og endurræstu."</string>
@@ -1114,6 +1131,8 @@
<item quantity="other">Opin Wi-Fi net í boði</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Tengjast opnu Wi-Fi neti"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Tengist opnu Wi‑Fi neti"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Tengt við Wi‑Fi net"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Ekki hægt að tengjast Wi-Fi neti"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Kveikt verður sjálfkrafa á Wi‑Fi"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Þegar þú ert nálægt vistuðu hágæðaneti"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ekki kveikja aftur"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Sjálfkrafa kveikt á Wi-Fi"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Þú ert nálægt vistuðu neti: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Skrá inn á Wi-Fi net"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Skrá inn á net"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1410,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> yfir tilgreindum mörkum."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Bakgrunnsgögn takmörkuð"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Ýttu til að eyða takmörkun."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Mikil gagnanotkun"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Gagnanotkun þín síðustu daga er meiri en venjulega. Ýttu til að skoða upplýsingar um notkun og stillingar."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Öryggisvottorð"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Þetta vottorð er gilt."</string>
<string name="issued_to" msgid="454239480274921032">"Gefið út fyrir:"</string>
@@ -1686,7 +1709,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Þangað til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (næsta viðvörun)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Þar til þú slekkur á „Ónáðið ekki“"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Þar til þú slekkur"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Þar til þú slekkur á „Ónáðið ekki“"</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">"Minnka"</string>
@@ -1735,9 +1758,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Öll tungumál"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Öll svæði"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Leita"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Viltu kveikja á vinnustillingu?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Þetta slekkur á vinnusniðinu þínu, þar á meðal forritum, samstillingu í bakgrunni og tengdum eiginleikum"</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">"Kveikja"</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">"Þú ert með ný skilaboð"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Opnaðu SMS-forritið til að skoða"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Sum virkni kann að vera takmörkuð"</string>
@@ -1808,6 +1837,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Ekki var hægt að endurheimta flýtileið vegna þess að forritið styður ekki öryggisafritun og endurheimt"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ekki var hægt að endurheimta flýtileið vegna þess að undirskriftir forrita passa ekki saman"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Ekki var hægt að endurheimta flýtileið"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Flýtileið er óvirk"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> vill sýna sneiðar úr <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Breyta"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index c1ef402..8807282 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Questo dispositivo è gestito dalla tua organizzazione, che potrebbe monitorare il traffico di rete. Tocca per i dettagli."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Il dispositivo verrà resettato"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Impossibile usare l\'app di amministrazione. Il dispositivo verrà resettato.\n\nPer eventuali domande, contatta l\'amministratore della tua organizzazione."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Stampa disattivata da <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Io"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opzioni tablet"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opzioni TV"</string>
@@ -263,8 +264,8 @@
<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">"Modalità provvisoria"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Passa al profilo personale"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Passa al profilo di lavoro"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Passa al profilo personale"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Passa a profilo di lavoro"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatti"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"accedere ai contatti"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Consenti a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere ai tuoi contatti"</string>
@@ -416,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Consente all\'applicazione di accedere alle funzioni telefoniche del dispositivo. Questa autorizzazione consente all\'applicazione di determinare il numero di telefono e gli ID dei dispositivi, se una chiamata è attiva e il numero remoto connesso da una chiamata."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"indirizzamento delle chiamate tramite il sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Consente all\'app di indirizzare le proprie chiamate tramite il sistema al fine di migliorare l\'esperienza di chiamata."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"lettura dei numeri di telefono"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Consente all\'app di accedere ai numeri di telefono del dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"disattivazione stand-by del tablet"</string>
@@ -485,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Movimento del dito troppo lento. Riprova."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Non riconosciuto"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware per l\'impronta digitale non disponibile."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossibile memorizzare l\'impronta digitale. Rimuovi un\'impronta esistente."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timeout impronta digitale. Riprova."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operazione associata all\'impronta digitale annullata."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Operazione associata all\'impronta digitale annullata dall\'utente."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Troppi tentativi. Riprova più tardi."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Troppi tentativi. Sensore di impronte digitali disattivato."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Riprova."</string>
@@ -990,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Apri"</string>
<string name="sms" msgid="4560537514610063430">"Invia messaggio"</string>
<string name="add_contact" msgid="7867066569670597203">"Aggiungi"</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">"Spazio di archiviazione in esaurimento"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Alcune funzioni di sistema potrebbero non funzionare"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Memoria insufficiente per il sistema. Assicurati di avere 250 MB di spazio libero e riavvia."</string>
@@ -1115,6 +1128,8 @@
<item quantity="one">Apri rete Wi-Fi disponibile</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Stabilisci la connessione per aprire la rete Wi‑Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connessione per aprire la rete Wi‑Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Connessione alla rete Wi-Fi stabilita"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Impossibile connettersi alla rete Wi-Fi"</string>
@@ -1412,6 +1427,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> oltre il limite specificato."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Dati in background limitati"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Tocca per rimuovere le limitazioni."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Massiccio utilizzo dei dati"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"L\'utilizzo dei dati negli ultimi giorni è superiore al normale. Tocca per visualizzare l\'utilizzo e le impostazioni."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificato di sicurezza"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Questo certificato è valido."</string>
<string name="issued_to" msgid="454239480274921032">"Rilasciato a:"</string>
@@ -1688,7 +1705,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Fino a <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Fino a <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (prossima sveglia)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Fino alla disattivazione di Non disturbare"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Fino alla disattivazione"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Fino alla disattivazione di Non disturbare"</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">"Comprimi"</string>
@@ -1737,9 +1754,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Tutte le lingue"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Tutte le aree geografiche"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Cerca"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Attivare la modalità Lavoro?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Verrà attivato il profilo di lavoro, incluse app, sincronizzazione in background e funzioni correlate"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Attivare il profilo di lavoro?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Le tue app di lavoro, le notifiche, i dati e altri elementi del profilo di lavoro saranno attivati."</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Attiva"</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">"Hai nuovi messaggi"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Apri l\'app SMS per la visualizzazione"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Funzioni potenzial. limitate"</string>
@@ -1811,7 +1832,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Impossibile ripristinare la scorciatoia perché la firma dell\'app non corrisponde"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Impossibile ripristinare la scorciatoia"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"La scorciatoia è disattivata"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Disinstalla"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Avvia comunque"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Disinstallare l\'app dannosa?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"L\'app <xliff:g id="APP_0">%1$s</xliff:g> vuole mostrare porzioni dell\'app <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Modifica"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 7c0ce3a..d14e2aa 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -185,6 +185,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"אפשרויות טלוויזיה"</string>
@@ -221,6 +222,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"צילום מסך"</string>
<string name="bugreport_title" msgid="2667494803742548533">"שלח דיווח על באג"</string>
<string name="bugreport_message" msgid="398447048750350456">"פעולה זו תאסוף מידע על מצב המכשיר הנוכחי שלך על מנת לשלוח אותו כהודעת אימייל. היא תימשך זמן קצר מרגע פתיחת דיווח הבאג ועד לשליחת ההודעה בפועל. אנא המתן בסבלנות."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"דוח אינטראקטיבי"</string>
@@ -268,8 +270,10 @@
<string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="RIGHT_SIDE">%2$s</xliff:g>, <xliff:g id="LEFT_SIDE">%1$s</xliff:g>"</string>
<string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
<string name="android_system_label" msgid="6577375335728551336">"מערכת Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"עבור ל\'אישי\'"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"עבור ל\'עבודה\'"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"האפליקציה <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> תקבל הרשאת גישה לאנשי הקשר שלך"</string>
@@ -421,6 +425,10 @@
<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>
@@ -490,10 +498,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"יותר מדי ניסיונות. חיישן טביעות האצבע הושבת."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"נסה שוב."</string>
@@ -1029,6 +1040,12 @@
<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">"אין מספיק שטח אחסון עבור המערכת. ודא שיש לך שטח פנוי בגודל 250MB התחל שוב."</string>
@@ -1158,6 +1175,8 @@
<item quantity="one">יש רשת Wi-Fi פתוחה וזמינה</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"התחברות לרשת Wi‑Fi פתוחה"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"מתחבר לרשת Wi‑Fi פתוחה"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"מחובר לרשת Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"לא ניתן היה להתחבר לרשת Wi-Fi"</string>
@@ -1167,6 +1186,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"רשת Wi‑Fi הופעלה אוטומטית"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"המיקום הנוכחי שלך הוא בקרבת הרשת השמורה: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"היכנס לרשת Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"היכנס לרשת"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1455,6 +1476,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"אישור אבטחה"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"אישור זה תקף."</string>
<string name="issued_to" msgid="454239480274921032">"הוקצה ל:"</string>
@@ -1751,7 +1774,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"עד שתכבה את \'נא לא להפריע\'"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"עד הכיבוי"</string>
<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>
@@ -1802,9 +1825,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"להפעיל את \'מצב עבודה\'?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"פעולה זו תפעיל את הפרופיל העבודה שלך, כולל אפליקציות, סנכרון ברקע ותכונות קשורות"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"ייתכן שחלק מהפונקציונליות תהיה מוגבלת"</string>
@@ -1877,6 +1906,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> רוצה להציג חלקים מ-<xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"עריכה"</string>
</resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 45ed466..663aa06 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"ტელევიზორის პარამეტრები"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"ეკრანის ანაბეჭდი"</string>
<string name="bugreport_title" msgid="2667494803742548533">"შექმენით შეცდომის ანგარიში"</string>
<string name="bugreport_message" msgid="398447048750350456">"იგი შეაგროვებს ინფორმაციას თქვენი მოწყობილობის ამჟამინდელი მდგომარეობის შესახებ, რათა ის ელფოსტის შეტყობინების სახით გააგზავნოს. ხარვეზის ანგარიშის მომზადებასა და შეტყობინების გაგზავნას გარკვეული დრო სჭირდება. გთხოვთ, მოითმინოთ."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ინტერაქტიული ანგარიში"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"პირად პროფილზე გადართვა"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"სამსახურის პროფილზე გადართვა"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის</b> თქვენს კონტაქტებზე წვდომის ნების დართვა"</string>
@@ -415,6 +419,10 @@
<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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"დაფიქსირდა მეტისმეტად ბევრი მცდელობა. თითის ანაბეჭდის სენსორი გათიშულია."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ხელახლა სცადეთ"</string>
@@ -989,6 +1000,12 @@
<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">"სისტემისათვის საკმარისი საცავი არ არის. დარწმუნდით, რომ იქონიოთ სულ მცირე 250 მბაიტი თავისუფალი სივრცე და დაიწყეთ ხელახლა."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">ხელმისაწვდომია ღია Wi-Fi ქსელი</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"დაუკავშირდით ღია Wi‑Fi ქსელს"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"მიმდინარეობს ღია Wi‑Fi ქსელთან დაკავშირება"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi ქსელთან დაკავშირება წარმატებით მოხერხდა"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi ქსელთან დაკავშირება ვერ მოხერხდა"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi ავტომატურად ჩაირთო"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"თქვენ შენახული ქსელის მახლობლად ხართ: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi ქსელთან დაკავშირება"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ქსელში შესვლა"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"ლიმიტი გადაჭარბებულია <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="ssl_certificate" msgid="6510040486049237639">"უსაფრთხოების სერტიფიკატი"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ეს სერტიფიკატი სწორია."</string>
<string name="issued_to" msgid="454239480274921032">"მიეცა:"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"სანამ გამორთავთ „არ შემაწუხოთ“ ფუნქციას"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"გამორთვამდე"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"ჩაირთოს სამსახურის რეჟიმი?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"ეს ქმედება ჩართავს თქვენს სამსახურის პროფილს, მათ შორის, აპებს, ფონურ სინქრონიზაციას და სხვა დაკავშირებულ ფუნქციებს"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"ზოგიერთი ფუნქცია შეიძლება შეიზღუდოს"</string>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g>-ს სურს, გაჩვენოთ <xliff:g id="APP_2">%2$s</xliff:g>-ის ფრაგმენტები"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"რედაქტირება"</string>
</resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 51c5147..a65286b 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"ТД опциялары"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Скриншот"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Қате туралы есеп құру"</string>
<string name="bugreport_message" msgid="398447048750350456">"Құрылғының қазіргі күйі туралы ақпаратты жинап, электрондық хабармен жібереді. Есеп әзір болғанша біраз уақыт кетеді, шыдай тұрыңыз."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивті есеп"</string>
@@ -262,8 +264,8 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"Жекеге ауысу"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Жұмысқа ауысу"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Жеке профильге ауысу"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Жұмыс профиліне ауысу"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Контактілер"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"контактілерге кіру"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"\"<xliff:g id="APP_NAME">%1$s</xliff:g>\" қолданбасына контактілерге кіруге рұқсат беріңіз"</string>
@@ -415,6 +417,10 @@
<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>
@@ -484,10 +490,12 @@
<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>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Пайдаланушы саусақ ізі операциясынан бас тартты."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Талпыныстар тым көп. Кейінірек қайталап көріңіз."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Тым көп әрекет жасалды. Саусақ ізін оқу сканері өшірілді."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Әрекетті қайталаңыз."</string>
@@ -989,6 +997,12 @@
<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">"Жүйе үшін жад жеткіліксіз. 250 МБ бос орын бар екенін тексеріп, қайта іске қосыңыз."</string>
@@ -1114,6 +1128,8 @@
<item quantity="one">Ашық Wi-Fi желісі қол жетімді</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Ашық Wi‑Fi желісіне қосылу"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ашық Wi‑Fi желісіне қосылуда"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi желісіне қосылды"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi желісіне қосылмады"</string>
@@ -1123,6 +1139,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi автоматты түрде қосылды"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Сақталған желінің маңайындасыз: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi желісіне кіру"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Желіге кіру"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1410,6 +1428,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Анықталған уақтыттан <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="ssl_certificate" msgid="6510040486049237639">"Қауіпсіздік сертификаты"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Бұл сертификат жарамды."</string>
<string name="issued_to" msgid="454239480274921032">"Кімге берілген:"</string>
@@ -1686,7 +1706,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"\"Мазаламау\" режимін өшіргенше"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Өшірілгенге дейін"</string>
<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>
@@ -1735,9 +1755,13 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Жұмыс режимін қосу керек пе?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Бұл жұмыс профилін, соның ішінде қолданбаларды, фондық синхрондауды және қатысты мүмкіндіктерді қосады"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Жұмыс профилі қосылсын ба?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Жұмыс қолданбалары, хабарландырулар, деректер және басқа да жұмыс профильдерінің мүмкіндіктері қосылады"</string>
<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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Кейбір функциялар істемеуі мүмкін"</string>
@@ -1808,6 +1832,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> қолданбасы <xliff:g id="APP_2">%2$s</xliff:g> қолданбасының үзінділерін көрсеткісі келеді"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Өзгерту"</string>
</resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index c266416..bccd96d 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"ជម្រើសទូរទស្សន៍"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"រូបថតអេក្រង់"</string>
<string name="bugreport_title" msgid="2667494803742548533">"យករបាយការណ៍កំហុស"</string>
<string name="bugreport_message" msgid="398447048750350456">"វានឹងប្រមូលព័ត៌មានអំពីស្ថានភាពឧបករណ៍របស់អ្នក ដើម្បីផ្ញើជាសារអ៊ីមែល។ វានឹងចំណាយពេលតិចពីពេលចាប់ផ្ដើមរបាយការណ៍រហូតដល់ពេលវារួចរាល់ដើម្បីផ្ញើ សូមអត់ធ្មត់។"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"របាយការណ៍អន្តរកម្ម"</string>
@@ -262,8 +264,8 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"ប្តូរទៅផ្ទាល់ខ្លួន"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"ប្តូរទៅការងារ"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"ប្តូរទៅកម្រងព័ត៌មានផ្ទាល់ខ្លួន"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"ប្តូរទៅកម្រងព័ត៌មានការងារ"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"ទំនាក់ទំនង"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"ចូលប្រើទំនាក់ទំនងរបស់អ្នក"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"អនុញ្ញាតឲ្យ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ចូលប្រើទំនាក់ទំនងរបស់អ្នក"</string>
@@ -415,6 +417,10 @@
<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>
@@ -484,10 +490,12 @@
<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>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ប្រតិបត្តិការស្នាមម្រាមដៃត្រូវបានបោះបង់ដោយអ្នកប្រើប្រាស់។"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ព្យាយាមចូលច្រើនពេកហើយ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។"</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ព្យាយាមចូលច្រើនដងពេកហើយ។ ឧបករណ៍ចាប់ស្នាមម្រាមដៃត្រូវបានបិទ។"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ព្យាយាមម្ដងទៀត។"</string>
@@ -989,6 +997,12 @@
<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">"មិនមានទំហំផ្ទុកគ្រប់គ្រាន់សម្រាប់ប្រព័ន្ធ។ សូមប្រាកដថាអ្នកមានទំហំទំនេរ 250MB ហើយចាប់ផ្ដើមឡើងវិញ។"</string>
@@ -1116,6 +1130,8 @@
<item quantity="one">បើកបណ្តាញ Wi-Fi ដែលមាន</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"ភ្ជាប់ទៅបណ្តាញ Wi‑Fi ចំហ"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"កំពុងភ្ជាប់ទៅបណ្តាញ Wi‑Fi ចំហ"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"បានភ្ជាប់ទៅបណ្តាញ Wi‑Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"មិនអាចភ្ជាប់ទៅបណ្តាញ Wi‑Fi បានទេ"</string>
@@ -1125,6 +1141,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi បានបើកដោយស្វ័យប្រវត្តិ"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"អ្នកនៅជិតបណ្តាញដែលបានរក្សាទុក៖ <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<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) -->
@@ -1411,6 +1429,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"វិញ្ញាបនបត្រសុវត្ថិភាព"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"វិញ្ញាបនបត្រនេះត្រឹមត្រូវ។"</string>
<string name="issued_to" msgid="454239480274921032">"បានចេញឲ្យ៖"</string>
@@ -1687,7 +1707,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"រហូតទាល់តែអ្នកបិទ កុំរំខាន"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"រហូតទាល់តែអ្នកបិទ"</string>
<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>
@@ -1736,9 +1756,13 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"បើកមុខងារការងារ?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"វានឹងបើកកម្រងព័ត៌មានការងាររបស់អ្នក រួមទាំងកម្មវិធី សមកាលកម្មផ្ទៃខាងក្រោយ និងមុខងារដែលពាក់ព័ន្ធផងដែរ"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"បើកកម្រងព័ត៌មានការងារ?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"កម្មវិធីការងារ ការជូនដំណឹង ទិន្នន័យ និងមុខងារកម្រងព័ត៌មានការងារផ្សេងទៀតរបស់អ្នកនឹងត្រូវបានបើក"</string>
<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>
<string name="user_encrypted_title" msgid="9054897468831672082">"លទ្ធភាពប្រើមុខងារមួយចំនួនអាចត្រូវបាកម្រិត"</string>
@@ -1809,6 +1833,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> ចង់បង្ហាញស្ថិតិប្រើប្រាស់របស់ <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"កែសម្រួល"</string>
</resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index b9539ea..ee690b5 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"ಟಿವಿ ಆಯ್ಕೆಗಳು"</string>
@@ -217,8 +218,7 @@
<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="global_action_screenshot" msgid="8329831278085426283">"ಸ್ಕ್ರೀನ್ಶಾಟ್"</string>
<string name="bugreport_title" msgid="2667494803742548533">"ದೋಷ ವರದಿ ರಚಿಸಿ"</string>
<string name="bugreport_message" msgid="398447048750350456">"ನಿಮ್ಮ ಸಾಧನದ ಪ್ರಸ್ತುತ ಸ್ಥಿತಿಯ ಕುರಿತು ಮಾಹಿತಿಯನ್ನು ಸಂಗ್ರಹಿಸಿಕೊಳ್ಳುವುದರ ಜೊತೆ ಇ-ಮೇಲ್ ರೂಪದಲ್ಲಿ ನಿಮಗೆ ರವಾನಿಸುತ್ತದೆ. ಇದು ದೋಷ ವರದಿಯನ್ನು ಪ್ರಾರಂಭಿಸಿದ ಸಮಯದಿಂದ ಅದನ್ನು ಕಳುಹಿಸುವವರೆಗೆ ಸ್ವಲ್ಪ ಸಮಯವನ್ನು ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ; ದಯವಿಟ್ಟು ತಾಳ್ಮೆಯಿಂದಿರಿ."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ಪರಸ್ಪರ ಸಂವಹನ ವರದಿ"</string>
@@ -264,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"ವೈಯಕ್ತಿಕಗೆ ಬದಲಿಸಿ"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"ಕೆಲಸಕ್ಕೆ ಬದಲಿಸು"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಪ್ರವೇಶಿಸಲು <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ಗೆ ಅನುಮತಿಸಿ"</string>
@@ -417,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ಸಾಧನದ ಫೋನ್ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ಫೋನ್ ಸಂಖ್ಯೆ ಮತ್ತು ಸಾಧನದ ID ಗಳನ್ನು ನಿರ್ಧರಿಸಲು, ಕರೆಯು ಸಕ್ರಿಯವಾಗಿದೆಯೇ ಮತ್ತು ಕರೆಯ ಮೂಲಕ ರಿಮೋಟ್ ಸಂಖ್ಯೆಯು ಸಂಪರ್ಕಗೊಂಡಿವೆಯೇ ಎಂಬುದನ್ನೂ ನಿರ್ಧರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಕಲ್ಪಿಸುತ್ತದೆ."</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>
@@ -486,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಫಿಂಗರ್ ಫ್ರಿಂಟ್ ಸೆನ್ಸಾರ್ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
@@ -991,6 +1000,12 @@
<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">"ಸಿಸ್ಟಂನಲ್ಲಿ ಸಾಕಷ್ಟು ಸಂಗ್ರಹಣೆಯಿಲ್ಲ. ನೀವು 250MB ನಷ್ಟು ಖಾಲಿ ಸ್ಥಳವನ್ನು ಹೊಂದಿರುವಿರಾ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ ಹಾಗೂ ಮರುಪ್ರಾರಂಭಿಸಿ."</string>
@@ -1116,6 +1131,8 @@
<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>
@@ -1125,10 +1142,8 @@
<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_wakeup_enabled_title" msgid="6534603733173085309">"ವೈ-ಫೈ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಆಗಿದೆ"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"ನೀವು ಉಳಿಸಿದ ನೆಟ್ವರ್ಕ್ನ ಸಮೀಪವಿರುವಿರಿ: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<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) -->
@@ -1416,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"ಭದ್ರತಾ ಪ್ರಮಾಣಪತ್ರ"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ಈ ಪ್ರಮಾಣಪತ್ರವು ಮಾನ್ಯವಾಗಿದೆ."</string>
<string name="issued_to" msgid="454239480274921032">"ಇವರಿಗೆ ನೀಡಲಾಗಿದೆ:"</string>
@@ -1692,7 +1709,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"ನೀವು ಆಫ್ ಮಾಡುವವರೆಗೂ ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"ನೀವು ಆಫ್ ಮಾಡುವವರೆಗೆ"</string>
<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>
@@ -1741,9 +1758,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"ಉದ್ಯೋಗ ಮೋಡ್ ಆನ್ ಮಾಡುವುದೇ?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"ಇದು ನಿಮ್ಮ ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಜೊತೆಗೆ ಅಪ್ಲಿಕೇಶನ್ಗಳು, ಹಿನ್ನೆಲೆ ಸಿಂಕ್ ಮತ್ತು ಸಂಬಂಧಿತ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆನ್ ಮಾಡುತ್ತದೆ"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"ಕೆಲವು ಕಾರ್ಯನಿರ್ವಹಣೆಗಳು ಸೀಮಿತವಾಗಿರಬಹುದು"</string>
@@ -1815,10 +1838,12 @@
<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 (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_2">%2$s</xliff:g> ಸ್ಲೈಸ್ಗಳನ್ನು <xliff:g id="APP_0">%1$s</xliff:g> ತೋರಿಸಲು ಬಯಸಿದೆ"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"ಎಡಿಟ್"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 221a233..b3a5ba6 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV 옵션"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"스크린샷"</string>
<string name="bugreport_title" msgid="2667494803742548533">"버그 신고"</string>
<string name="bugreport_message" msgid="398447048750350456">"현재 기기 상태에 대한 정보를 수집하여 이메일 메시지로 전송합니다. 버그 신고를 시작하여 전송할 준비가 되려면 약간 시간이 걸립니다."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"대화형 보고서"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"개인으로 전환"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"직장으로 전환"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>에서 내 연락처를 액세스하도록 허용합니다."</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"앱이 기기의 휴대전화 기능에 접근할 수 있도록 허용합니다. 이 권한을 사용하면 앱이 전화번호 및 기기의 ID, 활성 통화인지 여부, 통화가 연결된 원격 번호 등을 확인할 수 있습니다."</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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"시도 횟수가 너무 많습니다. 지문 센서가 사용 중지되었습니다."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"다시 시도해 보세요."</string>
@@ -989,6 +1000,12 @@
<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">"시스템의 저장 공간이 부족합니다. 250MB의 여유 공간이 확보한 후 다시 시작하세요."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">개방형 Wi-Fi 네트워크 사용 가능</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"공개 Wi‑Fi 네트워크에 연결"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"공개 Wi‑Fi 네트워크에 연결 중"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi 네트워크에 연결됨"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi 네트워크에 연결할 수 없음"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi가 자동으로 사용 설정됨"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"주변에 저장된 네트워크(<xliff:g id="NETWORK_SSID">%1$s</xliff:g>)가 있습니다"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi 네트워크에 로그인"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"네트워크에 로그인"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"보안 인증서"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"유효한 인증서입니다."</string>
<string name="issued_to" msgid="454239480274921032">"발급 대상:"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"알림 일시중지 기능을 사용 중지할 때까지"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"사용 중지할 때까지"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"작업 모드를 사용 설정하시겠습니까?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"앱, 백그라운드 동기화 및 관련 기능을 포함한 직장 프로필이 사용 설정됩니다."</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"일부 기능이 제한될 수 있습니다."</string>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g>에서 <xliff:g id="APP_2">%2$s</xliff:g>의 슬라이스를 표시하려고 합니다"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"수정"</string>
</resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 1bce491..6b4be9b 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Сыналгы параметрлери"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Скриншот"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Ката тууралуу билдирүү түзүү"</string>
<string name="bugreport_message" msgid="398447048750350456">"Ушуну менен түзмөгүңүздүн учурдагы абалы тууралуу маалымат топтолуп, электрондук почта аркылуу жөнөтүлөт. Отчет даяр болгуча бир аз күтө туруңуз."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивдүү кабар"</string>
@@ -262,8 +264,8 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"Жеке профилге которулуу"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Жумуш профилине которулуу"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Жеке профилге которулуу"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Жумуш профилине которулуу"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Байланыштар"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"байланыштарыңызды көрүүгө"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна байланыштарыңызды пайдалануу мүмкүнчүлүгүн бериңиз"</string>
@@ -415,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Колдонмого түзмөктүн чалуу мүмкүнчүлүктөрүнө жетки алуу уруксатын берет. Бул уруксат колдонмого, телефондун номурун, түзмөктүн ID-син, чалуунун абалын жана байланышта чыккан номурду аныктоого жол берет."</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>
@@ -484,10 +490,12 @@
<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>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Манжа изи менен аныктыгын текшерүүнү колдонуучу жокко чыгарды."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Аракеттер өтө көп болду. Кийинчерээк кайра аракет кылыңыз."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Өтө көп жолу аракет жасадыңыз. Манжа изинин сенсору өчүрүлдү."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Кайра бир аракеттениңиз."</string>
@@ -989,6 +997,12 @@
<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">"Тутумда сактагыч жетишсиз. 250МБ бош орун бар экенин текшерип туруп, өчүрүп күйгүзүңүз."</string>
@@ -1114,6 +1128,8 @@
<item quantity="one">Ачык Wi-Fi тармагы жеткиликтүү</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Ачык Wi‑Fi тармагына туташуу"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ачык Wi‑Fi тармагына туташууда"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Ачык Wi‑Fi тармагына туташты"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi-Fi тармагына туташпай калды"</string>
@@ -1123,6 +1139,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi автоматтык түрдө күйгүзүлдү"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Сакталган тармактын жанындасыз: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi түйүнүнө кирүү"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Тармакка кирүү"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1411,6 +1429,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Орнотулган чектөөдөн <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="ssl_certificate" msgid="6510040486049237639">"Коопсуздук тастыктамасы"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Бул тастыктама жарактуу."</string>
<string name="issued_to" msgid="454239480274921032">"Берилди:"</string>
@@ -1687,7 +1707,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"\"Тынчымды алба\" режими өчүрүлгөнгө чейин"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Бул функция өчүрүлгөнгө чейин"</string>
<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>
@@ -1727,8 +1747,8 @@
<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="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>
@@ -1736,9 +1756,13 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Жумуш режими иштетилсинби?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Ушуну менен жумуш профилиңиз, ошондой эле колдонмолор, фондо шайкештирүү жана ага байланыштуу функциялар иштетилет."</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Жумуш профили күйгүзүлсүнбү?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Жумуш колдонмолоруңуз, эскертмелериңиз, дайындарыңыз жана жумуш профилинин башка функциялары өчүрүлөт"</string>
<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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Айрым функциялар чектлши мүмкн"</string>
@@ -1809,6 +1833,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> колдонмосу <xliff:g id="APP_2">%2$s</xliff:g> үлгүлөрүн көрсөткөнү жатат"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Түзөтүү"</string>
</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 9f7a28f..088d44f 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"ທາງເລືອກໂທລະພາບ"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"ພາບໜ້າຈໍ"</string>
<string name="bugreport_title" msgid="2667494803742548533">"ໃຊ້ລາຍງານຂໍ້ບົກພ່ອງ"</string>
<string name="bugreport_message" msgid="398447048750350456">"ນີ້ຈະເປັນການເກັບກຳຂໍ້ມູນກ່ຽວກັບ ສະຖານະປັດຈຸບັນຂອງອຸປະກອນທ່ານ ເພື່ອສົ່ງເປັນຂໍ້ຄວາມທາງອີເມວ. ມັນຈະໃຊ້ເວລາໜ້ອຍນຶ່ງ ໃນການເລີ່ມຕົ້ນການລາຍງານຂໍ້ຜິດພາດ ຈົນກວ່າຈະພ້ອມທີ່ຈະສົ່ງໄດ້, ກະລຸນາລໍຖ້າ."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ລາຍງານແບບໂຕ້ຕອບ"</string>
@@ -262,8 +264,10 @@
<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">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"ລະບົບ Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"ສະລັບໄປໂປຣໄຟລ໌ສ່ວນຕົວ"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"ສະລັບໄປໂປຣໄຟລ໌ວຽ."</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"ອະນຸຍາດ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ໃຫ້ເຂົ້າເຖິງລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານ"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ອະນຸຍາດໃຫ້ແອັບຯ ເຂົ້າເຖິງຄວາມສາມາດການໂທລະສັບຂອງອຸປະກອນ. ການກຳນົດສິດນີ້ເຮັດໃຫ້ແອັບຯສາມາດກວດສອບເບີໂທລະສັບ ແລະ ID ຂອງອຸປະກອນ, ບໍ່ວ່າການໂທຈະຍັງດຳເນີນຢູ່ ແລະເບີປາຍທາງເຊື່ອມຕໍ່ຢູ່ຫຼືບໍ່ກໍຕາມ."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"route calls through the system"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Allows the app to route its calls through the system in order to improve the calling experience."</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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ພະຍາຍາມຫຼາຍເທື່ອເກີນໄປ. ລະບົບປິດການເຮັດວຽກຂອງເຊັນເຊີລາຍນິ້ວມືແລ້ວ."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ລອງໃໝ່ອີກຄັ້ງ."</string>
@@ -989,6 +1000,12 @@
<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">"ບໍ່ມີບ່ອນເກັບຂໍ້ມູນພຽງພໍສຳລັບລະບົບ. ກວດສອບໃຫ້ແນ່ໃຈວ່າທ່ານມີພື້ນທີ່ຫວ່າງຢ່າງໜ້ອຍ 250MB ແລ້ວລອງໃໝ່."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">ເປີດເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ແບບເປີດ"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"ກຳລັງເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ແລ້ວ"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ບໍ່ສາມາດເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ໄດ້"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"ເປີດໃຊ້ Wi‑Fi ອັດຕະໂນມັດແລ້ວ"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"ທ່ານຢູ່ໃກ້ເຄືອຂ່າຍທີ່ບັນທຶກໄວ້: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ລົງຊື່ເຂົ້າເຄືອຂ່າຍ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"ໃບຮັບຮອງຄວາມປອດໄພ"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ໃບຮັບຮອງບໍ່ຖືກຕ້ອງ."</string>
<string name="issued_to" msgid="454239480274921032">"ອອກໃຫ້ແກ່:"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"ຈົນກວ່າທ່ານຈະປິດການຫ້າມລົບກວນ"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"ຈົນກວ່າທ່ານຈະປິດ"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"ເປີດໂໝດບ່ອນເຮັດວຽກບໍ?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"ນີ້ຈະເປີດໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານ, ຮວມທັງແອັບ, ການຊິ້ງໃນພື້ນຫຼັງ ແລະ ຄຸນສົມບັດທີ່ກ່ຽວຈ້ອງ"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"ບາງຄວາມສາມາດນຳໃຊ້ອາດຈະຖືກຈຳກັດ"</string>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> ຕ້ອງການສະແດງ <xliff:g id="APP_2">%2$s</xliff:g> ສະໄລ້"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"ແກ້ໄຂ"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index e248f45..89d803c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -185,6 +185,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Šį įrenginį tvarko organizacija ir gali stebėti tinklo srautą. Palieskite, kad gautumėte daugiau informacijos."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Įrenginys bus ištrintas"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Administratoriaus programos negalima naudoti. Dabar įrenginys bus ištrintas.\n\nJei kyla klausimų, susisiekite su organizacijos administratoriumi."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Neleidžiama spausdinti (<xliff:g id="OWNER_APP">%s</xliff:g>)."</string>
<string name="me" msgid="6545696007631404292">"Aš"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Planšetinio kompiuterio parinktys"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV parinktys"</string>
@@ -269,8 +270,10 @@
<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">"Saugos režimas"</string>
<string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Perjungti į asmeninį režimą"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Perjungti į darbo režimą"</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">"Kontaktai"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"pasiekti kontaktus"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Suteikti <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> prieigą prie kontaktų"</string>
@@ -422,6 +425,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Leidžiama programai pasiekti telefono funkcijas įrenginyje. Šis leidimas suteikia teisę programai nustatyti telefono numerį ir įrenginio ID, tai, ar skambutis aktyvus, ir skambučiu prijungtą nuotolinį numerį."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"nukreipti skambučius per sistemą"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Programai leidžiama nukreipti jos skambučius per sistemą siekiant pagerinti skambinimo paslaugas."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"skaityti telefonų numerius"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Programai leidžiama pasiekti įrenginio telefonų numerius."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"neleisti planšetiniam kompiuteriui užmigti"</string>
@@ -491,10 +498,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Per lėtai judinate pirštą. Bandykite dar kartą."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Neatpažintas"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Kontrolinio kodo aparatinė įranga nepasiekiama."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Negalima išsaugoti kontrolinio kodo. Pašalinkite esamą kontrolinį kodą."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Baigėsi kontrolinio kodo nustatymo skirtasis laikas. Bandykite dar kartą."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Kontrolinio kodo operacija atšaukta."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Per daug bandymų. Vėliau bandykite dar kartą."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Per daug bandymų. Kontrolinio kodo jutiklis išjungtas."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Bandykite dar kartą."</string>
@@ -1030,6 +1040,12 @@
<string name="browse" msgid="1245903488306147205">"Atidaryti"</string>
<string name="sms" msgid="4560537514610063430">"Pranešimas"</string>
<string name="add_contact" msgid="7867066569670597203">"Pridėti"</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">"Mažėja laisvos saugyklos vietos"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Kai kurios sistemos funkcijos gali neveikti"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Sistemos saugykloje nepakanka vietos. Įsitikinkite, kad yra 250 MB laisvos vietos, ir paleiskite iš naujo."</string>
@@ -1159,6 +1175,8 @@
<item quantity="other">Pasiekiami atvirieji „Wi-Fi“ tinklai</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Prisijunkite prie atviro „Wi‑Fi“ tinklo"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Prisijungiama prie atviro „Wi‑Fi“ tinklo"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Prisijungta prie „Wi-Fi“ tinklo"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nepavyko prisijungti prie „Wi‑Fi“ tinklo"</string>
@@ -1458,6 +1476,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> viršyta nurodyta riba."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Apriboti foniniai duomenys"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Palieskite ir pašal. apribojimą."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Naudojama daug duomenų"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Pastarąsias kelias dienas naudojate daugiau duomenų nei įprastai. Palietę peržiūrėkite naudojimą ir nustatymus."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Saugos sertifikatas"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Šis sertifikatas galioja."</string>
<string name="issued_to" msgid="454239480274921032">"Išduota:"</string>
@@ -1754,7 +1774,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Iki <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Iki <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (kitas signalas)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Kol neišjungsite netrukdymo režimo"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Kol išjungsite"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Kol neišjungsite režimo „Netrukdyti“"</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">"Sutraukti"</string>
@@ -1805,9 +1825,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Visos kalbos"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Visi regionai"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Paieška"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Įjungti darbo režimą?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Tai atlikus bus įjungtas darbo profilis, įskaitant programas, sinchronizavimą fone ir susijusias funkcijas"</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">"Įjungti"</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">"Turite naujų pranešimų"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Atidaryti SMS programą, norint peržiūrėti"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Kai kurios funkcijos gali būti ribojamos"</string>
@@ -1881,7 +1907,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nepavyko atkurti sparčiojo klavišo, nes programos parašas neatitinka"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nepavyko atkurti sparčiojo klavišo"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Spartusis klavišas išjungtas"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Pašalinti"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Vis tiek paleisti"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Pašalinti žalingą programą?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"„<xliff:g id="APP_0">%1$s</xliff:g>“ nori rodyti „<xliff:g id="APP_2">%2$s</xliff:g>“ fragmentus"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Redaguoti"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 2d98ade..75f39de 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -183,6 +183,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Jūsu organizācija pārvalda šo ierīci un var uzraudzīt tīkla datplūsmu. Pieskarieties, lai saņemtu detalizētu informāciju."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Jūsu ierīces dati tiks dzēsti"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Administratora lietotni nevar izmantot. Ierīcē saglabātie dati tiks dzēsti. \n\nJa jums ir kādi jautājumi, sazinieties ar savas organizācijas administratoru."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Drukāšanu atspējoja <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Man"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Planšetdatora opcijas"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV opcijas"</string>
@@ -219,6 +220,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Ārkārtas"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Kļūdu ziņojums"</string>
<string name="global_action_logout" msgid="935179188218826050">"Beigt sesiju"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Ekrānuzņēmums"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Kļūdu ziņojuma sagatavošana"</string>
<string name="bugreport_message" msgid="398447048750350456">"Veicot šo darbību, tiks apkopota informācija par jūsu ierīces pašreizējo stāvokli un nosūtīta e-pasta ziņojuma veidā. Kļūdu ziņojuma pabeigšanai un nosūtīšanai var būt nepieciešams laiks. Lūdzu, esiet pacietīgs."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktīvs pārskats"</string>
@@ -265,8 +267,10 @@
<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">"Drošais režīms"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Pārslēgt personīgo profilu"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Pārslēgt darba profilu"</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">"Kontaktpersonas"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"piekļūt jūsu kontaktpersonu datiem"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Atļaut lietotnei <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> piekļūt jūsu kontaktpersonām"</string>
@@ -418,6 +422,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ļauj lietotnei piekļūt ierīces tālruņa funkcijām. Ar šo atļauju lietotne var noteikt tālruņa numuru un ierīču ID, zvana statusu un attālo numuru, ar ko ir izveidots savienojums, veicot zvanu."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"maršrutēt zvanus sistēmā"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Ļauj lietotnei maršrutēt tās zvanus sistēmā, lai uzlabotu zvanīšanas pieredzi."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"lasīt tālruņa numurus"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Ļauj lietotnei piekļūt ierīcē esošajiem tālruņa numuriem."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"novērst planšetdatora pāriešanu miega režīmā"</string>
@@ -487,10 +495,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Pārāk lēna pirksta kustība. Lūdzu, mēģiniet vēlreiz."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nav atpazīts"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Nospieduma aparatūra nav pieejama."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Pirkstu nospiedumu nevar saglabāt. Lūdzu, noņemiet esošu pirksta nospiedumu."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Pirkstu nospiedumu nolasīšanas aparatūras noildze. Mēģiniet vēlreiz."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Nospieduma darbība neizdevās."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Pārāk daudz mēģinājumu. Vēlāk mēģiniet vēlreiz."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Pārāk daudz mēģinājumu. Pirksta nospieduma sensors atspējots."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Mēģiniet vēlreiz."</string>
@@ -1009,6 +1020,12 @@
<string name="browse" msgid="1245903488306147205">"Atvērt"</string>
<string name="sms" msgid="4560537514610063430">"Īsziņa"</string>
<string name="add_contact" msgid="7867066569670597203">"Pievienot"</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">"Paliek maz brīvas vietas"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Dažas sistēmas funkcijas var nedarboties."</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Sistēmai pietrūkst vietas. Atbrīvojiet vismaz 250 MB vietas un restartējiet ierīci."</string>
@@ -1136,6 +1153,8 @@
<item quantity="other">Ir pieejami atvērti Wi-Fi tīkli</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Savienojuma izveide ar atvērtu Wi-Fi tīklu"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Notiek savienojuma izveide ar atvērtu Wi-Fi tīklu"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Ir izveidots savienojums ar Wi-Fi tīklu"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nevarēja izveidot savienojumu ar Wi‑Fi tīklu"</string>
@@ -1145,6 +1164,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi tiks automātiski ieslēgts"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kad atrodaties saglabāta augstas kvalitātes tīkla tuvumā"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Neieslēgt atkārtoti"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi-Fi tika ieslēgts automātiski"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Jūs atrodaties saglabāta tīkla tuvumā: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>."</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Pierakstieties Wi-Fi tīklā"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Pierakstīšanās tīklā"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1432,6 +1453,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> virs norādītā ierobežojuma."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Fona dati ir ierobežoti."</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Pieskar., lai noņemtu ierobežoj."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Liels datu lietojums"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Datu lietojums dažās pēdējās dienās ir lielāks nekā parasti. Pieskarieties, lai skatītu lietojumu un iestatījumus."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Drošības sertifikāts"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Sertifikāts ir derīgs."</string>
<string name="issued_to" msgid="454239480274921032">"Izdots:"</string>
@@ -1718,7 +1741,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Līdz <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Līdz plkst. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nākamais signāls)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Līdz izslēgsiet statusu “Netraucēt”"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Līdz brīdim, kad izslēgsiet"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Līdz izslēgsiet statusu “Netraucēt”"</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">"Sakļaut"</string>
@@ -1768,9 +1791,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Visas valodas"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Visi reģioni"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Meklēt"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Vai ieslēgt darba režīmu?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Jūsu darba profils, tostarp lietotnes, sinhronizācija fonā un saistītās funkcijas, tiks aktivizēti."</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">"Ieslēgt"</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">"Jums ir jaunas īsziņas."</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Lai skatītu, atveriet īsziņu lietotni."</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Funkcijas var būt ierobežotas"</string>
@@ -1842,6 +1871,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nevarēja atjaunot saīsni, jo lietotnē netiek atbalstīta dublēšana un atjaunošana."</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Saīsni nevarēja atjaunot lietotnes paraksta neatbilstības dēļ."</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nevarēja atjaunot saīsni."</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Saīsne ir atspējota."</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Lietotne <xliff:g id="APP_0">%1$s</xliff:g> vēlas rādīt lietotnes <xliff:g id="APP_2">%2$s</xliff:g> sadaļas"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Rediģēt"</string>
</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 67aabea..746ac52 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Опции на телевизорот"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Слика од екранот"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Земи извештај за грешки"</string>
<string name="bugreport_message" msgid="398447048750350456">"Ова ќе собира информации за моменталната состојба на вашиот уред, за да ги испрати како порака по е-пошта. Тоа ќе одземе малку време почнувајќи од извештајот за грешки додека не се подготви за праќање; бидете трпеливи."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивен извештај"</string>
@@ -262,8 +264,8 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"Префрлете на личен профил"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Префрли на работен профил"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Префрли на личен профил"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Префрли се на работен профил"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакти"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"пристапува до контактите"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Дозволете <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> да пристапува до контактите"</string>
@@ -415,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Овозможува апликацијата да пристапи кон карактеристиките на телефонот на уредот. Оваа дозвола овозможува апликацијата да ги утврди телефонскиот број и ID на уредот, дали повикот е активен и далечинскиот број поврзан со повикот."</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>
@@ -484,10 +490,12 @@
<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>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Корисникот ја откажа потврдата со отпечаток."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Премногу обиди. Обидете се повторно подоцна."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Премногу обиди. Сензорот за отпечатоци е оневозможен."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Обидете се повторно."</string>
@@ -989,6 +997,12 @@
<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">"Нема доволно меморија во системот. Проверете дали има слободен простор од 250 МБ и рестартирајте."</string>
@@ -1114,6 +1128,8 @@
<item quantity="other">Отворени Wi-Fi мрежи се достапни</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Поврзете се на отворена Wi‑Fi-мрежа"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Поврзување на отворена Wi‑Fi-мрежа"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Се поврзавте на Wi‑Fi-мрежа"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не можеше да се поврзе на Wi‑Fi-мрежа"</string>
@@ -1123,6 +1139,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi се вклучи автоматски"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Близу сте до зачувана мрежа: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Најавете се на мрежа на Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Најавете се на мрежа"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1412,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"Сертификат за безбедност"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Овој сертификат е важечки."</string>
<string name="issued_to" msgid="454239480274921032">"Издадено на:"</string>
@@ -1688,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Додека не го исклучите „Не вознемирувај“"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Додека не го исклучите"</string>
<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>
@@ -1737,9 +1757,13 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Да се вклучи работен режим?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Ова ќе го вклучи вашиот работен профил, заедно со апликациите, синхронизирањето во заднина и слични функции"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Да се вклучи работниот профил?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Вашите работни апликации, известувања, податоци и други функции на работниот профил ќе бидат вклучени"</string>
<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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Некои функции се ограничени"</string>
@@ -1810,6 +1834,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> сака да прикажува делови од <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Измени"</string>
</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index ed2dc02..022e077 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"ടിവി ഓപ്ഷനുകൾ"</string>
@@ -217,8 +218,7 @@
<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="global_action_screenshot" msgid="8329831278085426283">"സ്ക്രീൻഷോട്ട്"</string>
<string name="bugreport_title" msgid="2667494803742548533">"ബഗ് റിപ്പോർട്ട് എടുക്കുക"</string>
<string name="bugreport_message" msgid="398447048750350456">"ഒരു ഇമെയിൽ സന്ദേശമായി അയയ്ക്കുന്നതിന്, ഇത് നിങ്ങളുടെ നിലവിലെ ഉപകരണ നിലയെക്കുറിച്ചുള്ള വിവരങ്ങൾ ശേഖരിക്കും. ബഗ് റിപ്പോർട്ട് ആരംഭിക്കുന്നതിൽ നിന്ന് ഇത് അയയ്ക്കാനായി തയ്യാറാകുന്നതുവരെ അൽപ്പസമയമെടുക്കും; ക്ഷമയോടെ കാത്തിരിക്കുക."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ഇന്റരാക്റ്റീവ് റിപ്പോർട്ട്"</string>
@@ -264,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"വ്യക്തിഗത പ്രൊഫൈലിലേക്ക് മാറുക"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് മാറുക"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"നിങ്ങളുടെ കോണ്ടാക്റ്റുകള് ആക്സസ് ചെയ്യാൻ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ആപ്പിനെ അനുവദിക്കുക"</string>
@@ -417,6 +419,10 @@
<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>
@@ -486,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"നിരവധി തവണ ശ്രമിച്ചതിനാൽ, വിരലടയാള സെൻസർ പ്രവർത്തനരഹിതമായി."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"വീണ്ടും ശ്രമിക്കൂ."</string>
@@ -991,6 +1000,12 @@
<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">"സിസ്റ്റത്തിനായി മതിയായ സംഭരണമില്ല. 250MB സൗജന്യ സംഭരണമുണ്ടെന്ന് ഉറപ്പുവരുത്തി പുനരാരംഭിക്കുക."</string>
@@ -1116,6 +1131,8 @@
<item quantity="one">ലഭ്യമായ വൈഫൈ നെറ്റ്വർക്ക് തുറക്കുക</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>
@@ -1125,10 +1142,8 @@
<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_wakeup_enabled_title" msgid="6534603733173085309">"വൈഫൈ സ്വമേധയാ ഓണായി"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"നിങ്ങൾ സംരക്ഷിച്ചിട്ടുള്ള ഒരു നെറ്റ്വർക്കിന് സമീപമാണ്: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<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) -->
@@ -1416,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"നിശ്ചിത പരിധിയിലും <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="ssl_certificate" msgid="6510040486049237639">"സുരക്ഷ സർട്ടിഫിക്കറ്റ്"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ഈ സര്ട്ടിഫിക്കറ്റ് സാധുതയുള്ളതാണ്."</string>
<string name="issued_to" msgid="454239480274921032">"ഇതിലേക്ക് നൽകി:"</string>
@@ -1692,7 +1709,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"\'ശല്ല്യപ്പെടുത്തരുത്\' ഓഫാക്കുന്നതുവരെ"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"നിങ്ങൾ ഓഫാക്കുന്നത് വരെ"</string>
<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>
@@ -1741,9 +1758,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"ഔദ്യോഗിക മോഡ് ഓണാക്കണോ?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"ആപ്പുകളും പശ്ചാത്തല സമന്വയവും ബന്ധപ്പെട്ട ഫീച്ചറുകളും ഉൾപ്പെടെ, ഔദ്യോഗിക പ്രൊഫൈലിനെ ഇത് ഓണാക്കും"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"ചില പ്രവർത്തനക്ഷമതകൾ പരിമിതപ്പെടാം"</string>
@@ -1815,10 +1838,12 @@
<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 (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_2">%2$s</xliff:g> സ്ലൈസുകൾ കാണിക്കാൻ <xliff:g id="APP_0">%1$s</xliff:g> താൽപ്പര്യപ്പെടുന്നു"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"എഡിറ്റ് ചെയ്യുക"</string>
</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index dbbb29e..7d082fd 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Телевиз сонголтууд"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Дэлгэцийн зураг дарах"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Согог репорт авах"</string>
<string name="bugreport_message" msgid="398447048750350456">"Энэ таны төхөөрөмжийн одоогийн статусын талаарх мэдээллийг цуглуулах ба имэйл мессеж болгон илгээнэ. Алдааны мэдэгдлээс эхэлж илгээхэд бэлэн болоход хэсэг хугацаа зарцуулагдана тэвчээртэй байна уу."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактив тайлан"</string>
@@ -262,8 +264,10 @@
<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">"Андройд систем"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"\"Хувийн\" руу шилжих"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"\"Ажлын\" руу шилжих"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>-д таны харилцагчдад хандахыг зөвшөөрнө үү"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Апп нь төхөөрөмжийн утасны функцд хандах боломжтой. Энэ зөвшөөрөл нь апп-д утасны дугаар болон төхөөрөмжийн ID-г, дуудлага идэвхтэй эсэх, холын дугаар дуудлагаар холбогдсон байгаа эсэхийг тогтоох боломжийг олгоно,"</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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Хэт олон удаа оролдсон тул хурууны хээ мэдрэгчийг идэвхгүй болголоо."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Дахин оролдно уу."</string>
@@ -989,6 +1000,12 @@
<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">"Системд хангалттай сан байхгүй байна. 250MБ чөлөөтэй зай байгаа эсэхийг шалгаад дахин эхлүүлнэ үү."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Нээлттэй Wi-Fi сүлжээ ашиглах боломжтой</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Нээлттэй Wi‑Fi сүлжээнд холбогдох"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Нээлттэй Wi‑Fi сүлжээнд холбогдож байна"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi сүлжээнд холбогдлоо"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi сүлжээнд холбогдож чадсангүй"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi-г автоматаар асаасан"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Та дараах хадгалсан сүлжээтэй ойрхон байна: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi сүлжээнд нэвтэрнэ үү"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Сүлжээнд нэвтэрнэ үү"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"Аюулгүй сертификат"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Сертификат хүчинтэй."</string>
<string name="issued_to" msgid="454239480274921032">"Гаргуулсан:"</string>
@@ -1683,7 +1706,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"\"Бүү саад бол\" горимыг унтраах хүртэл"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Та унтраах хүртэл"</string>
<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>
@@ -1732,9 +1755,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Ажлын горимыг асаах уу?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Энэ нь апп, цаана синк хийх болон холбоотой онцлог зэрэг таны ажлын профайлыг асаана"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Зарим үйлдэл хязгаарлалттай байж болно"</string>
@@ -1805,6 +1834,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> <xliff:g id="APP_2">%2$s</xliff:g>-н хэсгүүдийг (slices) харуулах хүсэлтэй байна"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Засах"</string>
</resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 9e36c1d..0da8708 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"टीव्ही पर्याय"</string>
@@ -217,8 +218,7 @@
<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="global_action_screenshot" msgid="8329831278085426283">"स्क्रीनशॉट"</string>
<string name="bugreport_title" msgid="2667494803742548533">"बग रीपोर्ट घ्या"</string>
<string name="bugreport_message" msgid="398447048750350456">"ई-मेल संदेश म्हणून पाठविण्यासाठी, हे तुमच्या सद्य डिव्हाइस स्थितीविषयी माहिती संकलित करेल. बग रीपोर्ट सुरू करण्यापासून तो पाठविण्यापर्यंत थोडा वेळ लागेल; कृपया धीर धरा."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"परस्परसंवादी अहवाल"</string>
@@ -264,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"वैयक्तिकवर स्विच करा"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"कार्यावर स्विच करा"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला तुमचे संपर्क अॅक्सेस करू द्या"</string>
@@ -417,6 +419,10 @@
<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>
@@ -486,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"खूप प्रयत्न करून झाले. फिंगरप्रिंट सेंसर बंद आहे."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन्हा प्रयत्न करा."</string>
@@ -991,6 +1000,12 @@
<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">"सिस्टीमसाठी पुरेसे संचयन नाही. आपल्याकडे 250MB मोकळे स्थान असल्याचे सुनिश्चित करा आणि रीस्टार्ट करा."</string>
@@ -1116,6 +1131,8 @@
<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>
@@ -1125,10 +1142,8 @@
<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_wakeup_enabled_title" msgid="6534603733173085309">"वाय-फाय आपोआप चालू झाले"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"तुम्ही या सेव्ह केलेल्या नेटवर्कजवळ आहात: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<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) -->
@@ -1416,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"निर्दिष्ट केलेल्या मर्यादेबाहेर <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="ssl_certificate" msgid="6510040486049237639">"सुरक्षितता प्रमाणपत्र"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"हे प्रमाणपत्र वैध आहे."</string>
<string name="issued_to" msgid="454239480274921032">"यावर जारी केले:"</string>
@@ -1692,7 +1709,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"आपण व्यत्यय आणू नका बंद करेपर्यंत"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"तुम्ही बंद करेपर्यंत"</string>
<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>
@@ -1741,9 +1758,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"कार्य मोड चालू करायचा?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"हे अॅप्स, पार्श्वभूमी संकालन आणि संबंधित वैशिष्ट्यांसह आपले कार्य प्रोफाइल चालू करेल"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"काही कार्यक्षमता मर्यादित असू शकतात"</string>
@@ -1815,10 +1838,12 @@
<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 (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> ला <xliff:g id="APP_2">%2$s</xliff:g> चे तुकडे दाखवायचे आहेत"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"संपादित करा"</string>
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index f7e18ff..e27b0f1 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organisasi anda mengurus peranti ini dan mungkin memantau trafik rangkaian. Ketik untuk mendapatkan butiran."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Peranti anda akan dipadam"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Apl pentadbir tidak dapat digunakan. Peranti anda akan dipadamkan sekarang.\n\nJika anda ingin mengemukakan soalan, hubungi pentadbir organisasi anda."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Pencetakan dilumpuhkan oleh <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Saya"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Pilihan tablet"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Pilihan TV"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Kecemasan"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Laporan pepijat"</string>
<string name="global_action_logout" msgid="935179188218826050">"Tamatkan sesi"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Tangkapan skrin"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Ambil laporan pepijat"</string>
<string name="bugreport_message" msgid="398447048750350456">"Ini akan mengumpul maklumat tentang keadaan peranti semasa anda untuk dihantarkan sebagai mesej e-mel. Harap bersabar, mungkin perlu sedikit masa untuk memulakan laporan sehingga siap untuk dihantar."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Laporan interaktif"</string>
@@ -262,8 +264,10 @@
<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">"Mod selamat"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Beralih kepada Peribadi"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Beralih kepada Kerja"</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">"Kenalan"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"mengakses kenalan anda"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Benarkan <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> mengakses kenalan anda"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Membenarkan apl mengakses ciri telefon pada peranti. Kebenaran ini membolehkan apl menentukan nombor telefon dan ID peranti, sama ada panggilan aktif dan nombor jauh yang dihubungkan dengan panggilan."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"halakan panggilan menerusi sistem"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Membenarkan apl menghalakan panggilan menerusi sistem untuk meningkatkan pengalaman panggilan."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"baca nombor telefon"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Membenarkan apl mengakses nombor telefon peranti."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"menghalang tablet daripada tidur"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Jari digerakkan terlalu perlahan. Sila cuba lagi."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Tidak dicam"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Perkakasan cap jari tidak tersedia."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Cap jari tidak dapat disimpan. Sila alih keluar cap jari sedia ada."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tamat masa cap jari dicapai. Cuba lagi."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Pengendalian cap jari dibatalkan."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Terlalu banyak percubaan. Cuba sebentar lagi."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Terlalu banyak percubaan. Penderia cap jadi dilumpuhkan."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Cuba lagi."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Buka"</string>
<string name="sms" msgid="4560537514610063430">"Mesej"</string>
<string name="add_contact" msgid="7867066569670597203">"Tambah"</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">"Ruang storan semakin berkurangan"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Beberapa fungsi sistem mungkin tidak berfungsi"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Tidak cukup storan untuk sistem. Pastikan anda mempunyai 250MB ruang kosong dan mulakan semula."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Rangkaian Wi-Fi terbuka tersedia</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Sambung ke rangkaian Wi-Fi terbuka"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Menyambung ke rangkaian Wi‑Fi terbuka"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Disambungkan ke rangkaian Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Tidak dapat menyambung ke rangkaian Wi-Fi"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi akan dihidupkan secara automatik"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Apabila anda berada berdekatan dengan rangkaian disimpan yang berkualiti tinggi"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Jangan hidupkan kembali"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi dihidupkan secara automatik"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Anda berada berdekatan rangkaian yang disimpan: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Log masuk ke rangkaian Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Log masuk ke rangkaian"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> melebihi had yang ditentukan."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Data latar belakang terhad"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Ketik untuk alih keluar sekatan."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Penggunaan data yang banyak"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Penggunaan data anda sepanjang beberapa hari yang lalu adalah lebih banyak daripada biasa. Ketik untuk melihat penggunaan dan tetapan."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Sijil keselamatan"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Sijil ini sah."</string>
<string name="issued_to" msgid="454239480274921032">"Dikeluarkan kepada:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Sehingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Sehingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (penggera akan datang)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Hingga anda mematikan Jangan Ganggu"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Sehingga anda matikan"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hingga anda mematikan Jangan Ganggu"</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">"Runtuhkan"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Semua bahasa"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Semua rantau"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Cari"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Hidupkan mod kerja?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Tindakan ini akan menghidupkan profil kerja, termasuk apl, penyegerakan latar belakang dan ciri yang berkaitan"</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">"Hidupkan"</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">"Anda mempunyai mesej baharu"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Buka apl SMS untuk melihat"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Sesetengah fungsi mungkin terhad"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Tidak dapat memulihkan pintasan kerana apl tidak menyokong sandaran dan segerakan"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Tidak dapat memulihkan pintasan kerana ketakpadanan tandatangan apl"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Tidak dapat memulihkan pintasan"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Pintasan dilumpuhkan"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> mahu menunjukkan <xliff:g id="APP_2">%2$s</xliff:g> hirisan"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Edit"</string>
</resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 5f67641..afccd79 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -181,6 +181,7 @@
<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="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">"Tabletဆိုင်ရာရွေးချယ်မှုများ"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"တီဗွီ ရွေးချယ်စရာများ"</string>
@@ -263,8 +264,8 @@
<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">"အန္တရာယ်ကင်းမှု စနစ်(Safe mode)"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android စနစ်"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"ကိုယ်ပိုင်သီးသန့်အဖြစ် ပြောင်းပါ"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"အလုပ်သို့ ပြောင်းပါ"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"ကိုယ်ရေးကိုယ်တာသုံး ပရိုဖိုင်သို့ ပြောင်းရန်"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"အလုပ်ပရိုဖိုင်သို့ ပြောင်းရန်"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"အဆက်အသွယ်များ"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"သင့် အဆက်အသွယ်များအား ဝင်ရောက်သုံးရန်"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<xliff:g id="APP_NAME">%1$s</xliff:g> အား သင်၏အဆက်အသွယ်များကို သုံးခွင့်ပေးရန်"</string>
@@ -416,6 +417,10 @@
<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>
@@ -485,10 +490,12 @@
<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>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"လက်ဗွေဖြင့် အထောက်အထားစိစစ်ခြင်းကို အသုံးပြုသူက ပယ်ဖျက်ထားသည်။"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ကြိုးစာမှု အကြိမ်များနေ၏။ နောက်မှ ထပ်မံကြိုးစားပါ။"</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"အကြိမ်အရေအတွက် အလွန်များနေပါပြီ။ လက်ဗွေဖတ်စနစ်ကို ပိတ်ထားပါသည်။"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ပြန်ကြိုးစားပါ"</string>
@@ -990,6 +997,12 @@
<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">"စနစ်အတွက် သိုလှောင်ခန်း မလုံလောက်ပါ။ သင့်ဆီမှာ နေရာလွတ် ၂၅၀ MB ရှိတာ စစ်ကြည့်ပြီး စတင်ပါ။"</string>
@@ -1115,6 +1128,8 @@
<item quantity="one">Wi-Fi ကွန်ယက်ရရှိနိုင်သည်အား ဖွင့်ပါ</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"အများသုံး Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်ပါ"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"အများသုံး Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်နေသည်"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်ပြီးပါပြီ"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်၍ မရပါ"</string>
@@ -1169,7 +1184,7 @@
<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> မှ စာ အမြောက်အများ ပို့နေပါသည်။ ဒီအပလီကေးရှင်းကို ဆက်လက်ပြီး လုပ်ဆောင်ရန် ခွင့်ပြုပါမလား"</string>
<string name="sms_control_yes" msgid="3663725993855816807">"ခွင့်ပြုရန်"</string>
- <string name="sms_control_no" msgid="625438561395534982">"ငြင်းပယ်ခြင်း"</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>
@@ -1413,6 +1428,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"သက်မှတ်နှုန်းထက် <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="ssl_certificate" msgid="6510040486049237639">"လုံခြံုမှုဆိုင်ရာ အသိအမှတ်ပြုလက်မှတ်"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ဤအသိအမှတ်ပြုလက်မှတ်မှာ တရားဝင်သည်"</string>
<string name="issued_to" msgid="454239480274921032">"ထုတ်ပေးသည်-"</string>
@@ -1689,7 +1706,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"\"မနှောင့်ယှက်ရန်\" ကို သင်ပိတ်လိုက်သည်အထိ"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"သင်ပိတ်လိုက်သည် အထိ"</string>
<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>
@@ -1738,9 +1755,13 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"အလုပ်မုဒ်ကို ဖွင့်လိုပါသလား။"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"၎င်းသည် အက်ပ်၊ နောက်ခံတွင် စင့်ခ်လုပ်ခြင်းနှင့် သက်ဆိုင်ရာ ဝန်ဆောင်မှုများ အပါအဝင် သင်၏အလုပ်ပရိုဖိုင်ကို ဖွင့်လိုက်ပါမည်"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"အလုပ်ပရိုဖိုင် ဖွင့်လိုသလား။"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"သင်၏ အလုပ်အက်ပ်၊ အကြောင်းကြားချက်၊ ဒေတာနှင့် အခြားအလုပ်ပရိုဖိုင် ဝန်ဆောင်မှုများကို ဖွင့်လိုက်ပါမည်"</string>
<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>
<string name="user_encrypted_title" msgid="9054897468831672082">"အချို့လုပ်ဆောင်ချက်များ ကန့်သတ်ချက်ရှိနိုင်သည်"</string>
@@ -1812,7 +1833,12 @@
<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>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"ဖြုတ်ရန်"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"မည်သို့ပင်ဖြစ်စေ ဖွင့်ရန်"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"အန္တရာယ်ရှိသည့် အက်ပ်ကို ဖြုတ်လိုပါသလား။"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> သည် <xliff:g id="APP_2">%2$s</xliff:g> ၏အချပ်များကို ပြသလိုသည်"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"တည်းဖြတ်ရန်"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index c3deb3e..4cbdd17 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organisasjonen din kontrollerer denne enheten og kan overvåke nettverkstrafikk. Trykk for å få mer informasjon."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Enheten blir slettet"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Administratorappen kan ikke brukes. Enheten din blir nå tømt.\n\nTa kontakt med administratoren for organisasjonen din hvis du har spørsmål."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"<xliff:g id="OWNER_APP">%s</xliff:g> har slått av utskrift."</string>
<string name="me" msgid="6545696007631404292">"Meg"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Innstillinger for nettbrettet"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Alternativer for TV"</string>
@@ -217,8 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Nødsituasjon"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Feilrapport"</string>
<string name="global_action_logout" msgid="935179188218826050">"Avslutt økten"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Skjermdump"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Utfør feilrapport"</string>
<string name="bugreport_message" msgid="398447048750350456">"Informasjon om tilstanden til enheten din samles inn og sendes som en e-post. Det tar litt tid fra du starter feilrapporten til e-posten er klar, så vær tålmodig."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv rapport"</string>
@@ -264,8 +264,10 @@
<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">"Sikkermodus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Bytt til den personlige profilen"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Bytt til jobbprofilen"</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">"Kontakter"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"se kontaktene dine"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Gi <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> tilgang til kontaktene dine"</string>
@@ -417,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lar appen bruke enhetens telefonfunksjoner. Med denne tillatelsen kan appen finne telefonnummer og enhets-ID-er, registrere om en samtale pågår, og se det eksterne nummeret det opprettes en forbindelse med via oppringing."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"send anrop gjennom systemet"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Lar appen sende anrop gjennom systemet for å forbedre anropsopplevelsen."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"les telefonnumre"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Gir appen tilgang til telefonnumrene til enheten."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"hindre nettbrettet fra å gå over til sovemodus"</string>
@@ -486,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Du flyttet fingeren for sakte. Prøv på nytt."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ikke gjenkjent"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Maskinvare for fingeravtrykk er ikke tilgjengelig."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeravtrykket kan ikke lagres. Fjern et eksisterende fingeravtrykk."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeravtrykk-operasjonen ble avbrutt."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"For mange forsøk. Prøve på nytt senere."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"For mange forsøk. Fingeravtrykkssensoren er slått av."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Prøv igjen."</string>
@@ -991,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Åpne"</string>
<string name="sms" msgid="4560537514610063430">"Melding"</string>
<string name="add_contact" msgid="7867066569670597203">"Legg til"</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">"Lite ledig lagringsplass"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Enkelte systemfunksjoner fungerer muligens ikke slik de skal"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Det er ikke nok lagringsplass for systemet. Kontrollér at du har 250 MB ledig plass, og start på nytt."</string>
@@ -1116,6 +1131,8 @@
<item quantity="one">Åpent Wi-Fi-nettverk er tilgjengelig</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Koble til et åpent Wi‑Fi-nettverk"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Kobler til åpent Wi-Fi-nettverk"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Koblet til Wi-Fi-nettverk"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Kunne ikke koble til Wi-Fi-nettverket"</string>
@@ -1125,10 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi slås på automatisk"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Når du er i nærheten av et lagret nettverk av høy kvalitet"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Ikke slå på igjen"</string>
- <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
- <skip />
- <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
- <skip />
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi er slått på automatisk"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Du er i nærheten av et lagret nettverk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Logg på Wi-Fi-nettverket"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Logg på nettverk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1415,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> over angitt grense."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Bakgrunnsdata er begrenset"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Trykk for å fjerne begrensningen."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Høy databruk"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Databruken din de siste dagene er høyere enn vanlig. Trykk for å se bruken og innstillingene."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Sikkerhetssertifikat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Sertifikatet er gyldig."</string>
<string name="issued_to" msgid="454239480274921032">"Utstedt til:"</string>
@@ -1691,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (neste alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Inntil du slår av Ikke forstyrr"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Til du slår av"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Inntil du slår av Ikke forstyrr"</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">"Skjul"</string>
@@ -1740,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Alle språk"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Alle områder"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Søk"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Vil du slå på jobbmodus?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Dette slår på jobbprofilen din, inkludert apper, synkronisering i bakgrunnen og relaterte funksjoner"</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">"Slå på"</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">"Du har nye meldinger"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Åpne SMS-appen for å se"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Enkelte funksjoner kan være begrenset"</string>
@@ -1814,10 +1837,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Kunne ikke gjenopprette snarveien på grunn av manglende samsvar for appsignaturen"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Kunne ikke gjenopprette snarveien"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Snarveien er slått av"</string>
- <!-- no translation found for harmful_app_warning_uninstall (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> vil vise <xliff:g id="APP_2">%2$s</xliff:g>-utsnitt"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Endre"</string>
</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 71e1258..014d4f2 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV विकल्पहरू"</string>
@@ -217,8 +218,7 @@
<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="global_action_screenshot" msgid="8329831278085426283">"स्क्रिनसट"</string>
<string name="bugreport_title" msgid="2667494803742548533">"बग रिपोर्ट लिनुहोस्"</string>
<string name="bugreport_message" msgid="398447048750350456">"एउटा इमेल सन्देशको रूपमा पठाउनलाई यसले तपाईँको हालैको उपकरणको अवस्थाको बारेमा सूचना जम्मा गर्ने छ। बग रिपोर्ट सुरु गरेदेखि पठाउन तयार नभएसम्म यसले केही समय लिन्छ; कृपया धैर्य गर्नुहोस्।"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"अन्तरक्रियामूलक रिपोर्ट"</string>
@@ -264,8 +264,10 @@
<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">"एन्ड्रोइड प्रणाली"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"व्यक्तिगत प्रोफाइलमा स्विच गर्नुहोस्"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"कार्य प्रोफाइलमा स्विच गर्नुहोस्"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> लाई आफ्ना सम्पर्क ठेगानाहरूमाथि पहुँच राख्न दिनुहोस्"</string>
@@ -417,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"उपकरणको फोन विशेषताहरूको पहुँच गर्न अनुप्रयोगलाई अनुमति दिन्छ। यस अनुमतिले फोन नम्बर र उपकरणको IDs, कल सक्षम छ कि छैन र कलद्वारा जोडिएको टाढाको नम्बर निर्धारण गर्न अनुमति दिन्छ।"</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>
@@ -486,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"अत्यन्त धेरै प्रयासहरू। फिंगरप्रिन्ट सेन्सरलाई असक्षम पारियो।"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन: प्रयास गर्नुहोला।"</string>
@@ -991,6 +1000,12 @@
<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>
@@ -1122,6 +1137,8 @@
<item quantity="one">खुल्ला Wi-Fi सञ्जाल उपलब्ध छ</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"खुला Wi‑Fi नेटवर्कमा जडान गर्नुहोस्"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"खुला Wi‑Fi नेटवर्कमा जडान गर्दै"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi नेटवर्कमा जडान गरियो"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi नेटवर्कमा जडान गर्न सकिएन"</string>
@@ -1131,10 +1148,8 @@
<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>
- <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
- <skip />
- <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
- <skip />
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi स्वतः सक्रिय गरियो"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"तपाईं कुनै सुरक्षित गरिएको नेटवर्क नजिकै हुनुहुन्छ: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"सञ्जालमा साइन इन गर्नुहोस्"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1421,6 +1436,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"सुरक्षा प्रमाणपत्र"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"प्रमाणपत्र मान्य छ।"</string>
<string name="issued_to" msgid="454239480274921032">"द्वारा जारी गरिएको:"</string>
@@ -1697,7 +1714,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"तपाईंले बाधा नपुर्याउनुहोस् नामक सुविधालाई निष्क्रिय नगरेसम्म"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"तपाईंले निष्क्रिय नपार्नुभएसम्म"</string>
<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>
@@ -1746,9 +1763,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"कार्य प्रोफाइल मोड सक्रिय गर्ने?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"यस कार्यले अनुप्रयोगहरू, पृष्ठभूमिको सिंक र सम्बन्धित सुविधाहरू लगायत तपाईंको कार्य प्रोफाइललाई सक्रिय गर्नेछ"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"केही कार्य सीमित हुनसक्छ"</string>
@@ -1820,10 +1843,12 @@
<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 (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> ले <xliff:g id="APP_2">%2$s</xliff:g> का स्लाइसहरू देखाउन चाहन्छ"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"सम्पादन गर्नुहोस्"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 1d8619c..7aa8bf07 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Dit apparaat wordt beheerd door je organisatie. Het netwerkverkeer kan worden bijgehouden. Tik voor meer informatie."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Je apparaat wordt gewist"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"De beheer-app kan niet worden gebruikt. Je apparaat wordt nu gewist.\n\nNeem contact op met de beheerder van je organisatie als je vragen hebt."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Afdrukken uitgeschakeld door <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Ik"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tabletopties"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV-opties"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Noodgeval"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Bugrapport"</string>
<string name="global_action_logout" msgid="935179188218826050">"Sessie beëindigen"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Bugrapport genereren"</string>
<string name="bugreport_message" msgid="398447048750350456">"Hiermee worden gegevens over de huidige status van je apparaat verzameld en als e-mail verzonden. Wanneer u een bugrapport start, duurt het even voordat het kan worden verzonden. Even geduld alstublieft."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactief rapport"</string>
@@ -262,8 +264,10 @@
<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">"Veilige modus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Overschakelen naar persoonlijk profiel"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Overschakelen naar werkprofiel"</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">"Contacten"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"toegang krijgen tot je contacten"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Geef <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> toegang tot je contacten"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Hiermee kan de app toegang krijgen tot de telefoonfuncties van het apparaat, Met deze toestemming kan de app het telefoonnummer en de apparaat-ID\'s bepalen, of een oproep actief is, en het andere telefoonnummer waarmee wordt gebeld."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"oproepen doorschakelen via het systeem"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Hiermee kan de app de bijbehorende oproepen doorschakelen via het systeem om de belfunctionaliteit te verbeteren."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"telefoonnummers lezen"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Hiermee kan de app toegang krijgen tot de telefoonnummers van het apparaat."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"voorkomen dat tablet overschakelt naar slaapmodus"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Vinger te langzaam bewogen. Probeer het opnieuw."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Niet herkend"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware voor vingerafdruk niet beschikbaar."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Vingerafdruk kan niet worden opgeslagen. Verwijder een bestaande vingerafdruk."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Time-out bereikt voor vingerafdruk. Probeer het opnieuw."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Vingerafdrukbewerking geannuleerd."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Te veel pogingen. Probeer het later opnieuw."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Te veel pogingen. Vingerafdruksensor uitgeschakeld."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probeer het opnieuw."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Openen"</string>
<string name="sms" msgid="4560537514610063430">"Bericht"</string>
<string name="add_contact" msgid="7867066569670597203">"Toevoegen"</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">"Opslagruimte is bijna vol"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Bepaalde systeemfuncties werken mogelijk niet"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Onvoldoende opslagruimte voor het systeem. Zorg ervoor dat je 250 MB vrije ruimte hebt en start opnieuw."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Open wifi-netwerk beschikbaar</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Verbinding maken met een open wifi-netwerk"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Verbinding maken met een open wifi-netwerk…"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Verbonden met een wifi-netwerk"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Kan geen verbinding maken met het wifi-netwerk"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wifi wordt automatisch ingeschakeld"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Wanneer je in de buurt van een opgeslagen netwerk van hoge kwaliteit bent"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Niet weer inschakelen"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wifi automatisch ingeschakeld"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Je bent in de buurt van een opgeslagen netwerk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Inloggen bij wifi-netwerk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Inloggen bij netwerk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> meer dan limiet."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Achtergrondgegevens beperkt"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Tik om beperking te verwijderen."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Hoog datagebruik"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Je datagebruik in de afgelopen dagen is hoger dan normaal. Tik om gebruik en instellingen weer te geven."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Beveiligingscertificaat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Dit certificaat is geldig."</string>
<string name="issued_to" msgid="454239480274921032">"Uitgegeven voor:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (volgende wekker)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Totdat je \'Niet storen\' uitschakelt"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Totdat je uitschakelt"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Totdat u \'Niet storen\' uitschakelt"</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">"Samenvouwen"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Alle talen"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Alle regio\'s"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Zoeken"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Werkmodus inschakelen?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Hiermee wordt je werkprofiel (waaronder apps, synchronisatie op de achtergrond en gerelateerde functies) ingeschakeld"</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">"Inschakelen"</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">"Je hebt nieuwe berichten"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Open je sms-app om ze te bekijken"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Bepaalde functionaliteit kan zijn beperkt"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Kan snelkoppeling niet herstellen omdat de app geen ondersteuning biedt voor \'Back-up maken en terugzetten\'"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Kan snelkoppeling niet herstellen vanwege een niet-overeenkomende app-ondertekening"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Kan snelkoppeling niet herstellen"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Snelkoppeling is uitgeschakeld"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> wil segmenten van <xliff:g id="APP_2">%2$s</xliff:g> weergeven"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Bewerken"</string>
</resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 8a11b9f..5412d47 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV ਚੋਣਾਂ"</string>
@@ -217,8 +218,7 @@
<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="global_action_screenshot" msgid="8329831278085426283">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
<string name="bugreport_title" msgid="2667494803742548533">"ਬਗ ਰਿਪੋਰਟ ਲਓ"</string>
<string name="bugreport_message" msgid="398447048750350456">"ਇਹ ਇੱਕ ਈਮੇਲ ਸੁਨੇਹਾ ਭੇਜਣ ਲਈ, ਤੁਹਾਡੇ ਵਰਤਮਾਨ ਡੀਵਾਈਸ ਬਾਰੇ ਜਾਣਕਾਰੀ ਇਕੱਠੀ ਕਰੇਗਾ। ਬੱਗ ਰਿਪੋਰਟ ਸ਼ੁਰੂ ਕਰਨ ਵਿੱਚ ਥੋੜ੍ਹਾ ਸਮਾਂ ਲੱਗੇਗਾ ਜਦੋਂ ਤੱਕ ਇਹ ਭੇਜੇ ਜਾਣ ਲਈ ਤਿਆਰ ਨਾ ਹੋਵੇ, ਕਿਰਪਾ ਕਰਕੇ ਧੀਰਜ ਰੱਖੋ।"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ਅੰਤਰਕਿਰਿਆਤਮਕ ਰਿਪੋਰਟ"</string>
@@ -264,8 +264,10 @@
<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 System"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"ਨਿੱਜੀ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"ਕੰਮ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ਨੂੰ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ \'ਤੇ ਪਹੁੰਚ ਕਰਨ ਦਿਓ"</string>
@@ -417,6 +419,10 @@
<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>
@@ -486,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ।"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
@@ -991,6 +1000,12 @@
<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">"ਸਿਸਟਮ ਲਈ ਲੋੜੀਂਦੀ ਸਟੋਰੇਜ ਨਹੀਂ ਹੈ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਹਾਡੇ ਕੋਲ 250MB ਖਾਲੀ ਜਗ੍ਹਾ ਹੈ ਅਤੇ ਮੁੜ-ਚਾਲੂ ਕਰੋ।"</string>
@@ -1116,6 +1131,8 @@
<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>
@@ -1125,10 +1142,8 @@
<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_wakeup_enabled_title" msgid="6534603733173085309">"ਵਾਈ‑ਫਾਈ ਨੂੰ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"ਤੁਸੀਂ ਕਿਸੇ ਰੱਖਿਅਤ ਕੀਤੇ ਨੈੱਟਵਰਕ ਦੇ ਨੇੜੇ ਹੋ: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<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) -->
@@ -1416,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"ਸੁਰੱਖਿਆ ਪ੍ਰਮਾਣ-ਪੱਤਰ"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ਇਹ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਵੈਧ ਹੈ।"</string>
<string name="issued_to" msgid="454239480274921032">"ਨੂੰ ਜਾਰੀ ਕੀਤਾ ਗਿਆ:"</string>
@@ -1692,7 +1709,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ \'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਸੇਵਾ ਨੂੰ ਬੰਦ ਨਹੀਂ ਕਰਦੇ ਹੋ"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਬੰਦ ਨਹੀਂ ਕਰਦੇ ਹੋ"</string>
<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>
@@ -1741,9 +1758,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"ਕੀ ਕਾਰਜ ਮੋਡ ਚਾਲੂ ਕਰੀਏ?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"ਇਸ ਨਾਲ ਐਪਾਂ, ਬੈਕਗ੍ਰਾਊਂਡ ਸਮਕਾਲੀਕਰਨ, ਅਤੇ ਸਬੰਧਿਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸਮੇਤ ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਜਾਵੇਗਾ"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"ਕੁਝ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਸੀਮਿਤ ਹੋ ਸਕਦੀ ਹੈ"</string>
@@ -1815,10 +1838,12 @@
<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 (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> ਦੀ <xliff:g id="APP_2">%2$s</xliff:g> ਦੇ ਹਿੱਸੇ ਦਿਖਾਉਣ ਦੀ ਇੱਛਾ ਹੈ"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"ਸੰਪਾਦਨ ਕਰੋ"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 108b87b..952e55d 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -185,6 +185,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Twoja organizacja zarządza tym urządzeniem i może monitorować ruch w sieci. Kliknij, by dowiedzieć się więcej."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Twoje urządzenie zostanie wyczyszczone"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Tej aplikacji administratora nie można używać. Dane z urządzenia zostaną wykasowane.\n\nJeśli masz pytania, skontaktuj się z administratorem organizacji."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Drukowanie wyłączone przez: <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcje tabletu"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opcje telewizora"</string>
@@ -221,6 +222,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Alarmowy"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Zgłoszenie błędu"</string>
<string name="global_action_logout" msgid="935179188218826050">"Zakończ sesję"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Zrzut ekranu"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Zgłoś błąd"</string>
<string name="bugreport_message" msgid="398447048750350456">"Informacje o bieżącym stanie urządzenia zostaną zebrane i wysłane e-mailem. Przygotowanie zgłoszenia błędu do wysłania chwilę potrwa, więc zachowaj cierpliwość."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Raport interaktywny"</string>
@@ -268,8 +270,10 @@
<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">"Tryb awaryjny"</string>
<string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Włącz profil osobisty"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Włącz profil do pracy"</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">"Kontakty"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"dostęp do kontaktów"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Zezwalaj aplikacji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> na dostęp do kontaktów"</string>
@@ -421,6 +425,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Pozwala aplikacji na dostęp do funkcji telefonicznych urządzenia. Aplikacja z tym uprawnieniem może odczytać numer telefonu i identyfikator urządzenia, sprawdzić, czy połączenie jest aktywne, oraz poznać numer, z którym jest nawiązane połączenie."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"przekazywanie połączeń przez system"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Zezwala aplikacji na przekazywanie połączeń przez system, by poprawić ich jakość."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"odczytywanie numerów telefonów"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Zezwala aplikacji na dostęp do numerów telefonów na urządzeniu."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zapobieganie przechodzeniu tabletu do trybu uśpienia"</string>
@@ -490,10 +498,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Palec został obrócony zbyt wolno. Spróbuj ponownie."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nie rozpoznano odcisku palca."</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Czytnik linii papilarnych nie jest dostępny."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Nie można zapisać odcisku palca. Usuń istniejący odcisk palca."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Osiągnięto limit czasu odczytu linii papilarnych. Spróbuj ponownie."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Odczyt odcisku palca został anulowany."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zbyt wiele prób. Spróbuj ponownie później."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Zbyt wiele prób. Czytnik linii papilarnych został wyłączony."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Spróbuj ponownie."</string>
@@ -1029,6 +1040,12 @@
<string name="browse" msgid="1245903488306147205">"Otwórz"</string>
<string name="sms" msgid="4560537514610063430">"Wyślij SMS-a"</string>
<string name="add_contact" msgid="7867066569670597203">"Dodaj"</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">"Kończy się miejsce"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Niektóre funkcje systemu mogą nie działać"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Za mało pamięci w systemie. Upewnij się, że masz 250 MB wolnego miejsca i uruchom urządzenie ponownie."</string>
@@ -1158,6 +1175,8 @@
<item quantity="one">Dostępna jest otwarta sieć Wi-Fi</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Połącz się z otwartą siecią Wi-Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Łączę się z otwartą siecią Wi-Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Połączono z siecią Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nie udało się połączyć z siecią Wi‑Fi"</string>
@@ -1167,6 +1186,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi włączy się automatycznie"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Gdy znajdziesz się w pobliżu zapisanej sieci o mocnym sygnale"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Nie włączaj ponownie"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi włączone automatycznie"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Jesteś w pobliżu zapisanej sieci: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Zaloguj się w sieci Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Zaloguj się do sieci"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1455,6 +1476,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> ponad określony limit"</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Dane w tle są ograniczone"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Kliknij, by usunąć ograniczenie."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Duże użycie danych"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Od kilku dni przesyłasz więcej danych niż zwykle. Kliknij, by wyświetlić użycie i ustawienia."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certyfikat zabezpieczeń"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certyfikat jest ważny."</string>
<string name="issued_to" msgid="454239480274921032">"Wystawiony dla:"</string>
@@ -1751,7 +1774,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (następny alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Do wyłączenia trybu Nie przeszkadzać"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Dopóki nie wyłączysz"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Do wyłączenia Nie przeszkadzać"</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">"Zwiń"</string>
@@ -1802,9 +1825,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Wszystkie języki"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Wszystkie kraje"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Szukaj"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Włączyć tryb do pracy?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Spowoduje to włączenie Twojego profilu do pracy, w tym aplikacji, synchronizacji w tle i innych funkcji."</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">"Włącz"</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">"Masz nowe wiadomości"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Otwórz aplikację do SMS-ów, by wyświetlić wiadomość"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Niektóre funkcje mogą być niedostępne"</string>
@@ -1877,6 +1906,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nie można przywrócić skrótu, bo aplikacja nie obsługuje tworzenia i przywracania kopii zapasowej"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nie można przywrócić skrótu z powodu niezgodności podpisu aplikacji"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nie można przywrócić skrótu"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Skrót jest wyłączony"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Aplikacja <xliff:g id="APP_0">%1$s</xliff:g> chce pokazywać wycinki z aplikacji <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Edytuj"</string>
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 5201f14..11fc517 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opções de TV"</string>
@@ -263,8 +264,8 @@
<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">"Modo de segurança"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Alternar para \"Pessoal\""</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Alternar para \"Trabalho\""</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Deslize até o perfil pessoal"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Alternar para o perfil de trabalho"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acesse seus contatos"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Permitir que <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acesse seus contatos"</string>
@@ -416,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que o app acesse os recursos de telefonia do dispositivo. Esta permissão autoriza o app a determinar o número de telefone e IDs de dispositivo, quando uma chamada está ativa, e o número remoto conectado a uma chamada."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"encaminhar chamadas pelo sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Permite que o app encaminhe suas chamadas por meio do sistema para melhorar a experiência com chamadas."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"ler números de telefone"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Permite que o app acesse os número de telefone do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir modo de inatividade do tablet"</string>
@@ -485,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"O movimento do dedo está muito lento. Tente novamente."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Não reconhecido"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impressão digital não disponível."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não foi possível armazenar a impressão digital. Remova uma impressão digital já existente."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Operação de impressão digital cancelada pelo usuário."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Excesso de tentativas. Tente novamente mais tarde."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Excesso de tentativas. Sensor de impressão digital desativado."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
@@ -990,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Abrir"</string>
<string name="sms" msgid="4560537514610063430">"Mensagem"</string>
<string name="add_contact" msgid="7867066569670597203">"Adicionar"</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">"Pouco espaço de armazenamento"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Algumas funções do sistema podem não funcionar"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Não há armazenamento suficiente para o sistema. Certifique-se de ter 250 MB de espaço livre e reinicie."</string>
@@ -1115,6 +1128,8 @@
<item quantity="other">Abrir redes Wi-Fi disponíveis</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Conectar-se a uma rede Wi‑Fi aberta"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Conectando-se a uma rede Wi‑Fi aberta"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Conectado a uma rede Wi‑Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Não foi possível conectar-se à rede Wi‑Fi"</string>
@@ -1412,6 +1427,8 @@
<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_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="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>
@@ -1688,7 +1705,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Até que você desative \"Não perturbe\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Até você desativar"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Até que você desative \"Não perturbe\""</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">"Recolher"</string>
@@ -1737,9 +1754,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Todas as regiões"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pesquisa"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Ativar modo de trabalho?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Isso ativará seu perfil de trabalho, incluindo apps, sincronização de segundo plano e recursos relacionados"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Ativar o perfil de trabalho?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Seus apps, notificações, dados e outros recursos do perfil de trabalho serão ativados"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</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">"Você tem mensagens novas"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Abra o app de SMS para ver"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Algumas funcionalidades são limitadas"</string>
@@ -1811,7 +1832,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Não foi possível restaurar o atalho devido à incompatibilidade de assinatura de apps"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Não foi possível restaurar o atalho"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"O atalho está desativado"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Desinstalar"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Iniciar mesmo assim"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Desinstalar app nocivo?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> quer mostrar partes do app <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Editar"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index d6b888a..a624066 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"A sua entidade gere este dispositivo e pode monitorizar o tráfego de rede. Toque para obter mais detalhes."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"O seu dispositivo será apagado"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Não é possível utilizar a aplicação de administração. O seu dispositivo será agora apagado.\n\nSe tiver questões, contacte o gestor da entidade."</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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opções de TV"</string>
@@ -263,8 +264,10 @@
<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">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Mudar para pessoal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Mudar para trabalho"</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">"Contactos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"aceder aos contactos"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Permitir que a aplicação <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> aceda aos seus contactos"</string>
@@ -416,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que a aplicação aceda às funcionalidades de telefone do dispositivo. Esta autorização permite que a aplicação determine o número de telefone e IDs do dispositivo, se alguma chamada está ativa e qual o número remoto ligado por uma chamada."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"encaminhar chamadas através do sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Permite que a aplicação encaminhe as respetivas chamadas através do sistema de modo a melhorar a experiência da chamada."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"ler os números de telefone"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Permite à aplicação aceder aos números de telefone do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir que o tablet entre em inactividade"</string>
@@ -485,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Moveu o dedo demasiado lentamente. Tente novamente."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Não reconhecido"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impressão digital não disponível."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não é possível armazenar a impressão digital. Remova uma impressão digital existente."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Foi atingido o limite de tempo da impressão digital. Tente novamente."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiadas tentativas. Tente novamente mais tarde."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Demasiadas tentativas. Sensor de impressões digitais desativado."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
@@ -990,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Abrir"</string>
<string name="sms" msgid="4560537514610063430">"Mensagem"</string>
<string name="add_contact" msgid="7867066569670597203">"Adicionar"</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">"Está quase sem espaço de armazenamento"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Algumas funções do sistema poderão não funcionar"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Não existe armazenamento suficiente para o sistema. Certifique-se de que tem 250 MB de espaço livre e reinicie."</string>
@@ -1115,6 +1131,8 @@
<item quantity="one">Rede Wi-Fi aberta disponível</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Ligar à rede Wi-Fi aberta"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"A ligar à rede Wi-Fi aberta…"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Ligado à rede Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Não foi possível ligar à rede Wi-Fi"</string>
@@ -1412,6 +1430,8 @@
<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_restricted_title" msgid="5965157361036321914">"Dados em seg. plano restringidos"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Toque para remover a restrição."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Elevada utilização de dados"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"A sua utilização de dados ao longo dos últimos dias é superior ao normal. Toque para ver a utilização e as definições."</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>
@@ -1688,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Até desativar Não incomodar"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Até ser desativado"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Até desativar Não incomodar"</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">"Reduzir"</string>
@@ -1737,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Todas as regiões"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pesquisa"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Ativar o modo de trabalho?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Esta ação ativa o seu perfil de trabalho, incluindo as aplicações, a sincronização em segundo plano e as funcionalidades relacionadas"</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">"Ativar"</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">"Tem mensagens novas"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Abra a aplicação de SMS para ver"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Algumas funcionalid. limitadas"</string>
@@ -1811,7 +1837,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Não foi possível restaurar o atalho devido a uma falha de correspondência entre as assinaturas das aplicações."</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Não foi possível restaurar o atalho."</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"O atalho está desativado."</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Desinstalar"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Iniciar mesmo assim"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Pretende desinstalar a aplicação prejudicial?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"A aplicação <xliff:g id="APP_0">%1$s</xliff:g> pretende mostrar partes da aplicação <xliff:g id="APP_2">%2$s</xliff:g>."</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Editar"</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 5201f14..11fc517 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opções de TV"</string>
@@ -263,8 +264,8 @@
<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">"Modo de segurança"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Alternar para \"Pessoal\""</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Alternar para \"Trabalho\""</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Deslize até o perfil pessoal"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Alternar para o perfil de trabalho"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatos"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acesse seus contatos"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Permitir que <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> acesse seus contatos"</string>
@@ -416,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que o app acesse os recursos de telefonia do dispositivo. Esta permissão autoriza o app a determinar o número de telefone e IDs de dispositivo, quando uma chamada está ativa, e o número remoto conectado a uma chamada."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"encaminhar chamadas pelo sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Permite que o app encaminhe suas chamadas por meio do sistema para melhorar a experiência com chamadas."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"ler números de telefone"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Permite que o app acesse os número de telefone do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir modo de inatividade do tablet"</string>
@@ -485,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"O movimento do dedo está muito lento. Tente novamente."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Não reconhecido"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware de impressão digital não disponível."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não foi possível armazenar a impressão digital. Remova uma impressão digital já existente."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Operação de impressão digital cancelada pelo usuário."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Excesso de tentativas. Tente novamente mais tarde."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Excesso de tentativas. Sensor de impressão digital desativado."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
@@ -990,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Abrir"</string>
<string name="sms" msgid="4560537514610063430">"Mensagem"</string>
<string name="add_contact" msgid="7867066569670597203">"Adicionar"</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">"Pouco espaço de armazenamento"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Algumas funções do sistema podem não funcionar"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Não há armazenamento suficiente para o sistema. Certifique-se de ter 250 MB de espaço livre e reinicie."</string>
@@ -1115,6 +1128,8 @@
<item quantity="other">Abrir redes Wi-Fi disponíveis</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Conectar-se a uma rede Wi‑Fi aberta"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Conectando-se a uma rede Wi‑Fi aberta"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Conectado a uma rede Wi‑Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Não foi possível conectar-se à rede Wi‑Fi"</string>
@@ -1412,6 +1427,8 @@
<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_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="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>
@@ -1688,7 +1705,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Até que você desative \"Não perturbe\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Até você desativar"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Até que você desative \"Não perturbe\""</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">"Recolher"</string>
@@ -1737,9 +1754,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Todas as regiões"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pesquisa"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Ativar modo de trabalho?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Isso ativará seu perfil de trabalho, incluindo apps, sincronização de segundo plano e recursos relacionados"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Ativar o perfil de trabalho?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Seus apps, notificações, dados e outros recursos do perfil de trabalho serão ativados"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</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">"Você tem mensagens novas"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Abra o app de SMS para ver"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Algumas funcionalidades são limitadas"</string>
@@ -1811,7 +1832,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Não foi possível restaurar o atalho devido à incompatibilidade de assinatura de apps"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Não foi possível restaurar o atalho"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"O atalho está desativado"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Desinstalar"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Iniciar mesmo assim"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Desinstalar app nocivo?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> quer mostrar partes do app <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Editar"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 22b1bde..52995ae 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -183,6 +183,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organizația dvs. gestionează acest dispozitiv și poate monitoriza traficul în rețea. Atingeți pentru mai multe detalii."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Datele de pe dispozitiv vor fi șterse"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Aplicația de administrare nu poate fi utilizată. Dispozitivul va fi șters.\n\nDacă aveți întrebări, contactați administratorul organizației dvs."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Printare dezactivată de <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țiuni tablet PC"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opțiuni TV"</string>
@@ -266,8 +267,8 @@
<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">"Mod sigur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Comutați la Personal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Comutați la Serviciu"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Comutați la profilul personal"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Comutați la profilul de serviciu"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Persoane de contact"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceseze persoanele de contact"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Permiteți <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> să vă acceseze agenda"</string>
@@ -419,6 +420,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite aplicației să acceseze funcțiile de telefon ale dispozitivului. Cu această permisiune aplicația stabilește numărul de telefon și ID-urile de dispozitiv, dacă un apel este activ, precum și numărul de la distanță conectat printr-un apel."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"să direcționeze apelurile prin intermediul sistemului"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Permiteți aplicației să direcționeze apelurile prin intermediul sistemului pentru a îmbunătăți calitatea apelurilor."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"să citească numerele de telefon"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Permite aplicației să acceseze numerele de telefon ale dispozitivului."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"împiedicarea computerului tablet PC să intre în repaus"</string>
@@ -488,10 +493,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Ați mișcat degetul prea lent. Încercați din nou."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nu este recunoscută"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardware-ul pentru amprentă nu este disponibil."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Amprenta nu poate fi stocată. Eliminați o amprentă existentă."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timpul pentru amprentare a expirat. Încercați din nou."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operațiunea privind amprenta a fost anulată."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Operațiunea privind amprenta a fost anulată de utilizator."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Prea multe încercări. Încercați din nou mai târziu."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Prea multe încercări. Senzorul de amprentă este dezactivat."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Încercați din nou."</string>
@@ -1010,6 +1017,12 @@
<string name="browse" msgid="1245903488306147205">"Deschideți"</string>
<string name="sms" msgid="4560537514610063430">"Mesaj"</string>
<string name="add_contact" msgid="7867066569670597203">"Adăugați"</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">"Spațiul de stocare aproape ocupat"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Este posibil ca unele funcții de sistem să nu funcționeze"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Spațiu de stocare insuficient pentru sistem. Asigurați-vă că aveți 250 MB de spațiu liber și reporniți."</string>
@@ -1137,6 +1150,8 @@
<item quantity="one">Rețea Wi-Fi deschisă disponibilă</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Conectați-vă la o rețea Wi‑Fi deschisă"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Se stabilește conexiunea la o rețea Wi‑Fi deschisă"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"S-a realizat conexiunea la rețeaua Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nu s-a putut stabili conexiunea la rețeaua Wi-Fi"</string>
@@ -1435,6 +1450,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> peste limita specificată."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Datele de fundal restricționate"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Atingeți ca să eliminați restricția."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Utilizare mare a datelor"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Utilizarea datelor în ultimele zile este mai mare decât în mod normal. Atingeți pentru a vedea utilizarea și setările."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificat de securitate"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certificatul este valid."</string>
<string name="issued_to" msgid="454239480274921032">"Emis către:"</string>
@@ -1721,7 +1738,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Până la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Până la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (următoarea alarmă)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Până când dezactivați „Nu deranja”"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Până când dezactivați"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Până când dezactivați „Nu deranja”"</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">"Restrângeți"</string>
@@ -1771,9 +1788,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Toate limbile"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Toate regiunile"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Căutați"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Activați modul de serviciu?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Astfel veți activa profilul de serviciu, inclusiv aplicațiile, sincronizarea în fundal și funcțiile asociate"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Activați profilul de serviciu?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Se vor activa aplicațiile dvs. de serviciu, notificările, datele și alte funcții ale profilului de serviciu"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Activați"</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">"Aveți mesaje noi"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Deschideți aplicația pentru SMS-uri ca să vizualizați"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Unele funcții ar putea fi limitate"</string>
@@ -1846,7 +1867,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nu s-a putut restabili comanda rapidă din cauza nepotrivirii semnăturii aplicației"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nu s-a putut restabili comanda rapidă"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Comanda rapidă este dezactivată"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Dezinstalați"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Lansați oricum"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Dezinstalați aplicația dăunătoare?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> vrea să afișeze porțiuni din <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Editați"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 70dc651..0d62e75 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -185,6 +185,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Настройки телевизора"</string>
@@ -269,8 +270,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"Перейти в личный профиль"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Перейти в рабочий профиль"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Разрешите приложению <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> доступ к контактам"</string>
@@ -422,6 +425,10 @@
<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>
@@ -491,10 +498,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Слишком много попыток. Сканер отпечатков пальцев отключен."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Повторите попытку."</string>
@@ -1030,6 +1040,12 @@
<string name="browse" msgid="1245903488306147205">"Открыть"</string>
<string name="sms" msgid="4560537514610063430">"Написать SMS"</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">"Недостаточно свободного места для системы. Освободите не менее 250 МБ дискового пространства и перезапустите устройство."</string>
@@ -1159,6 +1175,8 @@
<item quantity="other">Есть открытые сети Wi-Fi</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Подключитесь к открытой сети Wi‑Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Подключение к открытой сети Wi‑Fi…"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Подключено к сети Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не удалось подключиться к сети Wi‑Fi"</string>
@@ -1458,6 +1476,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Лимит превышен на <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="ssl_certificate" msgid="6510040486049237639">"Сертификат безопасности"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Этот сертификат действителен."</string>
<string name="issued_to" msgid="454239480274921032">"Кому выдан:"</string>
@@ -1754,7 +1774,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Пока вы не отключите режим \"Не беспокоить\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Пока вы не отключите"</string>
<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>
@@ -1805,9 +1825,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Включить рабочий режим?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Вы включите рабочий профиль, в том числе приложения, фоновую синхронизацию и связанные функции."</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Некоторые функции недоступны"</string>
@@ -1881,7 +1907,12 @@
<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>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Удалить"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Запустить все равно"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Удалите опасное приложение"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Приложение \"<xliff:g id="APP_0">%1$s</xliff:g>\" запрашивает разрешение на показ фрагментов приложения \"<xliff:g id="APP_2">%2$s</xliff:g>\"."</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Изменить"</string>
</resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 609f99f..846b0ee 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"රූපවාහිනී විකල්ප"</string>
@@ -263,8 +264,8 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"පුද්ගලික වෙත මාරු වන්න"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"කාර්යාලය වෙත මාරු වන්න"</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"පුද්ගලික පැතිකඩ වෙත මාරුවන්න"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"කාර්යාල පැතිකඩ වෙත මාරු වන්න"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"සම්බන්ධතා"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"ඔබේ සම්බන්ධතාවලට පිවිසෙන්න"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> වෙත ඔබගේ සබඳතා ප්රවේශ කිරීමට අවසර දෙන්න"</string>
@@ -416,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"උපාංගයේ දුරකථන විශේෂාංග වෙත ප්රවේශයට යෙදුමට ඉඩ දෙයි. ඇමතුම සක්රිය වුවත්, සහ ඇමතුමකින් දුරස්ථ අංකය සම්බන්ධ වුවත් දුරකථන අංකය සහ උපාංග ID හඳුනා ගැනීමට මෙම අවසරය යෙදුමට ඉඩ දෙයි."</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>
@@ -485,10 +490,12 @@
<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>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"පරිශීලක විසින් ඇඟිලි සලකුණු මෙහෙයුම අවසන් කරන ලදී."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"උත්සාහයන් ඉතා වැඩි ගණනකි. කරුණාකර පසුව නැවත උත්සාහ කරන්න."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"උත්සාහයන් ඉතා වැඩි ගණනකි. ඇඟිලි සලකුණු සංවේදකය අබල කරන ලදී."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"නැවත උත්සාහ කරන්න."</string>
@@ -992,6 +999,12 @@
<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">"පද්ධතිය සඳහා ප්රමාණවත් ඉඩ නොමැත. ඔබට 250MB නිදහස් ඉඩක් තිබෙන ඔබට තිබෙන බව සහතික කරගෙන නැවත උත්සාහ කරන්න."</string>
@@ -1117,6 +1130,8 @@
<item quantity="other">විවෘත Wi-Fi ජාල තිබේ</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"විවෘත Wi-Fi ජාලය වෙත සම්බන්ධ වෙන්න"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"විවෘත Wi-Fi ජාලය වෙත සම්බන්ධ වෙමින්"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi-Fi ජාලයක් වෙත සම්බන්ධ විය"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi-Fi ජාලයක් වෙත සම්බන්ධ විය නොහැකි විය"</string>
@@ -1414,6 +1429,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"සඳහන් කළ සීමාවට වඩා <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="ssl_certificate" msgid="6510040486049237639">"ආරක්ෂිත සහතිකය"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"මෙම සහතිකය වලංගුයි."</string>
<string name="issued_to" msgid="454239480274921032">"ලබාදුන්නේ:"</string>
@@ -1690,7 +1707,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"බාධා නොකරන්න ඔබ අක්රිය කරන තුරු"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"ඔබ ක්රියාවිරහිත කරන තුරු"</string>
<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>
@@ -1739,9 +1756,13 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"කාර්යාල මෝඩය සක්රිය කරන්නද?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"මෙය මඟින් යෙදුම්, පසුබිම සමමුහුර්ත කිරීම, සහ සම්බන්ධිත විශේෂාංග ඇතුළුව, කාර්යාල පැතිකඩ සක්රිය කෙරේ"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"කාර්යාල පැතිකඩ ක්රියාත්මක කරන්නද?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"ඔබගේ වැඩ යෙදුම්, දැනුම්දීම්, දත්ත සහ වෙනත් කාර්යාල පැතිකඩ විශේෂාංග ක්රියාත්මක කරනු ඇත"</string>
<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>
<string name="user_encrypted_title" msgid="9054897468831672082">"ඇතැම් ක්රියාකාරිත්ව සීමිත විය හැකිය"</string>
@@ -1813,7 +1834,12 @@
<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>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"අස්ථාපනය කරන්න"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"කෙසේ වුවත් ආරම්භ කරන්න"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"හානිකර යෙදුම අස්ථාපනය කරන්නද?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> හට කොටස් <xliff:g id="APP_2">%2$s</xliff:g>ක් පෙන්වීමට අවශ්යයි"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"සංස්කරණය"</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 1fb90ff..8755d94 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -185,6 +185,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Vaša organizácia spravuje toto zariadenie a môže sledovať sieťovú premávku. Klepnutím zobrazíte podrobnosti."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Vaše zariadenie bude vymazané"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Daná aplikácia na správu sa nedá použiť. Vaše zariadenie bude vymazané.\n\nV prípade otázok kontaktujte správcu organizácie."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Tlač zakázala aplikácia <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Možnosti tabletu"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Možnosti televízora"</string>
@@ -221,6 +222,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Tiesňové volanie"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Hlásenie o chybách"</string>
<string name="global_action_logout" msgid="935179188218826050">"Ukončiť reláciu"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Snímka obrazovky"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Vytvoriť hlásenie chyby"</string>
<string name="bugreport_message" msgid="398447048750350456">"Týmto zhromaždíte informácie o aktuálnom stave zariadenia. Informácie je potom možné odoslať e-mailom, chvíľu však potrvá, kým bude hlásenie chyby pripravené na odoslanie. Prosíme vás preto o trpezlivosť."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktívne nahlásenie"</string>
@@ -268,8 +270,10 @@
<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">"Núdzový režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Prepnúť na osobný"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Prepnúť na pracovný"</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">"Kontakty"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"prístup ku kontaktom"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Povoľte aplikácii <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> prístup k vašim kontaktom"</string>
@@ -421,6 +425,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Umožňuje aplikácii pristupovať k telefónnym funkciám zariadenia. Aplikácia s týmto povolením môže určiť telefónne číslo a ID zariadenia, či práve prebieha hovor, a vzdialené číslo, s ktorým je prostredníctvom hovoru nadviazané spojenie."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"presmerovanie hovorov cez systém"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Umožňuje aplikácii presmerovať hovory cez systém na účely zlepšenia kvality hovorov."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"čítanie telefónnych čísel"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Umožňuje aplikácii pristupovať k telefónnym číslam zariadenia."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zabránenie prechodu tabletu do režimu spánku"</string>
@@ -490,10 +498,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Pohli ste prstom príliš pomaly. Skúste to znova."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nebol rozpoznaný"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardvér na snímanie odtlačku prsta nie je k dispozícii"</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Odtlačok prsta nie je možné uložiť. Odstráňte existujúci odtlačok."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit rozpoznania odtlačku vypršal. Skúste to znova."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Príliš veľa pokusov. Senzor odtlačkov prstov bol deaktivovaný."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Skúste to znova"</string>
@@ -1029,6 +1040,12 @@
<string name="browse" msgid="1245903488306147205">"Otvoriť"</string>
<string name="sms" msgid="4560537514610063430">"Správa"</string>
<string name="add_contact" msgid="7867066569670597203">"Pridať"</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">"Nedostatok ukladacieho priestoru"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Niektoré systémové funkcie nemusia fungovať"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"V úložisku nie je dostatok voľného miesta pre systém. Zaistite, aby ste mali 250 MB voľného miesta a zariadenie reštartujte."</string>
@@ -1158,6 +1175,8 @@
<item quantity="one">K dispozícii je verejná sieť Wi‑Fi</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Pripojenie k otvorenej sieti Wi‑Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Pripája sa k otvorenej sieti Wi‑Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Pripojenie k sieti Wi‑Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"K sieti Wi‑Fi sa nepodarilo pripojiť"</string>
@@ -1167,6 +1186,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi sa zapne automaticky"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Keď budete v blízkosti kvalitnej uloženej siete"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Znova nezapínať"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Pripojenie Wi‑Fi sa zaplo automaticky"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Ste v blízkosti uloženej siete: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prihlásiť sa do siete Wi‑Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prihlásenie do siete"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1455,6 +1476,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> nad stanovenou hranicou."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Dátové prenosy obmedzené"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Klepnutím odstránite obmedzenie."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Vysoká spotreba dát"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Vaša spotreba dát za niekoľko posledných dní je vyššia ako zvyčajne. Klepnutím zobrazíte spotrebu a nastavenia."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certifikát zabezpečenia"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certifikát je platný."</string>
<string name="issued_to" msgid="454239480274921032">"Vydané pre:"</string>
@@ -1751,7 +1774,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ďalší budík)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Dokiaľ nevypnete režim Nerušiť"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Dokiaľ túto funkciu nevypnete"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokiaľ nevypnete režim Nerušiť"</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">"Zbaliť"</string>
@@ -1802,9 +1825,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Všetky jazyky"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Všetky regióny"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Vyhľadávanie"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Aktivovať pracovný režim?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Týmto aktivujete pracovný profil vrátane aplikácií, synchronizácie na pozadí a súvisiacich funkcií"</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">"Zapnúť"</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">"Máte nové správy."</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorte aplikáciu pre SMS a zobrazte správu"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Niektoré funkcie môžu byť obmedzené"</string>
@@ -1877,6 +1906,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Odkaz sa nepodarilo obnoviť, pretože aplikácia nepodporuje zálohovanie a obnovu"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Odkaz sa nepodarilo obnoviť pre nesúlad podpisov aplikácie"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Odkaz sa nepodarilo obnoviť"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Skratka je zakázaná"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> chce zobrazovať rezy z aplikácie <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Upraviť"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 3c89e75..5657fe5 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -185,6 +185,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Vaša organizacija upravlja to napravo in lahko nadzira omrežni promet. Dotaknite se za podrobnosti."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Podatki v napravi bodo izbrisani"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Skrbniške aplikacije ni mogoče uporabljati. Podatki v napravi bodo izbrisani.\n\nČe imate vprašanja, se obrnite na skrbnika organizacije."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Tiskanje je onemogočil pravilnik <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Jaz"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Možnosti tabličnega računalnika"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Možnosti televizorja"</string>
@@ -269,8 +270,10 @@
<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">"Varni način"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Preklop na osebni profil"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Preklop na delovni profil"</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">"Stiki"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"dostop do stikov"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> omogočite dostop do stikov"</string>
@@ -422,6 +425,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Aplikaciji omogoča dostop do funkcij telefona v napravi. S tem dovoljenjem lahko aplikacija določi telefonsko številko in ID-je naprave, določi lahko tudi, ali je klic aktiven, in oddaljeno številko, s katero je klic povezan."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"Usmeri klice prek sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Dovoli, da aplikacija usmeri klice prek sistema, da se tako izboljša izkušnja klicanja."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"branje telefonskih številk"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Aplikaciji dovoljuje dostop do telefonskih številk v napravi."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"preprečitev prehoda tabličnega računalnika v stanje pripravljenosti"</string>
@@ -491,10 +498,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Prepočasen premik prsta. Poskusite znova."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Ni prepoznano"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Strojna oprema za prstne odtise ni na voljo."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Prstnega odtisa ni mogoče shraniti. Odstranite obstoječi prstni odtis."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Dosežena časovna omejitev za prstni odtis. Poskusite znova."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Dejanje s prstnim odtisom je bilo preklicano."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Preveč poskusov. Poskusite znova pozneje."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Preveč poskusov. Tipalo prstnih odtisov je onemogočeno."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Poskusite znova."</string>
@@ -1030,6 +1040,12 @@
<string name="browse" msgid="1245903488306147205">"Odpri"</string>
<string name="sms" msgid="4560537514610063430">"Sporočilo"</string>
<string name="add_contact" msgid="7867066569670597203">"Dodaj"</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">"Prostor za shranjevanje bo pošel"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Nekatere sistemske funkcije morda ne delujejo"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"V shrambi ni dovolj prostora za sistem. Sprostite 250 MB prostora in znova zaženite napravo."</string>
@@ -1159,6 +1175,8 @@
<item quantity="other">Na voljo so odprta omrežja Wi-Fi</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Vzpostavite povezavo z odprtim omrežjem Wi‑Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Vzpostavljanje povezave z odprtim omrežjem Wi‑Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Povezava z omrežjem Wi-Fi je vzpostavljena"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Povezave z omrežjem Wi-Fi ni bilo mogoče vzpostaviti"</string>
@@ -1458,6 +1476,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Velikost <xliff:g id="SIZE">%s</xliff:g> presega omejitev"</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Podatki v ozadju so omejeni"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Dotaknite se za odstr. omejitve."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Velika prenesena količina podatkov"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Prenesena količina podatkov v zadnjih nekaj dneh je večja kot običajno. Dotaknite se za ogled uporabe in nastavitev."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Varnostno potrdilo"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"To potrdilo je veljavno."</string>
<string name="issued_to" msgid="454239480274921032">"Izdano za:"</string>
@@ -1754,7 +1774,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (naslednji alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Dokler ne izklopite načina »ne moti«"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Dokler ne izklopite"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokler ne izklopite načina »ne moti«"</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">"Strni"</string>
@@ -1805,9 +1825,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Vsi jeziki"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Vse regije"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Išči"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Želite vklopiti delovni način?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"S tem bo vklopljen delovni profil, vključno z aplikacijami, sinhronizacijo v ozadju in povezanimi funkcijami."</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">"Vklop"</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">"Imate nova sporočila."</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Za ogled odprite aplikacijo za SMS-je"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Nekatere funkcije bodo omejene"</string>
@@ -1881,7 +1907,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Bližnjice ni bilo mogoče obnoviti zaradi neujemanja podpisa aplikacije"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Bližnjice ni bilo mogoče obnoviti"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Bližnjica je onemogočena"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Odstrani"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Vseeno zaženi"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Želite odstraniti škodljivo aplikacijo?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Aplikacija <xliff:g id="APP_0">%1$s</xliff:g> želi prikazati izreze aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Urejanje"</string>
</resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index e6d60d4..8309fe9 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organizata jote e menaxhon këtë pajisje dhe mund të monitorojë trafikun e rrjetit. Trokit për detaje."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Pajisja do të spastrohet"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Aplikacioni i administratorit nuk mund të përdoret. Pajisja jote tani do të fshihet.\n\nNëse ke pyetje, kontakto me administratorin e organizatës."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Printimi është çaktivizuar nga <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Unë"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opsionet e tabletit"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opsionet e televizorit"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Urgjenca"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Raporti i defekteve në kod"</string>
<string name="global_action_logout" msgid="935179188218826050">"Jepi fund sesionit"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Pamja e ekranit"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Merr raportin e defekteve në kod"</string>
<string name="bugreport_message" msgid="398447048750350456">"Ky funksion mundëson mbledhjen e informacioneve mbi gjendjen aktuale të pajisjes për ta dërguar si mesazh mail-i. Do të duhet pak kohë nga nisja e raportit të defekteve në kod. Faleminderit për durimin."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Raport interaktiv"</string>
@@ -262,8 +264,8 @@
<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">"Modaliteti i sigurisë"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistemi Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Ndryshoje te \"Personale\""</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Ndryshoje te \"Puna\""</string>
+ <string name="user_owner_label" msgid="8836124313744349203">"Kalo te profili personal"</string>
+ <string name="managed_profile_label" msgid="8947929265267690522">"Kalo te profili i punës"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktet"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"qasu te kontaktet e tua"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Lejo që <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> të ketë qasje te kontaktet e tua"</string>
@@ -415,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lejon aplikacionin të hyjë në funksionet telefonike të pajisjes. Kjo leje i mundëson aplikacionit të përcaktojë numrin e telefonit dhe ID-të e pajisjes, nëse një telefonatë është aktive apo nëse numri në distancë është i lidhur me një telefonatë."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"kalon telefonatat përmes sistemit"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Lejon që aplikacioni të kalojë telefonatat përmes sistemit për të përmirësuar përvojën e telefonatës."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"lexo numrat e telefonit"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Lejon që aplikacioni të ketë qasje te numrat e telefonit të pajisjes."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"parandalo kalimin e tabletit në fjetje"</string>
@@ -484,10 +490,12 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Gishti lëvizi shumë ngadalë. Provo përsëri."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nuk njihet"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardueri i gjurmës së gishtit nuk mundësohet."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Gjurma e gishtit nuk mund të ruhet. Hiq një gjurmë gishti ekzistuese."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Koha e veprimit për gjurmën e gishtit skadoi. Provo përsëri."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operacioni i gjurmës së gishtit u anulua."</string>
+ <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Veprimi i gjurmës së gishtit u anulua nga përdoruesi."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Keni bërë shumë tentativa. Provo përsëri më vonë."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Shumë përpjekje. Sensori i gjurmës së gishtit u çaktivizua."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Provo përsëri."</string>
@@ -989,6 +997,12 @@
<string name="browse" msgid="1245903488306147205">"Hap"</string>
<string name="sms" msgid="4560537514610063430">"Mesazh"</string>
<string name="add_contact" msgid="7867066569670597203">"Shto"</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">"Hapësira ruajtëse po mbaron"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Disa funksione të sistemit mund të mos punojnë"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nuk ka hapësirë të mjaftueshme ruajtjeje për sistemin. Sigurohu që të kesh 250 MB hapësirë të lirë dhe pastaj të rifillosh."</string>
@@ -1114,6 +1128,8 @@
<item quantity="one">Rrjet i hapur Wi-Fi në përdorim</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Lidhu me rrjetin e hapur Wi‑Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Po lidhet me rrjetin e hapur Wi‑Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Lidhur me rrjetin e hapur Wi‑Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nuk mund të lidhet me rrjetin Wi‑Fi"</string>
@@ -1123,6 +1139,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi do të aktivizohet automatikisht"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kur ndodhesh pranë një rrjeti të ruajtur me cilësi të lartë"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Mos e aktivizo përsëri"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi u aktivizua automatikisht"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Ndodhesh pranë një rrjeti të ruajtur: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Identifikohu në rrjetin Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Identifikohu në rrjet"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1410,6 +1428,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> mbi kufirin e përcaktuar."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Të dhënat e sfondit janë të kufizuara"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Trokit për të hequr kufizimin."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Përdorim i madh të dhënash"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Përdorimi i të dhënave të tua gjatë ditëve të fundit është më i madh se normalisht. Trokit për të parë përdorimin dhe cilësimet."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certifikatë sigurie"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certifikata është e vlefshme."</string>
<string name="issued_to" msgid="454239480274921032">"Lëshuar për:"</string>
@@ -1686,7 +1706,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Deri në <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Deri në <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarmi tjetër)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Deri sa të çaktivizosh \"Mos shqetëso\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Derisa ta çaktivizosh"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Deri sa të çaktivizosh gjendjen \"Mos shqetëso\""</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">"Shpalos"</string>
@@ -1735,9 +1755,13 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Të gjitha gjuhët"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Të gjitha rajonet"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Kërko"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Të aktivizohet modaliteti i punës?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Kjo do të aktivizojë profilin tënd të punës, duke përfshirë aplikacionet, sinkronizimin në sfond dhe funksionet e lidhura"</string>
+ <string name="work_mode_off_title" msgid="1118691887588435530">"Të aktivizohet profili i punës?"</string>
+ <string name="work_mode_off_message" msgid="5130856710614337649">"Aplikacionet e punës, njoftimet, të dhënat e tua dhe funksionet e tjera të profilit të punës do të aktivizohen"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivizo"</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">"Ke mesazhe të reja"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Hap aplikacionin SMS për ta parë"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Disa funksione mund të jenë të kufizuara"</string>
@@ -1808,6 +1832,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Nuk mund të restaurohej shkurtorja sepse aplikacioni nuk mbështet rezervimin dhe restaurimin"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Nuk mund të restaurohej shkurtorja për shkak të mospërputhjes së nënshkrimit të aplikacionit"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Nuk mund të restaurohej shkurtorja"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Shkurtorja është çaktivizuar"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> dëshiron të shfaqë pjesë të <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Modifiko"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 275db37..3dfebf5 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -183,6 +183,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Опције за ТВ"</string>
@@ -219,6 +220,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Снимак екрана"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Направи извештај о грешци"</string>
<string name="bugreport_message" msgid="398447048750350456">"Овим ће се прикупити информације о тренутном стању уређаја како би биле послате у поруци е-поште. Од започињања извештаја о грешци до тренутка за његово слање проћи ће неко време; будите стрпљиви."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактив. извештај"</string>
@@ -265,8 +267,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"Пређи на Лични профил"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Пређи на профил за Work"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Дозволите да <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> приступа контактима"</string>
@@ -418,6 +422,10 @@
<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>
@@ -487,10 +495,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Превише покушаја. Сензор за отисак прста је онемогућен."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Пробајте поново."</string>
@@ -1009,6 +1020,12 @@
<string name="browse" msgid="1245903488306147205">"Отвори"</string>
<string name="sms" msgid="4560537514610063430">"Пошаљи SMS"</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">"Нема довољно меморијског простора за систем. Уверите се да имате 250 MB слободног простора и поново покрените."</string>
@@ -1136,6 +1153,8 @@
<item quantity="other">Отворене Wi-Fi мреже су доступне</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Повежите се са отвореном Wi‑Fi мрежом"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Повезујете се са отвореном Wi‑Fi мрежом"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Повезали сте се са Wi‑Fi мрежом"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Повезивање са Wi‑Fi мрежом није успело"</string>
@@ -1145,6 +1164,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi је аутоматски укључен"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"У близини сте сачуване мреже: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Пријављивање на Wi-Fi мрежу"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Пријавите се на мрежу"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1432,6 +1453,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"Безбедносни сертификат"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Овај сертификат је важећи."</string>
<string name="issued_to" msgid="454239480274921032">"Издато за:"</string>
@@ -1718,7 +1741,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Док не искључите режим Не узнемиравај"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Док не искључите"</string>
<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>
@@ -1768,9 +1791,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Укључити режим за Work?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Ово ће укључити профил за Work, укључујући апликације, синхронизацију у позадини и сродне функције."</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Неке функције су можда ограничене"</string>
@@ -1842,6 +1871,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Апликација <xliff:g id="APP_0">%1$s</xliff:g> жели да приказује исечке из апликације <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Измени"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 1633e43..fee1a32 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Organisationen hanterar den här enheten och kan övervaka nätverkstrafiken. Tryck om du vill veta mer."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Enheten kommer att rensas"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Det går inte att använda administratörsappen. Enheten rensas.\n\nKontakta organisationens administratör om du har några frågor."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Utskrift har inaktiverats av <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Jag"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Alternativ för surfplattan"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV-alternativ"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Nödsituation"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Felrapport"</string>
<string name="global_action_logout" msgid="935179188218826050">"Avsluta session"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Skärmdump"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Skapa felrapport"</string>
<string name="bugreport_message" msgid="398447048750350456">"Nu hämtas information om aktuell status för enheten, som sedan skickas i ett e-postmeddelade. Det tar en liten stund innan felrapporten är färdig och kan skickas, så vi ber dig ha tålamod."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv rapport"</string>
@@ -262,8 +264,10 @@
<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">"Säkert läge"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Byt till din personliga profil"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Byt till jobbprofilen"</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">"Kontakter"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"få tillgång till dina kontakter"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Ge <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> åtkomstbehörighet till dina kontakter"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Tillåter att appen kommer åt enhetens telefonfunktioner. Med den här behörigheten tillåts appen att identifiera mobilens telefonnummer och enhets-ID, om ett samtal pågår och vilket nummer samtalet är kopplat till."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"dirigera samtal via systemet"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Appen tillåts att dirigera samtal via systemet för att förbättra samtalsupplevelsen."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"läsa telefonnummer"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Appen beviljas åtkomst till enhetens telefonnummer."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"förhindra att surfplattan går in i viloläge"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Du rörde fingret för långsamt. Försök igen."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Identifierades inte"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Det finns ingen maskinvara för fingeravtryck."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeravtrycket kan inte lagras. Ta bort ett befintligt fingeravtryck."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsgränsen för fingeravtrycket har uppnåtts. Försök igen."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeravtrycksåtgärden avbröts."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Du har gjort för många försök. Försök igen senare."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Du har försökt för många gånger. Fingeravtryckssensorn har inaktiverats."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Försök igen."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Öppna"</string>
<string name="sms" msgid="4560537514610063430">"Sms:a"</string>
<string name="add_contact" msgid="7867066569670597203">"Lägg till"</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">"Lagringsutrymmet börjar ta slut"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Det kan hända att vissa systemfunktioner inte fungerar"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Det finns inte tillräckligt med utrymme för systemet. Kontrollera att du har ett lagringsutrymme på minst 250 MB och starta om."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Öppet Wi-Fi-nätverk är tillgängligt</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Anslut till ett öppet Wi-Fi-nätverk"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ansluter till ett öppet Wi-Fi-nätverk"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Ansluten till Wi-Fi-nätverket"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Det gick inte att ansluta till Wi‑Fi-nätverket"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi aktiveras automatiskt"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"När du är i närheten av ett sparat nätverk av hög kvalitet"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Återaktivera inte"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi-Fi aktiverades automatiskt"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Du är i närheten av ett sparat nätverk: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Logga in på ett Wi-Fi-nätverk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Logga in på nätverket"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> över angiven gräns."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Bakgrundsdata är begränsade"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Ta bort begränsning."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Hög dataanvändning"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Dataanvändningen har varit högre än vanligt under de senaste dagarna. Om du trycker här visas användningen och inställningarna."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Säkerhetscertifikat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certifikatet är giltigt."</string>
<string name="issued_to" msgid="454239480274921032">"Utfärdad till:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Till kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Till <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nästa alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Tills du inaktiverar Stör ej"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Tills du stänger av"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Tills du inaktiverar Stör ej"</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">"Komprimera"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Alla språk"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Alla regioner"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Söka"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Vill du aktivera jobbläge?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Detta aktiverar jobbprofilen, inklusive appar, bakgrundssynkronisering och tillhörande funktioner"</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">"Aktivera"</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">"Du har nya meddelanden"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Öppna sms-appen och visa meddelandet"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Vissa funktioner är begränsade"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Det gick inte att återställa genvägen eftersom appen inte har stöd för säkerhetskopiering och återställning"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Det gick inte att återställa genvägen eftersom appens signatur inte stämmer"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Det gick inte att återställa genvägen"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Genvägen är inaktiverad"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> vill kunna visa bitar av <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Redigera"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 748f812..32d91ea 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -179,6 +179,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Shirika lako linadhibiti kifaa hiki na huenda likafuatilia shughuli kwenye mtandao. Gusa ili upate maelezo zaidi."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Data iliyomo kwenye kifaa chako itafutwa"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Huwezi kutumia programu ya msimamizi. Sasa data iliyo kwenye kifaa chako itafutwa.\n\nIkiwa una maswali yoyote, wasiliana na msimamizi wa shirika lako."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Kipengele cha kuchapisha kimezimwa na <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Mimi"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Chaguo za kompyuta ndogo"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Chaguo za runinga"</string>
@@ -261,8 +262,10 @@
<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">"Mtindo salama"</string>
<string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Badili uweke wasifu wa Binafsi"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Badili uweke wasifu wa Kazini"</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">"Anwani"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"ifikie anwani zako"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Ruhusu <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ifikie anwani zako"</string>
@@ -414,6 +417,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Huruhusu programu kufikia vipengele vya simu vilivyo kwenye kifaa. Idhini hii inaruhusu programu kutambua nambari ya simu na kifaa, kama kuna simu inayopigwa, na nambari ya mbali iliyounganishwa kwenye simu."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"elekeza simu kupitia mfumo"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Huruhusu programu kuelekeza simu zake kupitia mfumo ili kuboresha hali ya kupiga simu."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"kusoma nambari za simu"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Inaruhusu programu kufikia nambari za simu zilizo kwenye kifaa."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zuia kompyuta ndogo dhidi ya kulala"</string>
@@ -483,10 +490,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Kidole kilisogezwa polepole zaidi. Tafadhali jaribu tena."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Haitambuliwi"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Maunzi ya kitambulisho hayapatikani."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Kitambulisho hakiwezi kuhifadhiwa. Tafadhali ondoa kitambulisho kilichopo."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Muda wa kitambulisho umekwisha. Jaribu tena."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Utendaji wa kitambulisho imeghairiwa."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Majaribio mengi mno. Jaribu tena baadaye."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Majaribio mengi mno. Kitambua alama ya kidole kimezimwa."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Jaribu tena."</string>
@@ -988,6 +998,12 @@
<string name="browse" msgid="1245903488306147205">"Fungua"</string>
<string name="sms" msgid="4560537514610063430">"Ujumbe"</string>
<string name="add_contact" msgid="7867066569670597203">"Ongeza"</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">"Nafasi ya kuhifadhi inakaribia kujaa"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Baadhi ya vipengee vya mfumo huenda visifanye kazi"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Hifadhi haitoshi kwa ajili ya mfumo. Hakikisha una MB 250 za nafasi ya hifadhi isiyotumika na uanzishe upya."</string>
@@ -1113,6 +1129,8 @@
<item quantity="one">Fungua mtandao wa Wi-Fi unaopatikana</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Unganisha kwenye mtandao wa Wi‑Fi unaotumiwa na mtu yeyote"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Inaunganisha kwenye mtandao wa Wi‑Fi unaotumiwa na mtu yeyote"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Imeunganisha kwenye mtandao wa Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Imeshindwa kuunganisha kwenye mtandao wa Wi‑Fi"</string>
@@ -1410,6 +1428,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> juu ya kikomo kilichobainishwa."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Data ya mandhari nyuma imezuiwa"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Gusa ili uondoe kizuizi."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Matumizi ya data nyingi"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Umetumia data nyingi mno katika siku chache zilizopita. Gusa ili uangalie matumizi na mipangilio."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Cheti cha usalama"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Cheti hiki ni halali."</string>
<string name="issued_to" msgid="454239480274921032">"Kimetolewa kwa:"</string>
@@ -1686,7 +1706,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hadi <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Mpaka <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (kengele inayofuata)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Hadi utakapozima hali ya Usinisumbue"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Hadi utakapoizima"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hadi utakapozima Usinisumbue"</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">"Kunja"</string>
@@ -1735,9 +1755,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Lugha zote"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Maeneo yote"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Tafuta"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Ungependa kuwasha hali ya kazini?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Hatua hii itafungua wasifu wa kazini, ikiwa ni pamoja na programu, usawazishaji wa chini chini na vipengele husika"</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">"Washa"</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">"Una ujumbe mpya"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Fungua programu ya SMS ili uweze kuangalia"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Huenda baadhi ya vipengele havifanyi kazi"</string>
@@ -1809,7 +1835,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Imeshindwa kurejesha njia ya mkato kwa sababu ufunguo wako wa kuambatisha cheti kwenye programu haulingani"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Imeshindwa kurejesha njia ya mkato"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Njia ya mkato imezimwa"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Ondoa"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Fungua tu"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Ungependa kuondoa programu hatari?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> inataka kuonyesha vipengee <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Badilisha"</string>
</resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 6014de4..3afdebd 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"டிவி விருப்பங்கள்"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"ஸ்கிரீன் ஷாட்"</string>
<string name="bugreport_title" msgid="2667494803742548533">"பிழை அறிக்கையை எடு"</string>
<string name="bugreport_message" msgid="398447048750350456">"உங்கள் நடப்புச் சாதன நிலையை மின்னஞ்சல் செய்தியாக அனுப்ப, அது குறித்த தகவலை இது சேகரிக்கும். பிழை அறிக்கையைத் தொடங்குவதில் இருந்து, அது அனுப்புவதற்குத் தயாராகும் வரை, இதற்குச் சிறிது நேரம் ஆகும்; பொறுமையாகக் காத்திருக்கவும்."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ஊடாடத்தக்க அறிக்கை"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"தனிப்பட்ட சுயவிவரத்திற்கு மாறு"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"பணிச் சுயவிவரத்திற்கு மாறு"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"தொடர்புகளை அணுக, <b><xliff:g id="APP_NAME">%1$s</xliff:g></b>க்கு அனுமதி வழங்கவும்"</string>
@@ -415,6 +419,10 @@
<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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"பலமுறை முயன்றுவிட்டீர்கள். கைரேகை சென்சார் முடக்கப்பட்டது."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"மீண்டும் முயற்சிக்கவும்."</string>
@@ -989,6 +1000,12 @@
<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">"முறைமையில் போதுமான சேமிப்பகம் இல்லை. 250மெ.பை. அளவு காலி இடவசதி இருப்பதை உறுதிசெய்து மீண்டும் தொடங்கவும்."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">பொது வைஃபை நெட்வொர்க் உள்ளது</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>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"வைஃபை தானாகவே ஆன் செய்யப்பட்டது"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> என்ற சேமிக்கப்பட்ட நெட்வொர்க் அருகில் உள்ளீர்கள்"</string>
<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) -->
@@ -1410,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"குறிப்பிட்ட வரம்பைவிட <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="ssl_certificate" msgid="6510040486049237639">"பாதுகாப்பு சான்றிதழ்"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"இந்தச் சான்றிதழ் சரியானது."</string>
<string name="issued_to" msgid="454239480274921032">"இதற்கு வழங்கப்பட்டது:"</string>
@@ -1686,7 +1709,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"\'தொந்தரவு செய்யாதே\' என்பதை முடக்கும் வரை"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"ஆஃப் செய்யும் வரை"</string>
<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>
@@ -1735,9 +1758,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"பணிப் பயன்முறையை இயக்கவா?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"இவ்வாறு செய்தால், உங்கள் பணி விவரம் இயக்கப்படும். இதில் பயன்பாடுகள், பின்னணி ஒத்திசைவு, தொடர்புடைய அம்சங்கள் ஆகியவை அடங்கும்"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"சில செயல்பாடு வரம்பிடப்பட்டிருக்கலாம்"</string>
@@ -1808,6 +1837,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_2">%2$s</xliff:g> பயன்பாட்டின் விழிப்பூட்டல்களைக் காண்பிக்க, <xliff:g id="APP_0">%1$s</xliff:g> அனுமதி கேட்கிறது"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"திருத்து"</string>
</resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 589ac91..183b3a2 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"టీవీ ఎంపికలు"</string>
@@ -217,8 +218,7 @@
<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="global_action_screenshot" msgid="8329831278085426283">"స్క్రీన్షాట్"</string>
<string name="bugreport_title" msgid="2667494803742548533">"బగ్ నివేదికను సిద్ధం చేయి"</string>
<string name="bugreport_message" msgid="398447048750350456">"ఇది ఇ-మెయిల్ సందేశం రూపంలో పంపడానికి మీ ప్రస్తుత పరికర స్థితి గురించి సమాచారాన్ని సేకరిస్తుంది. బగ్ నివేదికను ప్రారంభించడం మొదలుకొని పంపడానికి సిద్ధం చేసే వరకు ఇందుకు కొంత సమయం పడుతుంది; దయచేసి ఓపిక పట్టండి."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ప్రభావశీల నివేదిక"</string>
@@ -264,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"వ్యక్తిగతానికి మార్చు"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"కార్యాలయానికి మార్చు"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, మీ పరిచయాలను యాక్సెస్ చేయండి"</string>
@@ -417,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"పరికరం యొక్క ఫోన్ ఫీచర్లను యాక్సెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి ఫోన్ నంబర్ మరియు పరికరం IDలను, కాల్ సక్రియంగా ఉందా లేదా అనే విషయాన్ని మరియు కాల్ ద్వారా కనెక్ట్ చేయబడిన రిమోట్ నంబర్ను కనుగొనడానికి యాప్ను అనుమతిస్తుంది."</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>
@@ -486,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"అనేకసార్లు ప్రయత్నించారు. వేలిముద్ర సెన్సార్ నిలిపివేయబడింది."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"మళ్లీ ప్రయత్నించండి."</string>
@@ -991,6 +1000,12 @@
<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">"సిస్టమ్ కోసం తగినంత నిల్వ లేదు. మీకు 250MB ఖాళీ స్థలం ఉందని నిర్ధారించుకుని, పునఃప్రారంభించండి."</string>
@@ -1116,6 +1131,8 @@
<item quantity="one">ఓపెన్ Wi-Fi నెట్వర్క్ అందుబాటులో ఉంది</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"బహిరంగ Wi‑Fi నెట్వర్క్కు కనెక్ట్ చేయండి"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"బహిరంగ Wi‑Fi నెట్వర్క్కు కనెక్ట్ చేస్తోంది"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi నెట్వర్క్కు కనెక్ట్ చేయబడింది"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi నెట్వర్క్కు కనెక్ట్ చేయడం సాధ్యపడలేదు"</string>
@@ -1125,10 +1142,8 @@
<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>
- <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
- <skip />
- <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
- <skip />
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi‑Fi స్వయంచాలకంగా ఆన్ చేయబడింది"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"మీరు సేవ్ చేసిన నెట్వర్క్కి సమీపంలో ఉన్నారు: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi నెట్వర్క్కి సైన్ ఇన్ చేయండి"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"నెట్వర్క్కి సైన్ ఇన్ చేయండి"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"పేర్కొన్న పరిమితి కంటే <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="ssl_certificate" msgid="6510040486049237639">"భద్రతా సర్టిఫికెట్"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ఈ సర్టిఫికెట్ చెల్లుబాటు అవుతుంది."</string>
<string name="issued_to" msgid="454239480274921032">"దీనికి జారీ చేయబడింది:"</string>
@@ -1692,7 +1709,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"మీరు అంతరాయం కలిగించవద్దు ఎంపిక ఆఫ్ చేసే వరకు"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"మీరు ఆఫ్చేసే వరకు"</string>
<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>
@@ -1741,9 +1758,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"కార్యాలయ మోడ్ని ఆన్ చేయాలా?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"ఇది అనువర్తనాలు, నేపథ్య సమకాలీకరణ మరియు సంబంధిత లక్షణాలతో సహా మీ కార్యాలయ ప్రొఫైల్ను ఆన్ చేస్తుంది"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"కొంత పనితనం పరిమితం కావచ్చు"</string>
@@ -1815,10 +1838,12 @@
<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 (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> <xliff:g id="APP_2">%2$s</xliff:g> స్లైస్లను చూపించాలనుకుంటోంది"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"సవరించు"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index d9a504b..2d85094 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"ตัวเลือกทีวี"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"ภาพหน้าจอ"</string>
<string name="bugreport_title" msgid="2667494803742548533">"ใช้รายงานข้อบกพร่อง"</string>
<string name="bugreport_message" msgid="398447048750350456">"การดำเนินการนี้จะรวบรวมข้อมูลเกี่ยวกับสถานะปัจจุบันของอุปกรณ์ของคุณ โดยจะส่งไปในรูปแบบข้อความอีเมล อาจใช้เวลาสักครู่ตั้งแต่เริ่มการสร้างรายงานข้อบกพร่องจนกระทั่งเสร็จสมบูรณ์ โปรดอดทนรอ"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"รายงานแบบอินเทอร์แอกทีฟ"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"เปลี่ยนไปใช้โปรไฟล์ส่วนตัว"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"เปลี่ยนไปใช้โปรไฟล์งาน"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"อนุญาตให้ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> เข้าถึงรายชื่อติดต่อของคุณ"</string>
@@ -415,6 +419,10 @@
<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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ลองหลายครั้งเกินไป ปิดใช้เซ็นเซอร์ลายนิ้วมือแล้ว"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ลองอีกครั้ง"</string>
@@ -989,6 +1000,12 @@
<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">"พื้นที่เก็บข้อมูลไม่เพียงพอสำหรับระบบ โปรดตรวจสอบว่าคุณมีพื้นที่ว่าง 250 MB แล้วรีสตาร์ท"</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">มี 1 เครือข่าย Wi-Fi สาธารณะที่ใช้งานได้</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"เชื่อมต่อเครือข่าย Wi‑Fi แบบเปิด"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"กำลังเชื่อมต่อเครือข่าย Wi‑Fi แบบเปิด"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"เชื่อมต่อเครือข่าย Wi-Fi แล้ว"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ไม่สามารถเชื่อมต่อเครือข่าย Wi‑Fi"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"เปิด Wi‑Fi โดยอัตโนมัติแล้ว"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"คุณอยู่ใกล้เครือข่ายที่บันทึกไว้ ซึ่งก็คือ <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ลงชื่อเข้าใช้เครือข่าย WiFi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ลงชื่อเข้าใช้เครือข่าย"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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">"ปริมาณการใช้อินเทอร์เน็ตในช่วง 2-3 วันที่ผ่านมาสูงกว่าปกติ แตะเพื่อดูปริมาณการใช้และการตั้งค่า"</string>
<string name="ssl_certificate" msgid="6510040486049237639">"ใบรับรองความปลอดภัย"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ใบรับรองนี้ใช้งานได้"</string>
<string name="issued_to" msgid="454239480274921032">"ออกให้แก่:"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"จนกว่าคุณจะปิดห้ามรบกวน"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"จนกว่าคุณจะปิด"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"เปิดโหมดงานไหม"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"การดำเนินการนี้จะเปิดโปรไฟล์งานของคุณ รวมถึงแอป การซิงค์ในพื้นหลัง และฟีเจอร์ที่เกี่ยวข้อง"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"อาจมีข้อจำกัดในบางฟังก์ชัน"</string>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> ต้องการแสดงส่วนต่างๆ ของ <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"แก้ไข"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 98e169e..cf185a4 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Pinamamahalaan ng iyong organisasyon ang device na ito, at maaari nitong subaybayan ang trapiko sa network. I-tap para sa mga detalye."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Buburahin ang iyong device"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Hindi magagamit ang admin app. Mabubura na ang iyong device.\n\nKung mayroon kang mga tanong, makipag-ugnayan sa admin ng iyong organisasyon."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Na-disable ng <xliff:g id="OWNER_APP">%s</xliff:g> ang pag-print."</string>
<string name="me" msgid="6545696007631404292">"Ako"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Mga pagpipilian sa tablet"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Mga opsyon sa TV"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Emergency"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Ulat sa bug"</string>
<string name="global_action_logout" msgid="935179188218826050">"Tapusin ang session"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Kunin ang ulat sa bug"</string>
<string name="bugreport_message" msgid="398447048750350456">"Mangongolekta ito ng impormasyon tungkol sa kasalukuyang katayuan ng iyong device, na ipapadala bilang mensaheng e-mail. Gugugol ito ng kaunting oras mula sa pagsisimula ng ulat sa bug hanggang sa handa na itong maipadala; mangyaring magpasensya."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactive na ulat"</string>
@@ -262,8 +264,10 @@
<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">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Lumipat sa Personal"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Lumipat sa para sa Trabaho"</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">"Mga Contact"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"i-access ang iyong mga contact"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Payagan ang <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> na i-access ang iyong mga contact"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Pinapayagan ang app na i-access ang mga tampok ng telepono ng device. Pinapayagan ng pahintulot na ito ang app na tukuyin ang numero ng telepono at mga ID ng device, kung aktibo man ang isang tawag, at ang malayuang numerong ikinonekta ng isang tawag."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"iruta ang mga tawag sa pamamagitan ng system"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Pinapayagan ang app na iruta ang mga tawag nito sa pamamagitan ng system upang mapahusay ang karanasan sa pagtawag."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"basahin ang mga numero ng telepono"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Pinapayagan ang app na i-access ang mga numero ng telepono ng device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"pigilan ang tablet mula sa pag-sleep"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Masyadong mabagal ang paggalaw ng daliri. Pakisubukang muli."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Hindi nakilala"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hindi available ang hardware na ginagamitan ng fingerprint."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Hindi maiimbak ang fingerprint. Mangyaring mag-alis ng umiiral nang fingerprint."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Nag-time out ang fingerprint. Subukang muli."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Nakansela ang operasyong ginagamitan ng fingerprint."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Masyadong maraming beses sumubok. Subukang muli sa ibang pagkakataon."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Masyadong maraming beses sumubok. Na-disable ang sensor para sa fingerprint."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Subukang muli."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Buksan"</string>
<string name="sms" msgid="4560537514610063430">"Padalhan ng Mensahe"</string>
<string name="add_contact" msgid="7867066569670597203">"Magdagdag"</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">"Nauubusan na ang puwang ng storage"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Maaaring hindi gumana nang tama ang ilang paggana ng system"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Walang sapat na storage para sa system. Tiyaking mayroon kang 250MB na libreng espasyo at i-restart."</string>
@@ -1114,6 +1131,8 @@
<item quantity="other">Available ang mga bukas na Wi-Fi network</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Kumonekta sa bukas na Wi‑Fi network"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Kumokonekta sa bukas na Wi‑Fi network"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Nakakonekta sa Wi‑Fi network"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Hindi makakonekta sa Wi‑Fi network"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Awtomatikong mag-o-on ang Wi‑Fi"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Kapag malapit ka sa naka-save na network na mataas ang kalidad"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Huwag i-on muli"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Awtomatikong na-on ang Wi‑Fi"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Malapit ka sa isang naka-save na network: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Mag-sign in sa Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Mag-sign in sa network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Lampas ng <xliff:g id="SIZE">%s</xliff:g> sa tinukoy na limitasyon."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Pinaghihigpitan ang data ng background"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"I-tap upang alisin paghihigpit."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Malaking paggamit ng data"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Mas malaki kaysa sa karaniwan ang paggamit mo ng data sa nakalipas na ilang araw. I-tap upang matingnan ang paggamit at mga setting."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificate ng seguridad"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"May-bisa ang certificate na ito."</string>
<string name="issued_to" msgid="454239480274921032">"Ibinigay kay:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hanggang <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Hanggang <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (susunod na alarm)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Hanggang sa i-off mo ang Huwag Istorbohin"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Hanggang sa i-off mo"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hanggang sa i-off mo ang Huwag Istorbohin"</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">"I-collapse"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Lahat ng wika"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Lahat ng rehiyon"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Maghanap"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"I-on ang work mode?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Io-on nito ang iyong profile sa trabaho, kasama ang mga app, pag-sync sa background, at mga kaugnay na feature"</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">"I-on"</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">"Mayroon kang mga bagong mensahe"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Buksan ang SMS app upang tingnan"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Limitado ilang functionality"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Hindi ma-restore ang shortcut dahil hindi sinusuportahan ng app ang pag-back up at pag-restore"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Hindi ma-restore ang shortcut dahil hindi magkatugma ang signature ng app"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Hindi ma-restore ang shortcut"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Naka-disable ang shortcut"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"Gustong ipakita ng <xliff:g id="APP_0">%1$s</xliff:g> ang mga slice ng <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"I-edit"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e2b1cb3..929991f 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Kuruluşunuz bu cihazı yönetmekte olup ağ trafiğini izleyebilir. Ayrıntılar için dokunun."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Cihazınız silinecek"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Yönetim uygulaması kullanılamıyor. Cihazınız şimdi silinecek.\n\nSorularınız varsa kuruluşunuzun yöneticisine başvurun."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Yazdırma işlemi <xliff:g id="OWNER_APP">%s</xliff:g> tarafından devre dışı bırakıldı."</string>
<string name="me" msgid="6545696007631404292">"Ben"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tablet seçenekleri"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV seçenekleri"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Acil durum"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Hata raporu"</string>
<string name="global_action_logout" msgid="935179188218826050">"Oturumu sonlandır"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Ekran görüntüsü"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Hata raporu al"</string>
<string name="bugreport_message" msgid="398447048750350456">"Bu rapor, e-posta iletisi olarak göndermek üzere cihazınızın şu anki durumuyla ilgili bilgi toplar. Hata raporu başlatıldıktan sonra hazır olması biraz zaman alabilir, lütfen sabırlı olun."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Etkileşimli rapor"</string>
@@ -262,8 +264,10 @@
<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">"Güvenli mod"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Kişisel Profile Geç"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"İş Profiline Geç"</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">"Kişiler"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"kişilerinize erişme"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> uygulamasının kişilerinize erişmesine izin verin"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Uygulamaya cihazdaki telefon özelliklerine erişme izni verir. Bu izin, uygulamanın telefon numarasını ve cihaz kimliğini, etkin bir çağrı olup olmadığını ve çağrıda bağlanılan karşı tarafın numarasını öğrenmesine olanak sağlar."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"çağrıları sistem üzerinden yönlendir"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Uygulamanın, çağrı deneyimini iyileştirmek için çağrılarını sistem üzerinden yönlendirmesine olanak tanır."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"telefon numaralarını oku"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Uygulamaya, cihazınızın telefon numaralarına erişme izni verir."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"tabletin uykuya geçmesini önle"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Parmak hareketi çok yavaştı. Lütfen tekrar deneyin."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Tanınmadı"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Parmak izi donanımı kullanılamıyor."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Parmak izi depolanamıyor. Lütfen mevcut parmak izlerinden birini kaldırın."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Parmak izi için zaman aşımı oluştu. Tekrar deneyin."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Parmak izi işlemi iptal edildi."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Çok fazla deneme yapıldı. Daha sonra tekrar deneyin."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Çok fazla deneme yapıldı. Parmak izi sensörü devre dışı bıraıldı."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tekrar deneyin."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Aç"</string>
<string name="sms" msgid="4560537514610063430">"Mesaj"</string>
<string name="add_contact" msgid="7867066569670597203">"Ekle"</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">"Depolama alanı bitiyor"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Bazı sistem işlevleri çalışmayabilir"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Sistem için yeterli depolama alanı yok. 250 MB boş alanınızın bulunduğundan emin olun ve yeniden başlatın."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Kullanılabilir Kablosuz ağı aç</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Açık kablosuz ağa bağlanın"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Açık kablosuz ağa bağlandı"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Kablosuz ağa bağlanıldı"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Kablosuz ağa bağlanamadı"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Kablosuz özelliği otomatik olarak açılacak"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Daha önce kaydedilmiş yüksek kaliteli bir ağın yakınında olduğunuzda"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Tekrar açılmasın"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Kablosuz ağ otomatik olarak açıldı"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Kayıtlı bir ağın yakınındasınız: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Kablosuz ağda oturum açın"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Ağda oturum açın"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g>, belirlenen limiti aşıyor."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Arka plan verileri kısıtlı"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Kısıtlamayı kaldır. için dokunun"</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Fazla veri kullanımı"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Son birkaç gün içindeki veri kullanımınız normalden fazla. Kullanımı ve ayarları görüntülemek için dokunun."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Güvenlik sertifikası"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Bu sertifika geçerli."</string>
<string name="issued_to" msgid="454239480274921032">"Verilen:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Şu saate kadar: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (sonraki alarma) saatine kadar"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Rahatsız Etmeyin ayarını kapatana kadar"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Siz kapatana kadar"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Rahatsız Etmeyin ayarını kapatana kadar"</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">"Daralt"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Tüm diller"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Tüm bölgeler"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Ara"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"İş modu açılsın mı?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Bu işlem; uygulamalar, arka planda senkronizasyon ve ilgili özellikler dahil olmak üzere iş profilinizi açar."</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">"Aç"</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">"Yeni mesajlarınız var"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Görüntülemek için SMS uygulamasını açın"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Bazı işlevler sınırlı olabilir"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Uygulama, yedekleme ve geri yüklemeyi desteklemediğinden kısayol geri yüklenemedi"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Uygulama imzası eşleşmediğinden kısayol geri yüklenemedi"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Kısayol geri yüklenemedi"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Kısayol devre dışı"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> uygulaması, <xliff:g id="APP_2">%2$s</xliff:g> dilimlerini göstermek istiyor"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Düzenle"</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 0d70955..b028b36 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -185,6 +185,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Параметри ТБ"</string>
@@ -269,8 +270,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"Перейти в особистий профіль"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Перейти в робочий профіль"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Надати додатку <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> доступ до контактів"</string>
@@ -422,6 +425,10 @@
<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>
@@ -491,10 +498,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Забагато спроб. Сканер відбитків пальців вимкнено."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Повторіть спробу."</string>
@@ -1030,6 +1040,12 @@
<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">"Недостатньо місця для системи. Переконайтесь, що на пристрої є 250 МБ вільного місця, і повторіть спробу."</string>
@@ -1159,6 +1175,8 @@
<item quantity="other">Відкриті мережі Wi-Fi доступні</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Під’єднайтеся до відкритої мережі Wi-Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Під’єднання до відкритої мережі Wi-Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Під’єднано до мережі Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не вдалося під’єднатися до мережі Wi-Fi"</string>
@@ -1458,6 +1476,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"Сертифікат безпеки"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Цей сертифікат дійсний."</string>
<string name="issued_to" msgid="454239480274921032">"Кому видано:"</string>
@@ -1754,7 +1774,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Доки ввімкнено режим \"Не турбувати\""</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Доки ви не вимкнете"</string>
<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>
@@ -1805,9 +1825,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Увімкнути робочий режим?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Буде ввімкнено робочий профіль, зокрема додатки, фонову синхронізацію та пов’язані функції"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"Деякі функції можуть не працювати"</string>
@@ -1881,7 +1907,12 @@
<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>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Видалити"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Усе одно запустити"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Видалити шкідливий додаток?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> хоче показати фрагменти додатка <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Редагувати"</string>
</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 54b25b7..c241214 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV کے اختیارات"</string>
@@ -217,8 +218,7 @@
<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="global_action_screenshot" msgid="8329831278085426283">"اسکرین شاٹ"</string>
<string name="bugreport_title" msgid="2667494803742548533">"بگ کی اطلاع لیں"</string>
<string name="bugreport_message" msgid="398447048750350456">"ایک ای میل پیغام کے بطور بھیجنے کیلئے، یہ آپ کے موجودہ آلہ کی حالت کے بارے میں معلومات جمع کرے گا۔ بگ کی اطلاع شروع کرنے سے لے کر بھیجنے کیلئے تیار ہونے تک اس میں تھوڑا وقت لگے گا؛ براہ کرم تحمل سے کام لیں۔"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"متعامل رپورٹ"</string>
@@ -264,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"ذاتی پر سوئچ کریں"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"کام پر سوئچ کریں"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> کو اپنے رابطوں تک رسائی کی اجازت دیں"</string>
@@ -417,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ایپ کو آلے کی فون والی خصوصیات تک رسائی حاصل کرنے کی اجازت دیتا ہے۔ یہ اجازت ایپ کو فون نمبر اور آلے کے IDs کا تعین کرنے، آیا کوئی کال فعال ہے، اور کال کے ذریعہ مربوط ریموٹ نمبر کا تعین کرنے دیتی ہے۔"</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>
@@ -486,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"کافی زیادہ کوششیں۔ فنگر پرنٹ سینسر غیر فعال ہو گیا۔"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوبارہ کوشش کریں۔"</string>
@@ -991,6 +1000,12 @@
<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">"سسٹم کیلئے کافی اسٹوریج نہیں ہے۔ اس بات کو یقینی بنائیں کہ آپ کے پاس 250MB خالی جگہ ہے اور دوبارہ شروع کریں۔"</string>
@@ -1116,6 +1131,8 @@
<item quantity="one">عوامی Wi-Fi نیٹ ورک دستیاب ہے</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"عوامی Wi‑Fi نیٹ ورک سے منسلک ہوں"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"عوامی Wi‑Fi نیٹ ورک سے منسلک ہو رہا ہے"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"عوامی Wi‑Fi نیٹ ورک سے منسلک ہو گيا"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi نیٹ ورک سے منسلک نہیں ہو سکا"</string>
@@ -1125,10 +1142,8 @@
<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>
- <!-- no translation found for wifi_wakeup_enabled_title (6534603733173085309) -->
- <skip />
- <!-- no translation found for wifi_wakeup_enabled_content (189330154407990583) -->
- <skip />
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi-Fi خود کار طور پر آن ہو گیا"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"آپ ایک محفوظ نیٹ ورک کے قریب ہیں: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi نیٹ ورک میں سائن ان کریں"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"نیٹ ورک میں سائن ان کریں"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"سیکیورٹی سرٹیفیکیٹ"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"یہ سرٹیفکیٹ درست ہے۔"</string>
<string name="issued_to" msgid="454239480274921032">"جاری کردہ بنام:"</string>
@@ -1692,7 +1709,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"جب تک آپ \'ڈسڑب نہ کریں\' کو آف نہیں کر دیتے"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"یہاں تک کہ آپ آف کر دیں"</string>
<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>
@@ -1741,9 +1758,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"دفتری وضع آن کریں؟"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"اس سے آپ کا دفتری پروفائل آن ہو جائے گا، بشمول ایپس، پس منظر کی مطابقت پذیری اور متعلقہ خصوصیات"</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>
<string name="user_encrypted_title" msgid="9054897468831672082">"کچھ فعالیت محدود ہو سکتی ہے"</string>
@@ -1815,10 +1838,12 @@
<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 (3846265696369136266) -->
+ <!-- no translation found for harmful_app_warning_uninstall (4837672735619532931) -->
<skip />
- <!-- no translation found for harmful_app_warning_launch_anyway (5784428382367400530) -->
+ <!-- no translation found for harmful_app_warning_open_anyway (596432803680914321) -->
<skip />
- <!-- no translation found for harmful_app_warning_title (2229996292333310435) -->
+ <!-- no translation found for harmful_app_warning_title (8982527462829423432) -->
<skip />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> <xliff:g id="APP_2">%2$s</xliff:g> کے سلائسز دکھانا چاہتی ہے"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"ترمیم کریں"</string>
</resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index ce8613f..2329a41 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Tashkilotingiz bu qurilmani boshqaradi va tarmoq trafigini nazorat qilishi mumkin. Tafsilotlar uchun bosing."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Qurilmangizdagi ma’lumotlar o‘chirib tashlanadi"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Administrator ilovasini ishlatib bo‘lmaydi. Qurilmada barcha ma’lumotlar o‘chirib tashlanadi.\n\nSavollaringiz bo‘lsa, administrator bilan bog‘laning."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Chop etish funksiyasi <xliff:g id="OWNER_APP">%s</xliff:g> tomonidan faolsizlantirilgan."</string>
<string name="me" msgid="6545696007631404292">"Men"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Planshet sozlamalari"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"TV tanlamalari"</string>
@@ -263,8 +264,10 @@
<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">"Xavfsiz usul"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android tizimi"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Shaxsiy profilga o‘tish"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Ishchi profilga o‘tish"</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">"Kontaktlar"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"kontaktlarga kirish"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> uchun kontaktlaringizga ruxsat berish"</string>
@@ -416,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ilovaga qurilmangizdagi telefon xususiyatlariga kirishga ruxsat beradi. Bu ruxsat ilovaga telefon raqami va qurilma nomlari, qo‘ng‘iroq faol yoki faolsizligi va masofadagi raqam qo‘ng‘rioq orqali bog‘langanligini aniqlashga imkon beradi."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"chaqiruvlarni tizim orqali yo‘naltirish"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Ilova aloqa sifatini yaxshilash maqsadida chaqiruvlarni tizim orqali yo‘naltirishi mumkin."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"telefon raqamlarini o‘qish"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Ilovaga qurilmaning telefon raqamlaridan foydalanishiga ruxsat beradi."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"planshetni uyquga ketishiga yo‘l qo‘ymaslik"</string>
@@ -485,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Barmoq juda sekin harakatlandi. Qayta urinib ko‘ring."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Aniqlanmadi"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Barmoq izi skaneri ish holatida emas."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Barmoq izini saqlab bo‘lmadi. Mavjud barmoq izlaridan birini o‘chirib tashlang."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmoq izini aniqlash vaqti tugab qoldi. Qayta urinib ko‘ring."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Barmoq izi tekshiruvi bekor qilindi."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Urinishlar soni ko‘payib ketdi. Keyinroq qayta urinib ko‘ring."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Urinishlar soni ko‘payib ketdi. Barmoq izi skaneri bloklandi."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Qayta urinib ko‘ring."</string>
@@ -990,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Ochish"</string>
<string name="sms" msgid="4560537514610063430">"Xabar"</string>
<string name="add_contact" msgid="7867066569670597203">"Qo‘shish"</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">"Xotirada bo‘sh joy tugamoqda"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Ba‘zi tizim funksiyalari ishlamasligi mumkin"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Tizim uchun xotirada joy yetarli emas. Avval 250 megabayt joy bo‘shatib, keyin qurilmani o‘chirib yoqing."</string>
@@ -1115,6 +1131,8 @@
<item quantity="one">Ochiq Wi-Fi tarmog‘i aniqlandi</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Ochiq Wi‑Fi tarmoqqa ulaning"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ochiq Wi‑Fi tarmoqqa ulanilmoqda"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi tarmoqqa ulanildi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi-Fi tarmoqqa ulanib bo‘lmadi"</string>
@@ -1413,6 +1431,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"Chegaradan <xliff:g id="SIZE">%s</xliff:g> oshib ketdi."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Fon rejimi cheklangan"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Cheklovni olib tashlash uchun bosing."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Ko‘p trafik sarflandi"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Oxirgi bir necha kunda odatdagidan ko‘proq trafik sarflandi. Trafik sarfi va sozlamalarni ko‘rish uchun bosing."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Xavfsizlik sertifikati"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Ushbu sertifikat - to‘g‘ri."</string>
<string name="issued_to" msgid="454239480274921032">"Tegishli:"</string>
@@ -1689,7 +1709,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> gacha"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> gacha (keyingi signal)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"“Bezovta qilinmasin” rejimi o‘chirilmaguncha"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"O‘chirib qo‘ymagunimcha"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"“Bezovta qilinmasin” rejimi o‘chirilmaguncha"</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">"Yig‘ish"</string>
@@ -1738,9 +1758,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Barcha tillar"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Barcha hududlar"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Qidiruv"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Ishchi rejim yoqilsinmi?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Bunda ishchi profilingiz, jumladan, ilovalar, fonda sinxronlash va aloqador funksiyalar yoqiladi"</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">"Yoqish"</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">"Sizga yangi SMS keldi"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Ko‘rish uchun SMS ilovasini oching"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Ba’zi funksiyalar cheklanishi m-n"</string>
@@ -1812,7 +1838,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ilova imzosi mos kelmagani uchun yorliq tiklanmadi"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Yorliq tiklanmadi"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Yorliq faolsizlantirildi"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"O‘chirib tashlash"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Baribir ishga tushirilsin"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Zararli ilova o‘chirilsinmi?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> ilovasi <xliff:g id="APP_2">%2$s</xliff:g> ilovasidan fragmentlar ko‘rsatish uchun ruxsat so‘ramoqda"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Tahrirlash"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index f5a1972..7557acf 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Tổ chức của bạn sẽ quản lý thiết bị này và có thể theo dõi lưu lượng truy cập mạng. Nhấn để biết chi tiết."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Thiết bị của bạn sẽ bị xóa"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Không thể sử dụng ứng dụng quản trị. Bây giờ, thiết bị của bạn sẽ bị xóa.\n\nNếu bạn có thắc mắc, hãy liên hệ với quản trị viên của tổ chức bạn."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"<xliff:g id="OWNER_APP">%s</xliff:g> đã tắt tính năng in."</string>
<string name="me" msgid="6545696007631404292">"Tôi"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tùy chọn máy tính bảng"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Tùy chọn TV"</string>
@@ -217,6 +218,7 @@
<string name="global_action_emergency" msgid="7112311161137421166">"Khẩn cấp"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Báo cáo lỗi"</string>
<string name="global_action_logout" msgid="935179188218826050">"Kết thúc phiên"</string>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"Ảnh chụp màn hình"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Nhận báo cáo lỗi"</string>
<string name="bugreport_message" msgid="398447048750350456">"Báo cáo này sẽ thu thập thông tin về tình trạng thiết bị hiện tại của bạn, để gửi dưới dạng thông báo qua email. Sẽ mất một chút thời gian kể từ khi bắt đầu báo cáo lỗi cho tới khi báo cáo sẵn sàng để gửi; xin vui lòng kiên nhẫn."</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Báo cáo tương tác"</string>
@@ -262,8 +264,10 @@
<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">"Chế độ an toàn"</string>
<string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Chuyển sang Cá nhân"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Chuyển sang Công việc"</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">"Danh bạ"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"truy cập vào danh bạ của bạn"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Cho phép <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> truy cập vào danh bạ của bạn"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Cho phép ứng dụng truy cập vào các tính năng điện thoại của thiết bị. Quyền này cho phép ứng dụng xác định số điện thoại và ID thiết bị, cho dù cuộc gọi có hiện hoạt hay không và số từ xa có được kết nối bằng một cuộc gọi hay không."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"định tuyến cuộc gọi thông qua hệ thống"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Cho phép ứng dụng định tuyến cuộc gọi thông qua hệ thống nhằm cải thiện trải nghiệm gọi điện."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"đọc số điện thoại"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Cho phép ứng dụng truy cập số điện thoại của thiết bị."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ngăn máy tính bảng chuyển sang chế độ ngủ"</string>
@@ -484,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Di chuyển ngón tay quá chậm. Vui lòng thử lại."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Không nhận dạng được"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Phần cứng vân tay không khả dụng."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Không thể lưu vân tay. Vui lòng xóa vân tay hiện có."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Đã hết thời gian chờ vân tay. Hãy thử lại."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Thao tác dùng dấu vân tay bị hủy."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Quá nhiều lần thử. Hãy thử lại sau."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Quá nhiều lần thử. Cảm biến vân tay đã bị tắt."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Thử lại."</string>
@@ -989,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Mở"</string>
<string name="sms" msgid="4560537514610063430">"Gửi tin nhắn"</string>
<string name="add_contact" msgid="7867066569670597203">"Thêm"</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">"Sắp hết dung lượng lưu trữ"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Một số chức năng hệ thống có thể không hoạt động"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Không đủ bộ nhớ cho hệ thống. Đảm bảo bạn có 250 MB dung lượng trống và khởi động lại."</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">Mở mạng Wi-Fi khả dụng</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Kết nối với mạng Wi-Fi đang mở"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Đang kết nối với mạng Wi‑Fi đang mở"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Đã kết nối với mạng Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Không thể kết nối với mạng Wi‑Fi"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi-Fi sẽ tự động bật"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"Khi bạn ở gần mạng đã lưu chất lượng cao"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Không bật lại"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"Wi-Fi đã tự động bật"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"Bạn đang ở gần mạng đã lưu: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Đăng nhập vào mạng Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Đăng nhập vào mạng"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> vượt quá g.hạn được chỉ định."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Dữ liệu nền bị giới hạn"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Nhấn để xóa giới hạn."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Mức sử dụng dữ liệu lớn"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Mức sử dụng dữ liệu của bạn trong vài ngày qua lớn hơn bình thường. Hãy nhấn để xem mức sử dụng và cài đặt."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Chứng chỉ bảo mật"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Chứng chỉ này hợp lệ."</string>
<string name="issued_to" msgid="454239480274921032">"Cấp cho:"</string>
@@ -1685,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Cho đến <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Cho tới <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (cảnh báo tiếp theo)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Cho đến khi bạn tắt Không làm phiền"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Cho đến khi bạn tắt"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Cho đến khi bạn tắt Đừng làm phiền"</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">"Thu gọn"</string>
@@ -1734,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Tất cả ngôn ngữ"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Tất cả khu vực"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Tìm kiếm"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Bật chế độ làm việc?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Thao tác này sẽ bật hồ sơ công việc của bạn, bao gồm ứng dụng, đồng bộ hóa trong nền và các tính năng liên quan."</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">"Bật"</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">"Bạn có tin nhắn mới"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Mở ứng dụng SMS để xem"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Một số chức năng có thể bị hạn chế"</string>
@@ -1807,6 +1836,13 @@
<string name="shortcut_restore_not_supported" msgid="5028808567940014190">"Không thể khôi phục lối tắt do ứng dụng không hỗ trợ sao lưu và khôi phục"</string>
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Không thể khôi phục lối tắt do không khớp chữ ký ứng dụng"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Không thể khôi phục lối tắt"</string>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Đã vô hiệu hóa lối tắt"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> muốn hiển thị các lát của <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Chỉnh sửa"</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 70b299e..e52185e 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"电视选项"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"屏幕截图"</string>
<string name="bugreport_title" msgid="2667494803742548533">"提交错误报告"</string>
<string name="bugreport_message" msgid="398447048750350456">"这会收集有关当前设备状态的信息,并以电子邮件的形式进行发送。从开始生成错误报告到准备好发送需要一点时间,请耐心等待。"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"互动式报告"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"切换到“个人”"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"切换到“工作”"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"允许<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>访问您的通讯录"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"允许该应用访问设备的电话功能。此权限可让该应用确定本机号码和设备 ID、是否正处于通话状态以及拨打的号码。"</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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"尝试次数过多。指纹传感器已停用。"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"请重试。"</string>
@@ -989,6 +1000,12 @@
<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">"系统存储空间不足。请确保您有250MB的可用空间,然后重新启动。"</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">有可用的开放 WLAN 网络</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"连接到开放的 WLAN 网络"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"正在连接到开放的 WLAN 网络"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"已连接到 WLAN 网络"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"无法连接到 WLAN 网络"</string>
@@ -1123,6 +1142,8 @@
<string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"WLAN 将自动开启"</string>
<string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"当您位于已保存的高品质网络信号范围内时"</string>
<string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"不要重新开启"</string>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"已自动开启 WLAN 网络"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"您位于已保存的网络 (<xliff:g id="NETWORK_SSID">%1$s</xliff:g>) 信号范围内"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"登录到WLAN网络"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"登录到网络"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"超出规定上限 <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="ssl_certificate" msgid="6510040486049237639">"安全证书"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"该证书有效。"</string>
<string name="issued_to" msgid="454239480274921032">"颁发给:"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"直到您关闭“勿扰”模式"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"直到您将其关闭"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"要开启工作模式吗?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"这将开启您的工作资料(包括应用、后台同步和相关功能)"</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>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"“<xliff:g id="APP_0">%1$s</xliff:g>”想要显示“<xliff:g id="APP_2">%2$s</xliff:g>”图块"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"编辑"</string>
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 3dad724..cba21c3 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"電視選項"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"擷取螢幕畫面"</string>
<string name="bugreport_title" msgid="2667494803742548533">"取得錯誤報告"</string>
<string name="bugreport_message" msgid="398447048750350456">"這會收集您目前裝置狀態的相關資訊,並以電郵傳送給您。從開始建立錯誤報告到準備傳送需要一段時間,請耐心等候。"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"互動報告"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"切換至個人設定檔"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"切換至工作設定檔"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"允許 <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> 存取您的聯絡人"</string>
@@ -415,6 +419,10 @@
<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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"嘗試次數過多,指紋感應器已停用。"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"再試一次。"</string>
@@ -989,6 +1000,12 @@
<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">"系統儲存空間不足。請確認裝置有 250 MB 的可用空間,然後重新啟動。"</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">有可用的公開 Wi-Fi 網絡</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"連線至開放的 Wi-Fi 網絡"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"正在連線至開放的 Wi-Fi 網絡"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"已連線至 Wi-Fi 網絡"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"無法連線至 Wi-Fi 網絡"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"已自動開啟 Wi‑Fi"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"您附近有已儲存的網絡:<xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"登入 Wi-Fi 網絡"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"登入網絡"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"安全性憑證"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"憑證有效。"</string>
<string name="issued_to" msgid="454239480274921032">"發給:"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"直至您關閉「請勿騷擾」功能"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"直至您關閉為止"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"要開啟工作模式嗎?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"您的工作設定檔將會開啟,當中包括應用程式、背景同步處理和相關功能"</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>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"「<xliff:g id="APP_0">%1$s</xliff:g>」想顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的快訊"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"編輯"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index d3ad7b0..2b4f6cb 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -181,6 +181,7 @@
<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="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>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"電視選項"</string>
@@ -217,6 +218,7 @@
<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>
+ <string name="global_action_screenshot" msgid="8329831278085426283">"擷取螢幕畫面"</string>
<string name="bugreport_title" msgid="2667494803742548533">"取得錯誤報告"</string>
<string name="bugreport_message" msgid="398447048750350456">"這會收集你目前裝置狀態的相關資訊,以便透過電子郵件傳送。從錯誤報告開始建立到準備傳送的這段過程可能需要一點時間,敬請耐心等候。"</string>
<string name="bugreport_option_interactive_title" msgid="8635056131768862479">"互動式報告"</string>
@@ -262,8 +264,10 @@
<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>
- <string name="user_owner_label" msgid="1119010402169916617">"切換至個人設定檔"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"切換至公司設定檔"</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>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取你的聯絡人"</string>
@@ -415,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"允許應用程式使用裝置的電話功能。這項權限可讓應用程式判讀手機號碼和裝置 ID、是否正在通話中,以及所撥打的對方號碼。"</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>
@@ -484,10 +492,13 @@
<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>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"嘗試次數過多,指紋感應器已停用。"</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"請再試一次。"</string>
@@ -989,6 +1000,12 @@
<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">"系統儲存空間不足。請確定你已釋出 250MB 的可用空間,然後重新啟動。"</string>
@@ -1114,6 +1131,8 @@
<item quantity="one">有多個可用的開放 Wi-Fi 網路</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"連線至開放的 Wi‑Fi 網路"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"正在連線至開放的 Wi‑Fi 網路"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"已連線至 Wi-Fi 網路"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"無法連線至 Wi‑Fi 網路"</string>
@@ -1123,6 +1142,8 @@
<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>
+ <string name="wifi_wakeup_enabled_title" msgid="6534603733173085309">"已自動開啟 Wi‑Fi"</string>
+ <string name="wifi_wakeup_enabled_content" msgid="189330154407990583">"你位於已儲存的網路範圍內:<xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"登入 Wi-Fi 網路"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"登入網路"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1409,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<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="ssl_certificate" msgid="6510040486049237639">"安全性憑證"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"憑證有效。"</string>
<string name="issued_to" msgid="454239480274921032">"發佈至:"</string>
@@ -1685,7 +1708,7 @@
</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>
- <string name="zen_mode_forever" msgid="1916263162129197274">"直到你關閉「零打擾」模式"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"直到你關閉為止"</string>
<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>
@@ -1734,9 +1757,15 @@
<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>
- <string name="work_mode_off_title" msgid="2615362773958585967">"要啟用工作模式嗎?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"這樣做會啟用你的 Work 設定檔,包括應用程式、背景同步處理和相關功能"</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>
@@ -1807,6 +1836,13 @@
<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>
- <!-- no translation found for shortcut_disabled_reason_unknown (5276016910284687075) -->
+ <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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"「<xliff:g id="APP_0">%1$s</xliff:g>」想要顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的區塊"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"編輯"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e97f893..3f5d2b1 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -181,6 +181,7 @@
<string name="network_logging_notification_text" msgid="7930089249949354026">"Inhlangano yakho iphethe le divayisi futhi kungenzeka ingaqaphi ithrafikhi yenethiwekhi. Thephela imininingwane."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Idivayisi yakho izosulwa"</string>
<string name="factory_reset_message" msgid="7972496262232832457">"Uhlelo lokusebenza lomlawuli alikwazi ukusetshenziswa. Idivayisi yakho manje izosuswa.\n\nUma unemibuzo, xhumana nomlawuli wezinhlangano zakho."</string>
+ <string name="printing_disabled_by" msgid="8936832919072486965">"Ukuphrinta kukhutshazwe nge-<xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="me" msgid="6545696007631404292">"Mina"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Okukhethwa kukho kwethebhulethi"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Izinketho ze-TV"</string>
@@ -263,8 +264,10 @@
<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">"Imodi ephephile"</string>
<string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
- <string name="user_owner_label" msgid="1119010402169916617">"Shintshela komuntu siqu"</string>
- <string name="managed_profile_label" msgid="5289992269827577857">"Shintshela kumsebenzi"</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">"Oxhumana nabo"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"finyelela koxhumana nabo"</string>
<string name="permgrouprequest_contacts" msgid="1601591667800538208">"Vumela i-<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ukuthi ithole ukufinyelela koxhumana nabo"</string>
@@ -416,6 +419,10 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ivumela uhlelo lokusebenza ukufinyelela izici zefoni zedivayisi. Le mvume ivumela uhlelo lokusebenza ukucacisa inombolo yefoni nobunikazi bedivayisi, ukuthi noma ikholi iyasebenza, futhi nenombolo yesilawuli kude zixhunywe ngekholi."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"yanza imizila yamakholi ngesistimu"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Ivumela uhlelo lokusebenza ukwenza imizila yamakholi ngesistimu ukuze ithuthukise umuzwa wokushaya."</string>
+ <!-- no translation found for permlab_acceptHandover (2661534649736022409) -->
+ <skip />
+ <!-- no translation found for permdesc_acceptHandovers (4570660484220539698) -->
+ <skip />
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"funda izinombolo zefoni"</string>
<string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Ivumela uhlelo lokusebenza ukufinyelela izinombolo zefoni zedivayisi."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"gwema ithebhulethi ukuba ingalali"</string>
@@ -485,10 +492,13 @@
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Umnwe uhanjiswe kancane kakhulu. Sicela uzame futhi."</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
+ <string name="fingerprint_not_recognized" msgid="2690661881608146617">"Akubonwa"</string>
<string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Izingxenyekazi zekhompuyutha zezingxivizo zeminwe azitholakali."</string>
<string name="fingerprint_error_no_space" msgid="1055819001126053318">"Izigxivizo zeminwe azikwazi ukugcinwa. Sicela ususe izigxivizo zeminwe ezikhona."</string>
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ukusebenza kwezingxivizo zeminwe kukhanseliwe."</string>
+ <!-- no translation found for fingerprint_error_user_canceled (7999639584615291494) -->
+ <skip />
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi."</string>
<string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Imizamo eminingi kakhulu. Inzwa yezigxivizo zeminwe ikhutshaziwe."</string>
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Zama futhi."</string>
@@ -990,6 +1000,12 @@
<string name="browse" msgid="1245903488306147205">"Vula"</string>
<string name="sms" msgid="4560537514610063430">"Umlayezo"</string>
<string name="add_contact" msgid="7867066569670597203">"Engeza"</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">"Isikhala sokulondoloza siyaphela"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Eminye imisebenzi yohlelo ingahle ingasebenzi"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Akusona isitoreji esanele sesistimu. Qiniseka ukuthi unesikhala esikhululekile esingu-250MB uphinde uqalise kabusha."</string>
@@ -1115,6 +1131,8 @@
<item quantity="other">Vula amanethiwekhi we-Wi-Fi atholakalayo</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Xhuma kunethiwekhi evulekile ye-Wi‑Fi"</string>
+ <!-- no translation found for wifi_available_carrier_network_title (4527932626916527897) -->
+ <skip />
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ixhuma kunethiwekhi evulekile ye-Wi‑Fi"</string>
<string name="wifi_available_title_connected" msgid="7542672851522241548">"Kuxhumeke kunethiwekhi ye-Wi‑Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Ayikwazanga ukuxhumeka kunethiwekhi ye-Wi-Fi"</string>
@@ -1412,6 +1430,8 @@
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> ngaphezu komkhawulo ocacisiwe"</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Imininingo egciniwe ivinjelwe"</string>
<string name="data_usage_restricted_body" msgid="469866376337242726">"Thepha ukuze ususe umkhawulo."</string>
+ <string name="data_usage_rapid_title" msgid="4579994056245665351">"Ukusetshenziswa okukhulu kwedatha"</string>
+ <string name="data_usage_rapid_body" msgid="4899922842674185567">"Ukusetshenziswa kwedatha yakho ezinsukwini zokugcina ezimbalwa yinkulu kunokujwayelekile. Thepha ukuze ubuke ukusetshenziswa nezilungiselelo."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Isitifiketi sokuvikeleka"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Lesi sitifiketi silungile."</string>
<string name="issued_to" msgid="454239480274921032">"Ikhishelwe u:"</string>
@@ -1688,7 +1708,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Kuze kube ngu-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"Kuze kube ngu-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (i-alamu elandelayo)"</string>
- <string name="zen_mode_forever" msgid="1916263162129197274">"Uze uvale ungaphazamisi"</string>
+ <string name="zen_mode_forever" msgid="931849471004038757">"Uze uvale isikrini"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Uze uvale ungaphazamisi"</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">"Goqa"</string>
@@ -1737,9 +1757,15 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Zonke izilimi"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Zonke izifunda"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Sesha"</string>
- <string name="work_mode_off_title" msgid="2615362773958585967">"Vula imodi yomsebenzi?"</string>
- <string name="work_mode_off_message" msgid="2961559609199223594">"Lokhu kuzovula iphrofayela yakho yomsebenzi, okufaka izinhlelo zokusebenza, ukuvumelanisa okungemuva, nezici ezihlobene"</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">"Vula"</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">"Unemilayezo emisha"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Vula uhlelo lokusebenza lwe-SMS ukuze ubuke"</string>
<string name="user_encrypted_title" msgid="9054897468831672082">"Okunye ukusebenza kungakhawulelwe"</string>
@@ -1811,7 +1837,12 @@
<string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Ayikwazanga ukubuyisa isinqamuleli ngoba isignisha yohlelo lokusebenza ayifani"</string>
<string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Ayikwazanga ukubuyisa isinqamuleli"</string>
<string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Isinqamuleli sikhutshaziwe"</string>
- <string name="harmful_app_warning_uninstall" msgid="3846265696369136266">"Khipha"</string>
- <string name="harmful_app_warning_launch_anyway" msgid="5784428382367400530">"Qalisa noma kunjalo"</string>
- <string name="harmful_app_warning_title" msgid="2229996292333310435">"Khipha uhlelo lokusebenza oluyingozi?"</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 />
+ <string name="slices_permission_request" msgid="8484943441501672932">"I-<xliff:g id="APP_0">%1$s</xliff:g> ifuna ukubonisa izingcezu ze-<xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="screenshot_edit" msgid="7867478911006447565">"Hlela"</string>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 354d658..68dad87 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3036,6 +3036,28 @@
<!-- The title this view should present to accessibility as a pane title.
See {@link android.view.View#setAccessibilityPaneTitle(CharSequence)} -->
<attr name="accessibilityPaneTitle" format="string" />
+
+ <!-- Sets the color of the spot shadow that is drawn when the view has a positive Z or
+ elevation value.
+ <p>
+ By default the shadow color is black. Generally, this color will be opaque so the
+ intensity of the shadow is consistent between different views with different colors.
+ <p>
+ The opacity of the final spot shadow is a function of the shadow caster height, the
+ alpha channel of the outlineSpotShadowColor (typically opaque), and the
+ {@link android.R.attr#spotShadowAlpha} theme attribute. -->
+ <attr name="outlineSpotShadowColor" format="color" />
+
+ <!-- Sets the color of the ambient shadow that is drawn when the view has a positive Z
+ or elevation value.
+ <p>
+ By default the shadow color is black. Generally, this color will be opaque so the
+ intensity of the shadow is consistent between different views with different colors.
+ <p>
+ The opacity of the final ambient shadow is a function of the shadow caster height,
+ the alpha channel of the outlineAmbientShadowColor (typically opaque), and the
+ {@link android.R.attr#ambientShadowAlpha} theme attribute. -->
+ <attr name="outlineAmbientShadowColor" format="color" />
</declare-styleable>
<!-- Attributes that can be assigned to a tag for a particular View. -->
@@ -5878,6 +5900,13 @@
<attr name="insetBottom" format="fraction|dimension" />
</declare-styleable>
+ <!-- Drawable used to draw animated images (gif) -->
+ <declare-styleable name="AnimatedImageDrawable">
+ <!-- Identifier of the image file. This attribute is mandatory.
+ It must be an image file with multiple frames, e.g. gif or webp -->
+ <attr name="src" />
+ </declare-styleable>
+
<!-- Drawable used to draw bitmaps. -->
<declare-styleable name="BitmapDrawable">
<!-- Identifier of the bitmap file. This attribute is mandatory. -->
@@ -8766,6 +8795,16 @@
<attr name="fontProviderCerts" format="reference" />
</declare-styleable>
+ <!-- Attributes that are read when parsing a tag. -->
+ <declare-styleable name="VideoView2">
+ <attr name="enableControlView" format="boolean" />
+ <attr name="showSubtitle" format="boolean" />
+ <attr name="viewType" format="enum">
+ <enum name="surfaceView" value="0" />
+ <enum name="textureView" value="1" />
+ </attr>
+ </declare-styleable>
+
<!-- @hide -->
<declare-styleable name="RecyclerView">
<attr name="layoutManager" format="string" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 66e56bf..607414d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -436,7 +436,7 @@
0 = Not available.
1 = Available.
-->
- <integer translatable="false" name="config_wifi_wakeup_available">0</integer>
+ <integer translatable="false" name="config_wifi_wakeup_available">1</integer>
<!-- Array of ConnectivityManager.TYPE_xxxx values allowable for tethering.
@@ -2283,10 +2283,7 @@
Can be customized for other product types -->
<string name="config_chooseTypeAndAccountActivity" translatable="false"
>android/android.accounts.ChooseTypeAndAccountActivity</string>
- <!-- Name of the activity that will handle requests to the system to choose an activity for
- the purposes of resolving an intent. -->
- <string name="config_chooserActivity" translatable="false"
- >com.android.systemui/com.android.systemui.chooser.ChooserActivity</string>
+
<!-- Component name of a custom ResolverActivity (Intent resolver) to be used instead of
the default framework version. If left empty, then the framework version will be used.
Example: com.google.android.myapp/.resolver.MyResolverActivity -->
@@ -2480,9 +2477,9 @@
<item>restart</item>
<item>screenshot</item>
<item>logout</item>
+ <item>lockdown</item>
<item>bugreport</item>
<item>users</item>
- <item>lockdown</item>
</string-array>
<!-- Number of milliseconds to hold a wake lock to ensure that drawing is fully
@@ -3126,6 +3123,15 @@
-->
<string name="config_defaultAutofillService" translatable="false"></string>
+ <!-- The component name, flattened to a string, for the default system textclassifier service.
+ This service must be trusted, as it can be activated without explicit consent of the user.
+ (e.g. com.android.textclassifier/.TextClassifierServiceImpl).
+ If no textclassifier service with the specified name exists on the device (or if this is
+ set to empty string), a default textclassifier will be loaded in the calling app's process.
+ See android.view.textclassifier.TextClassificationManager.
+ -->
+ <string name="config_defaultTextClassifierService" translatable="false"></string>
+
<!-- Whether the device uses the default focus highlight when focus state isn't specified. -->
<bool name="config_useDefaultFocusHighlight">true</bool>
@@ -3247,6 +3253,10 @@
or empty if the default should be used. -->
<string translatable="false" name="config_deviceSpecificDevicePolicyManagerService"></string>
+ <!-- Class name of the device specific implementation to replace the AudioService
+ or empty if the default should be used. -->
+ <string translatable="false" name="config_deviceSpecificAudioService"></string>
+
<!-- Component name of media projection permission dialog -->
<string name="config_mediaProjectionPermissionDialogComponent" translateable="false">com.android.systemui/com.android.systemui.media.MediaProjectionPermissionActivity</string>
@@ -3265,4 +3275,6 @@
<string name="config_defaultAssistantAccessPackage" translatable="false">android.ext.services</string>
<bool name="config_supportBluetoothPersistedState">true</bool>
+
+ <bool name="config_keepRestrictedProfilesInBackground">true</bool>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 2c824ea0..e610efd 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -33,6 +33,10 @@
<dimen name="toast_y_offset">24dp</dimen>
<!-- Height of the status bar -->
<dimen name="status_bar_height">24dp</dimen>
+ <!-- Height of area above QQS where battery/time go -->
+ <dimen name="quick_qs_offset_height">48dp</dimen>
+ <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+ <dimen name="quick_qs_total_height">176dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_height">48dp</dimen>
<!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
@@ -523,7 +527,7 @@
<dimen name="content_rect_bottom_clip_allowance">20dp</dimen>
<!-- Magnifier dimensions -->
- <dimen name="magnifier_width">164dp</dimen>
+ <dimen name="magnifier_width">100dp</dimen>
<dimen name="magnifier_height">48dp</dimen>
<dimen name="magnifier_elevation">2dp</dimen>
<dimen name="magnifier_offset">42dp</dimen>
@@ -635,4 +639,26 @@
<!-- Size of thumbnail used in the cross profile apps animation -->
<dimen name="cross_profile_apps_thumbnail_size">72dp</dimen>
+ <!-- Padding between the title and content in the harmful app dialog -->
+ <dimen name="harmful_app_padding_top">10dp</dimen>
+ <!-- Bottom padding for the "app name" section of the harmful app dialog -->
+ <dimen name="harmful_app_name_padding_bottom">20dp</dimen>
+ <!-- Left padding for the "app name" section of the harmful app dialog -->
+ <dimen name="harmful_app_name_padding_left">24dp</dimen>
+ <!-- Right padding for the "app name" section of the harmful app dialog -->
+ <dimen name="harmful_app_name_padding_right">24dp</dimen>
+ <!-- Top padding for the "app name" section of the harmful app dialog -->
+ <dimen name="harmful_app_name_padding_top">8dp</dimen>
+ <!-- Padding between the icon and app name in the harmful app dialog -->
+ <dimen name="harmful_app_icon_name_padding">20dp</dimen>
+ <!-- The size of the icon on the harmful app dialog -->
+ <dimen name="harmful_app_icon_size">44dp</dimen>
+ <!-- Left padding for the message section of the harmful app dialog -->
+ <dimen name="harmful_app_message_padding_left">24dp</dimen>
+ <!-- Right padding for the message section of the harmful app dialog -->
+ <dimen name="harmful_app_message_padding_right">24dp</dimen>
+ <!-- Bottom padding for the message section of the harmful app dialog -->
+ <dimen name="harmful_app_message_padding_bottom">24dp</dimen>
+ <!-- Line spacing modifier for the message field of the harmful app dialog -->
+ <item name="harmful_app_message_line_spacing_modifier" type="dimen">1.22</item>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 80fc5db..dee880f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2866,6 +2866,8 @@
<public name="lastBaselineToBottomHeight" />
<public name="lineHeight" />
<public name="accessibilityHeading" />
+ <public name="outlineSpotShadowColor" />
+ <public name="outlineAmbientShadowColor" />
</public-group>
<public-group type="style" first-id="0x010302e0">
@@ -2881,6 +2883,9 @@
<public-group type="string" first-id="0x0104001b">
</public-group>
+ <!-- An interpolator which accelerates fast but decelerates extra slowly. -->
+ <public type="interpolator" name="fast_out_extra_slow_in" id="0x10c001a"/>
+
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 69d96fc..3b752c4 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -916,11 +916,6 @@
<string name="permdesc_persistentActivity" product="default">Allows the app to make parts of itself persistent in memory. This can limit memory available to other apps slowing down the phone.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_foregroundService">run foreground service</string>
- <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_foregroundService">Allows the app to make use of foreground services.</string>
-
- <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_getPackageSize">measure app storage space</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_getPackageSize">Allows the app to retrieve its code, data, and cache sizes</string>
@@ -3227,19 +3222,23 @@
<string name="dlg_ok">OK</string>
<!-- USB_PREFERENCES: Notification for when the user connected to the charger only. This is the title -->
- <string name="usb_charging_notification_title">USB charging this device</string>
+ <string name="usb_charging_notification_title">Charging this device via USB</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to supply power to attached device. This is the title -->
- <string name="usb_supplying_notification_title">USB supplying power to attached device</string>
+ <string name="usb_supplying_notification_title">Charging connected device via USB</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MTP mode. This is the title -->
- <string name="usb_mtp_notification_title">USB for file transfer</string>
+ <string name="usb_mtp_notification_title">USB file transfer turned on</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in PTP mode. This is the title -->
- <string name="usb_ptp_notification_title">USB for photo transfer</string>
+ <string name="usb_ptp_notification_title">PTP via USB turned on</string>
+ <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in Tethering mode. This is the title -->
+ <string name="usb_tether_notification_title">USB tethering turned on</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MIDI mode. This is the title -->
- <string name="usb_midi_notification_title">USB for MIDI</string>
+ <string name="usb_midi_notification_title">MIDI via USB turned on</string>
<!-- USB_PREFERENCES: Notification for when a USB accessory is attached. This is the title -->
- <string name="usb_accessory_notification_title">Connected to a USB accessory</string>
+ <string name="usb_accessory_notification_title">USB accessory mode turned on</string>
<!-- See USB_PREFERENCES. This is the message. -->
<string name="usb_notification_message">Tap for more options.</string>
+ <!-- See USB_PREFERENCES. This is the message when a data mode is turned on (mtp, ptp, midi) and the device is supplying power.. -->
+ <string name="usb_power_notification_message">Charging connected device. Tap for more options.</string>
<!-- USB_PREFERENCES: Notification for when a type-c USB audio accessory is attached but not supported. This is the title -->
<string name="usb_unsupported_audio_accessory_title">Analog audio accessory detected</string>
<!-- Message of notification shown when a type-c USB audio accessory is attached but not supported. -->
@@ -4424,15 +4423,6 @@
<!-- DO NOT TRANSLATE -->
<string name="date_picker_day_typeface">sans-serif-medium</string>
- <!-- Notify use that they are in Lock-to-app -->
- <string name="lock_to_app_toast">To unpin this screen, touch & hold Back and Overview
- buttons</string>
-
- <!-- Starting lock-to-app indication. -->
- <string name="lock_to_app_start">Screen pinned</string>
- <!-- Exting lock-to-app indication. -->
- <string name="lock_to_app_exit">Screen unpinned</string>
-
<!-- Lock-to-app unlock pin string -->
<string name="lock_to_app_unlock_pin">Ask for PIN before unpinning</string>
<!-- Lock-to-app unlock pattern string -->
@@ -4847,12 +4837,12 @@
<!--Battery saver warning. STOPSHIP: Remove it eventually. -->
<string name="battery_saver_warning_title" translatable="false">Extreme battery saver</string>
- <!-- Label for the uninstall button on the harmful app warning dialog. -->
- <string name="harmful_app_warning_uninstall">Uninstall</string>
- <!-- Label for the launch anyway button on the harmful app warning dialog. -->
- <string name="harmful_app_warning_launch_anyway">Launch anyway</string>
- <!-- Title for the harmful app warning dialog. -->
- <string name="harmful_app_warning_title">Uninstall harmful app?</string>
+ <!-- Label for the uninstall button on the harmful app warning dialog. [CHAR LIMIT=20] -->
+ <string name="harmful_app_warning_uninstall">UNINSTALL</string>
+ <!-- Label for the open anyway button on the harmful app warning dialog. [CHAR LIMIT=20] -->
+ <string name="harmful_app_warning_open_anyway">OPEN ANYWAY</string>
+ <!-- Title for the harmful app warning dialog. [CHAR LIMIT=40] -->
+ <string name="harmful_app_warning_title">Harmful app detected</string>
<!-- Text describing a permission request for one app to show another app's
slices [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 710bbfb..fee5a80 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -460,6 +460,7 @@
<java-symbol type="bool" name="config_useDefaultFocusHighlight" />
<java-symbol type="array" name="config_deviceSpecificSystemServices" />
<java-symbol type="string" name="config_deviceSpecificDevicePolicyManagerService" />
+ <java-symbol type="string" name="config_deviceSpecificAudioService" />
<java-symbol type="integer" name="config_num_physical_slots" />
<java-symbol type="color" name="tab_indicator_text_v4" />
@@ -766,9 +767,6 @@
<java-symbol type="string" name="kilobyteShort" />
<java-symbol type="string" name="last_month" />
<java-symbol type="string" name="launchBrowserDefault" />
- <java-symbol type="string" name="lock_to_app_toast" />
- <java-symbol type="string" name="lock_to_app_start" />
- <java-symbol type="string" name="lock_to_app_exit" />
<java-symbol type="string" name="lock_to_app_unlock_pin" />
<java-symbol type="string" name="lock_to_app_unlock_pattern" />
<java-symbol type="string" name="lock_to_app_unlock_password" />
@@ -1070,7 +1068,6 @@
<java-symbol type="string" name="owner_name" />
<java-symbol type="string" name="config_chooseAccountActivity" />
<java-symbol type="string" name="config_chooseTypeAndAccountActivity" />
- <java-symbol type="string" name="config_chooserActivity" />
<java-symbol type="string" name="config_customResolverActivity" />
<java-symbol type="string" name="config_appsAuthorizedForSharedAccounts" />
<java-symbol type="string" name="error_message_title" />
@@ -1636,6 +1633,7 @@
<java-symbol type="dimen" name="navigation_bar_height_landscape_car_mode" />
<java-symbol type="dimen" name="navigation_bar_width_car_mode" />
<java-symbol type="dimen" name="status_bar_height" />
+ <java-symbol type="dimen" name="quick_qs_total_height" />
<java-symbol type="drawable" name="ic_jog_dial_sound_off" />
<java-symbol type="drawable" name="ic_jog_dial_sound_on" />
<java-symbol type="drawable" name="ic_jog_dial_unlock" />
@@ -2025,8 +2023,10 @@
<java-symbol type="string" name="usb_mtp_notification_title" />
<java-symbol type="string" name="usb_charging_notification_title" />
<java-symbol type="string" name="usb_notification_message" />
+ <java-symbol type="string" name="usb_power_notification_message" />
<java-symbol type="string" name="usb_ptp_notification_title" />
<java-symbol type="string" name="usb_midi_notification_title" />
+ <java-symbol type="string" name="usb_tether_notification_title" />
<java-symbol type="string" name="usb_supplying_notification_title" />
<java-symbol type="string" name="usb_unsupported_audio_accessory_title" />
<java-symbol type="string" name="usb_unsupported_audio_accessory_message" />
@@ -3100,6 +3100,7 @@
<java-symbol type="string" name="notification_channel_usb" />
<java-symbol type="string" name="notification_channel_heavy_weight_app" />
<java-symbol type="string" name="config_defaultAutofillService" />
+ <java-symbol type="string" name="config_defaultTextClassifierService" />
<java-symbol type="string" name="notification_channel_foreground_service" />
<java-symbol type="string" name="foreground_service_app_in_background" />
@@ -3228,8 +3229,9 @@
<java-symbol type="string" name="shortcut_disabled_reason_unknown" />
<java-symbol type="string" name="harmful_app_warning_uninstall" />
- <java-symbol type="string" name="harmful_app_warning_launch_anyway" />
+ <java-symbol type="string" name="harmful_app_warning_open_anyway" />
<java-symbol type="string" name="harmful_app_warning_title" />
+ <java-symbol type="layout" name="harmful_app_warning_dialog" />
<java-symbol type="string" name="config_defaultAssistantAccessPackage" />
@@ -3238,4 +3240,6 @@
<java-symbol type="string" name="slices_permission_request" />
<java-symbol type="string" name="screenshot_edit" />
+
+ <java-symbol type="bool" name="config_keepRestrictedProfilesInBackground" />
</resources>
diff --git a/core/res/res/xml/default_zen_mode_config.xml b/core/res/res/xml/default_zen_mode_config.xml
index 1e4c03e..a446088 100644
--- a/core/res/res/xml/default_zen_mode_config.xml
+++ b/core/res/res/xml/default_zen_mode_config.xml
@@ -19,5 +19,6 @@
<!-- Default configuration for zen mode. See android.service.notification.ZenModeConfig. -->
<zen version="2">
- <allow alarms="true" media_system_other="true" calls="false" messages="false" reminders="false" events="false" />
+ <allow alarms="true" media_system_other="true" calls="false" messages="false" reminders="false"
+ events="false" />
</zen>
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 60b46b4..2ea1b46 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -52,10 +52,8 @@
org.apache.http.legacy \
android.test.base \
android.test.mock \
-
-ifeq ($(REMOVE_OAHL_FROM_BCP),true)
-LOCAL_JAVA_LIBRARIES += framework-oahl-backward-compatibility
-endif
+ framework-oahl-backward-compatibility \
+ framework-atb-backward-compatibility \
LOCAL_PACKAGE_NAME := FrameworksCoreTests
LOCAL_COMPATIBILITY_SUITE := device-tests
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 53c22f6..7d5c60a 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -51,7 +51,6 @@
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
<uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
<uses-permission android:name="android.permission.DOWNLOAD_CACHE_NON_PURGEABLE" />
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
diff --git a/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java
new file mode 100644
index 0000000..dce22ce
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.content.pm;
+
+import static android.content.pm.PackageBuilder.builder;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
+
+import android.os.Build;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test for {@link AndroidTestBaseUpdater}
+ */
+@SmallTest
+@RunWith(OptionalClassRunner.class)
+@OptionalClassRunner.OptionalClass("android.content.pm.AndroidTestBaseUpdater")
+public class AndroidTestBaseUpdaterTest extends PackageSharedLibraryUpdaterTest {
+
+ private static final String OTHER_LIBRARY = "other.library";
+
+ @Test
+ public void targeted_at_O() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O);
+
+ // Should add org.apache.http.legacy.
+ PackageBuilder after = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(ANDROID_TEST_BASE);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_O_not_empty_usesLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(OTHER_LIBRARY);
+
+ // The org.apache.http.legacy jar should be added at the start of the list because it
+ // is not on the bootclasspath and the package targets pre-P.
+ PackageBuilder after = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(ANDROID_TEST_BASE, OTHER_LIBRARY);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_O_in_usesLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(ANDROID_TEST_BASE);
+
+ // No change is required because although org.apache.http.legacy has been removed from
+ // the bootclasspath the package explicitly requests it.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void targeted_at_O_in_usesOptionalLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .optionalLibraries(ANDROID_TEST_BASE);
+
+ // No change is required because although org.apache.http.legacy has been removed from
+ // the bootclasspath the package explicitly requests it.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void in_usesLibraries() {
+ PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_BASE);
+
+ // No change is required because the package explicitly requests org.apache.http.legacy
+ // and is targeted at the current version so does not need backwards compatibility.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void in_usesOptionalLibraries() {
+ PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_BASE);
+
+ // No change is required because the package explicitly requests org.apache.http.legacy
+ // and is targeted at the current version so does not need backwards compatibility.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
+ checkBackwardsCompatibility(before, after, AndroidTestBaseUpdater::new);
+ }
+}
diff --git a/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java
new file mode 100644
index 0000000..866de93
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.content.pm;
+
+import static android.content.pm.PackageBuilder.builder;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
+
+import android.content.pm.PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test for {@link AndroidTestRunnerSplitUpdater}
+ */
+@SmallTest
+@RunWith(JUnit4.class)
+public class AndroidTestRunnerSplitUpdaterTest extends PackageSharedLibraryUpdaterTest {
+
+ @Test
+ public void android_test_runner_in_usesOptionalLibraries() {
+ PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_RUNNER);
+
+ PackageBuilder after = builder()
+ .optionalLibraries(ANDROID_TEST_MOCK, ANDROID_TEST_RUNNER);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void android_test_runner_in_usesLibraries_android_test_mock_in_usesOptionalLibraries() {
+ PackageBuilder before = builder()
+ .requiredLibraries(ANDROID_TEST_RUNNER)
+ .optionalLibraries(ANDROID_TEST_MOCK);
+
+ PackageBuilder after = builder()
+ .requiredLibraries(ANDROID_TEST_RUNNER)
+ .optionalLibraries(ANDROID_TEST_MOCK);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
+ checkBackwardsCompatibility(before, after, AndroidTestRunnerSplitUpdater::new);
+ }
+}
diff --git a/core/tests/coretests/src/android/content/pm/OptionalClassRunner.java b/core/tests/coretests/src/android/content/pm/OptionalClassRunner.java
new file mode 100644
index 0000000..91697c0
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/OptionalClassRunner.java
@@ -0,0 +1,141 @@
+/*
+ * 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.content.pm;
+
+import org.junit.Assume;
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.JUnit4;
+import org.junit.runners.ParentRunner;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Will run a test class, iff a class, specified by name in the {@link OptionalClass} annotation,
+ * exists on the class path.
+ *
+ * <p>It is an {@link InitializationError} if no {@link OptionalClass} annotation is specified on
+ * the class that has {@code @RunWith(OptionalClassRunner.class)}.
+ *
+ * <p>If the named class cannot be found then the test class is reported as having been ignored.
+ */
+public class OptionalClassRunner extends Runner {
+
+ private final Runner mDelegate;
+
+ public OptionalClassRunner(Class<?> testClass) throws InitializationError {
+ OptionalClass annotation = testClass.getAnnotation(OptionalClass.class);
+ if (annotation == null) {
+ throw new InitializationError(
+ "No " + OptionalClass.class.getName() + " annotation found on " + testClass);
+ }
+
+ String className = annotation.value();
+ Runner delegate;
+ try {
+ Class.forName(className);
+ // The class could be found so create a JUnit4 delegate for the class to run.
+ delegate = new JUnit4(testClass);
+ } catch (ClassNotFoundException e) {
+ // The class could not be found so create a Runner delegate that will treat the
+ // test as having failed a test assumption.
+ delegate = new ClassNotFoundRunner(testClass, className);
+ }
+
+ this.mDelegate = delegate;
+ }
+
+ @Override
+ public Description getDescription() {
+ return mDelegate.getDescription();
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ mDelegate.run(notifier);
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ public @interface OptionalClass {
+ String value();
+ }
+
+ /**
+ * Emulates a class containing a single test that fails due to an invalid assumption caused by
+ * the missing class.
+ */
+ private static class ClassNotFoundRunner extends ParentRunner<Runner> {
+
+ private List<Runner> mChildren;
+
+ ClassNotFoundRunner(Class<?> testClass, String className)
+ throws InitializationError {
+ super(testClass);
+ this.mChildren = Collections.singletonList(new ChildRunner(testClass, className));
+ }
+
+ @Override
+ protected List<Runner> getChildren() {
+ return mChildren;
+ }
+
+ @Override
+ protected Description describeChild(Runner child) {
+ return child.getDescription();
+ }
+
+ @Override
+ protected void runChild(Runner child, RunNotifier notifier) {
+ child.run(notifier);
+ }
+
+ private class ChildRunner extends Runner {
+
+ private final Class<?> mTestClass;
+
+ private final String mClassName;
+
+ ChildRunner(Class<?> testClass, String className) {
+ this.mTestClass = testClass;
+ this.mClassName = className;
+ }
+
+ @Override
+ public Description getDescription() {
+ return Description.createTestDescription(mTestClass, "classNotFound");
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ runLeaf(new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ Assume.assumeTrue("Could not find class: " + mClassName, false);
+ }
+ }, getDescription(), notifier);
+ }
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/content/pm/OrgApacheHttpLegacyUpdaterTest.java b/core/tests/coretests/src/android/content/pm/OrgApacheHttpLegacyUpdaterTest.java
new file mode 100644
index 0000000..dcd2707
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/OrgApacheHttpLegacyUpdaterTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.content.pm;
+
+import static android.content.pm.PackageBuilder.builder;
+import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+
+import android.os.Build;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test for {@link OrgApacheHttpLegacyUpdater}
+ */
+@SmallTest
+@RunWith(OptionalClassRunner.class)
+@OptionalClassRunner.OptionalClass("android.content.pm.OrgApacheHttpLegacyUpdater")
+public class OrgApacheHttpLegacyUpdaterTest extends PackageSharedLibraryUpdaterTest {
+
+ private static final String OTHER_LIBRARY = "other.library";
+
+ @Test
+ public void targeted_at_O() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O);
+
+ // Should add org.apache.http.legacy.
+ PackageBuilder after = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_O_not_empty_usesLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(OTHER_LIBRARY);
+
+ // The org.apache.http.legacy jar should be added at the start of the list because it
+ // is not on the bootclasspath and the package targets pre-P.
+ PackageBuilder after = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(ORG_APACHE_HTTP_LEGACY, OTHER_LIBRARY);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_O_in_usesLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ // No change is required because although org.apache.http.legacy has been removed from
+ // the bootclasspath the package explicitly requests it.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void targeted_at_O_in_usesOptionalLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .optionalLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ // No change is required because although org.apache.http.legacy has been removed from
+ // the bootclasspath the package explicitly requests it.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void in_usesLibraries() {
+ PackageBuilder before = builder().requiredLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ // No change is required because the package explicitly requests org.apache.http.legacy
+ // and is targeted at the current version so does not need backwards compatibility.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void in_usesOptionalLibraries() {
+ PackageBuilder before = builder().optionalLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ // No change is required because the package explicitly requests org.apache.http.legacy
+ // and is targeted at the current version so does not need backwards compatibility.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
+ checkBackwardsCompatibility(before, after, OrgApacheHttpLegacyUpdater::new);
+ }
+}
diff --git a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
index 6996e50..c64d520 100644
--- a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
@@ -16,179 +16,158 @@
package android.content.pm;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
+import static android.content.pm.PackageBuilder.builder;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
+import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
-import android.content.pm.PackageParser.Package;
+import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
import android.os.Build;
import android.support.test.filters.SmallTest;
-import org.junit.Before;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.List;
@SmallTest
@RunWith(JUnit4.class)
-public class PackageBackwardCompatibilityTest {
-
- private static final String ORG_APACHE_HTTP_LEGACY = "org.apache.http.legacy";
-
- private static final String ANDROID_TEST_RUNNER = "android.test.runner";
-
- private static final String ANDROID_TEST_MOCK = "android.test.mock";
-
- private static final String OTHER_LIBRARY = "other.library";
-
- private Package mPackage;
-
- private static ArrayList<String> arrayList(String... strings) {
- ArrayList<String> list = new ArrayList<>();
- Collections.addAll(list, strings);
- return list;
- }
-
- @Before
- public void setUp() {
- mPackage = new Package("org.package.name");
- mPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- }
+public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdaterTest {
@Test
- public void null_usesLibraries() {
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- assertNull("usesLibraries not updated correctly", mPackage.usesLibraries);
+ public void null_usesLibraries_and_usesOptionalLibraries() {
+ PackageBuilder before = builder();
+ PackageBuilder after = builder();
+
+ checkBackwardsCompatibility(before, after);
}
+ /**
+ * Detect when the org.apache.http.legacy is not on the bootclasspath.
+ *
+ * <p>This test will be ignored when org.apache.http.legacy is not on the bootclasspath and
+ * succeed otherwise. This allows a developer to ensure that the tests are being
+ */
@Test
- public void null_usesOptionalLibraries() {
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- assertNull("usesOptionalLibraries not updated correctly", mPackage.usesOptionalLibraries);
+ public void detectWhenOAHLisOnBCP() {
+ Assume.assumeTrue(PackageBackwardCompatibility.bootClassPathContainsOAHL());
}
+ /**
+ * Detect when the android.test.base is not on the bootclasspath.
+ *
+ * <p>This test will be ignored when org.apache.http.legacy is not on the bootclasspath and
+ * succeed otherwise. This allows a developer to ensure that the tests are being
+ */
+ @Test
+ public void detectWhenATBisOnBCP() {
+ Assume.assumeTrue(PackageBackwardCompatibility.bootClassPathContainsATB());
+ }
+
+ /**
+ * Ensures that the {@link PackageBackwardCompatibility} uses {@link OrgApacheHttpLegacyUpdater}
+ * and {@link AndroidTestBaseUpdater} when necessary.
+ *
+ * <p>More comprehensive tests for that class can be found in
+ * {@link OrgApacheHttpLegacyUpdaterTest}.
+ */
@Test
public void targeted_at_O() {
- mPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
- assertEquals("usesLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY),
- mPackage.usesLibraries);
- } else {
- assertNull("usesOptionalLibraries not updated correctly", mPackage.usesLibraries);
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O);
+
+ List<String> expected = new ArrayList<>();
+ if (!PackageBackwardCompatibility.bootClassPathContainsATB()) {
+ expected.add(ANDROID_TEST_BASE);
}
- assertNull("usesOptionalLibraries not updated correctly", mPackage.usesOptionalLibraries);
+ if (!PackageBackwardCompatibility.bootClassPathContainsOAHL()) {
+ expected.add(ORG_APACHE_HTTP_LEGACY);
+ }
+
+ PackageBuilder after = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(expected);
+
+ checkBackwardsCompatibility(before, after);
}
- @Test
- public void targeted_at_O_not_empty_usesLibraries() {
- mPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
- mPackage.usesLibraries = arrayList(OTHER_LIBRARY);
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
- // The org.apache.http.legacy jar should be added at the start of the list.
- assertEquals("usesLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY, OTHER_LIBRARY),
- mPackage.usesLibraries);
- } else {
- assertEquals("usesLibraries not updated correctly",
- arrayList(OTHER_LIBRARY),
- mPackage.usesLibraries);
- }
- assertNull("usesOptionalLibraries not updated correctly", mPackage.usesOptionalLibraries);
- }
-
- @Test
- public void targeted_at_O_org_apache_http_legacy_in_usesLibraries() {
- mPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
- mPackage.usesLibraries = arrayList(ORG_APACHE_HTTP_LEGACY);
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
- assertEquals("usesLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY),
- mPackage.usesLibraries);
- } else {
- assertNull("usesLibraries not updated correctly", mPackage.usesLibraries);
- }
- assertNull("usesOptionalLibraries not updated correctly", mPackage.usesOptionalLibraries);
- }
-
- @Test
- public void targeted_at_O_org_apache_http_legacy_in_usesOptionalLibraries() {
- mPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
- mPackage.usesOptionalLibraries = arrayList(ORG_APACHE_HTTP_LEGACY);
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- assertNull("usesLibraries not updated correctly", mPackage.usesLibraries);
- if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
- assertEquals("usesOptionalLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY),
- mPackage.usesOptionalLibraries);
- } else {
- assertNull("usesOptionalLibraries not updated correctly",
- mPackage.usesOptionalLibraries);
- }
- }
-
+ /**
+ * Ensures that the {@link PackageBackwardCompatibility} uses
+ * {@link RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest}
+ * when necessary.
+ *
+ * <p>More comprehensive tests for that class can be found in
+ * {@link RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest}.
+ */
@Test
public void org_apache_http_legacy_in_usesLibraries() {
- mPackage.usesLibraries = arrayList(ORG_APACHE_HTTP_LEGACY);
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
- assertEquals("usesLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY),
- mPackage.usesLibraries);
- } else {
- assertNull("usesLibraries not updated correctly", mPackage.usesLibraries);
- }
- assertNull("usesOptionalLibraries not updated correctly", mPackage.usesOptionalLibraries);
+ Assume.assumeTrue("Test requires that "
+ + ORG_APACHE_HTTP_LEGACY + " is on the bootclasspath",
+ PackageBackwardCompatibility.bootClassPathContainsOAHL());
+
+ PackageBuilder before = builder()
+ .requiredLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ // org.apache.http.legacy should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder();
+
+ checkBackwardsCompatibility(before, after);
}
+ /**
+ * Ensures that the {@link PackageBackwardCompatibility} uses
+ * {@link RemoveUnnecessaryAndroidTestBaseLibrary}
+ * when necessary.
+ *
+ * <p>More comprehensive tests for that class can be found in
+ * {@link RemoveUnnecessaryAndroidTestBaseLibraryTest}.
+ */
@Test
- public void org_apache_http_legacy_in_usesOptionalLibraries() {
- mPackage.usesOptionalLibraries = arrayList(ORG_APACHE_HTTP_LEGACY);
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- assertNull("usesLibraries not updated correctly", mPackage.usesLibraries);
- if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
- assertEquals("usesOptionalLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY),
- mPackage.usesOptionalLibraries);
- } else {
- assertNull("usesOptionalLibraries not updated correctly",
- mPackage.usesOptionalLibraries);
- }
+ public void android_test_base_in_usesLibraries() {
+ Assume.assumeTrue("Test requires that "
+ + ANDROID_TEST_BASE + " is on the bootclasspath",
+ PackageBackwardCompatibility.bootClassPathContainsATB());
+
+ PackageBuilder before = builder()
+ .requiredLibraries(ANDROID_TEST_BASE);
+
+ // android.test.base should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder();
+
+ checkBackwardsCompatibility(before, after);
}
+ /**
+ * Ensures that the {@link PackageBackwardCompatibility} uses a
+ * {@link PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater}.
+ *
+ * <p>More comprehensive tests for that class can be found in
+ * {@link AndroidTestRunnerSplitUpdaterTest}.
+ */
@Test
public void android_test_runner_in_usesLibraries() {
- mPackage.usesLibraries = arrayList(ANDROID_TEST_RUNNER);
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- assertEquals("usesLibraries not updated correctly",
- arrayList(ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK),
- mPackage.usesLibraries);
+ PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_RUNNER);
+
+ List<String> expected = new ArrayList<>();
+ if (!PackageBackwardCompatibility.bootClassPathContainsATB()) {
+ expected.add(ANDROID_TEST_BASE);
+ }
+ expected.add(ANDROID_TEST_MOCK);
+ expected.add(ANDROID_TEST_RUNNER);
+
+ PackageBuilder after = builder()
+ .requiredLibraries(expected);
+
+ checkBackwardsCompatibility(before, after);
}
- @Test
- public void android_test_runner_in_usesOptionalLibraries() {
- mPackage.usesOptionalLibraries = arrayList(ANDROID_TEST_RUNNER);
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- assertEquals("usesOptionalLibraries not updated correctly",
- arrayList(ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK),
- mPackage.usesOptionalLibraries);
- }
-
- @Test
- public void android_test_runner_in_usesLibraries_android_test_mock_in_usesOptionalLibraries() {
- mPackage.usesLibraries = arrayList(ANDROID_TEST_RUNNER);
- mPackage.usesOptionalLibraries = arrayList(ANDROID_TEST_MOCK);
- PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- assertEquals("usesLibraries not updated correctly",
- arrayList(ANDROID_TEST_RUNNER),
- mPackage.usesLibraries);
- assertEquals("usesOptionalLibraries not updated correctly",
- arrayList(ANDROID_TEST_MOCK),
- mPackage.usesOptionalLibraries);
+ private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
+ checkBackwardsCompatibility(before, after, PackageBackwardCompatibility::getInstance);
}
}
diff --git a/core/tests/coretests/src/android/content/pm/PackageBuilder.java b/core/tests/coretests/src/android/content/pm/PackageBuilder.java
new file mode 100644
index 0000000..4ceed83
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/PackageBuilder.java
@@ -0,0 +1,95 @@
+/*
+ * 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.content.pm;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.Build;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Test support for building {@link PackageParser.Package} instances.
+ */
+class PackageBuilder {
+
+ private int mTargetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+
+ private ArrayList<String> mRequiredLibraries;
+
+ private ArrayList<String> mOptionalLibraries;
+
+ public static PackageBuilder builder() {
+ return new PackageBuilder();
+ }
+
+ public PackageParser.Package build() {
+ PackageParser.Package pkg = new PackageParser.Package("org.package.name");
+ pkg.applicationInfo.targetSdkVersion = mTargetSdkVersion;
+ pkg.usesLibraries = mRequiredLibraries;
+ pkg.usesOptionalLibraries = mOptionalLibraries;
+ return pkg;
+ }
+
+ PackageBuilder targetSdkVersion(int version) {
+ this.mTargetSdkVersion = version;
+ return this;
+ }
+
+ PackageBuilder requiredLibraries(String... names) {
+ this.mRequiredLibraries = arrayListOrNull(names);
+ return this;
+ }
+
+ PackageBuilder requiredLibraries(List<String> names) {
+ this.mRequiredLibraries = arrayListOrNull(names.toArray(new String[names.size()]));
+ return this;
+ }
+
+ PackageBuilder optionalLibraries(String... names) {
+ this.mOptionalLibraries = arrayListOrNull(names);
+ return this;
+ }
+
+ /**
+ * Check that this matches the supplied {@link PackageParser.Package}.
+ *
+ * @param pkg the instance to compare with this.
+ */
+ public void check(PackageParser.Package pkg) {
+ assertEquals("targetSdkVersion should not be changed",
+ mTargetSdkVersion,
+ pkg.applicationInfo.targetSdkVersion);
+ assertEquals("usesLibraries not updated correctly",
+ mRequiredLibraries,
+ pkg.usesLibraries);
+ assertEquals("usesOptionalLibraries not updated correctly",
+ mOptionalLibraries,
+ pkg.usesOptionalLibraries);
+ }
+
+ private static ArrayList<String> arrayListOrNull(String... strings) {
+ if (strings == null || strings.length == 0) {
+ return null;
+ }
+ ArrayList<String> list = new ArrayList<>();
+ Collections.addAll(list, strings);
+ return list;
+ }
+
+}
diff --git a/core/tests/coretests/src/android/content/pm/PackageSharedLibraryUpdaterTest.java b/core/tests/coretests/src/android/content/pm/PackageSharedLibraryUpdaterTest.java
new file mode 100644
index 0000000..d5d3d7a
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/PackageSharedLibraryUpdaterTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.content.pm;
+
+import java.util.function.Supplier;
+
+/**
+ * Helper for classes that test {@link PackageSharedLibraryUpdater}.
+ */
+abstract class PackageSharedLibraryUpdaterTest {
+
+ static void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after,
+ Supplier<PackageSharedLibraryUpdater> updaterSupplier) {
+ PackageParser.Package pkg = before.build();
+ updaterSupplier.get().updatePackage(pkg);
+ after.check(pkg);
+ }
+}
diff --git a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
new file mode 100644
index 0000000..3dba440
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.content.pm;
+
+import static android.content.pm.PackageBuilder.builder;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
+
+import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
+import android.os.Build;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test for {@link RemoveUnnecessaryAndroidTestBaseLibrary}
+ */
+@SmallTest
+@RunWith(JUnit4.class)
+public class RemoveUnnecessaryAndroidTestBaseLibraryTest
+ extends PackageSharedLibraryUpdaterTest {
+
+ private static final String OTHER_LIBRARY = "other.library";
+
+ @Test
+ public void targeted_at_O() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O);
+
+ // No change required.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void targeted_at_O_not_empty_usesLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(OTHER_LIBRARY);
+
+ // No change required.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void targeted_at_O_in_usesLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(ANDROID_TEST_BASE);
+
+ // android.test.base should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_O_in_usesOptionalLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .optionalLibraries(ANDROID_TEST_BASE);
+
+ // android.test.base should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void in_usesLibraries() {
+ PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_BASE);
+
+ // android.test.base should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder();
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void in_usesOptionalLibraries() {
+ PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_BASE);
+
+ // android.test.base should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder();
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void in_bothLibraries() {
+ PackageBuilder before = builder()
+ .requiredLibraries(ANDROID_TEST_BASE)
+ .optionalLibraries(ANDROID_TEST_BASE);
+
+ // android.test.base should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder();
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
+ // TODO(b/72538146) - Cannot use constructor reference here because it is also used in
+ // PackageBackwardCompatibility and that seems to create a package-private lambda in
+ // android.content.pm which this then tries to reuse but fails because it cannot access
+ // package-private classes/members because the test is loaded by a different ClassLoader
+ // than the lambda.
+ checkBackwardsCompatibility(before, after,
+ () -> new RemoveUnnecessaryAndroidTestBaseLibrary());
+ }
+
+}
diff --git a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
new file mode 100644
index 0000000..15b27d7
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.content.pm;
+
+import static android.content.pm.PackageBuilder.builder;
+import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+
+import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryOrgApacheHttpLegacyLibrary;
+import android.os.Build;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test for {@link RemoveUnnecessaryOrgApacheHttpLegacyLibrary}
+ */
+@SmallTest
+@RunWith(JUnit4.class)
+public class RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest
+ extends PackageSharedLibraryUpdaterTest {
+
+ private static final String OTHER_LIBRARY = "other.library";
+
+ @Test
+ public void targeted_at_O() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O);
+
+ // No change required.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void targeted_at_O_not_empty_usesLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(OTHER_LIBRARY);
+
+ // No change required.
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void targeted_at_O_in_usesLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .requiredLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ // org.apache.http.legacy should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_O_in_usesOptionalLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O)
+ .optionalLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ // org.apache.http.legacy should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder()
+ .targetSdkVersion(Build.VERSION_CODES.O);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void in_usesLibraries() {
+ PackageBuilder before = builder().requiredLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ // org.apache.http.legacy should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder();
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void in_usesOptionalLibraries() {
+ PackageBuilder before = builder().optionalLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ // org.apache.http.legacy should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder();
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void in_bothLibraries() {
+ PackageBuilder before = builder()
+ .requiredLibraries(ORG_APACHE_HTTP_LEGACY)
+ .optionalLibraries(ORG_APACHE_HTTP_LEGACY);
+
+ // org.apache.http.legacy should be removed from the libraries because it is provided
+ // on the bootclasspath and providing both increases start up cost unnecessarily.
+ PackageBuilder after = builder();
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
+ // TODO(b/72538146) - Cannot use constructor reference here because it is also used in
+ // PackageBackwardCompatibility and that seems to create a package-private lambda in
+ // android.content.pm which this then tries to reuse but fails because it cannot access
+ // package-private classes/members because the test is loaded by a different ClassLoader
+ // than the lambda.
+ checkBackwardsCompatibility(before, after,
+ () -> new RemoveUnnecessaryOrgApacheHttpLegacyLibrary());
+ }
+}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 2f747ec..0083b01 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -245,6 +245,7 @@
Settings.Global.INTENT_FIREWALL_UPDATE_CONTENT_URL,
Settings.Global.INTENT_FIREWALL_UPDATE_METADATA_URL,
Settings.Global.JOB_SCHEDULER_CONSTANTS,
+ Settings.Global.KEEP_PROFILE_IN_BACKGROUND,
Settings.Global.LANG_ID_UPDATE_CONTENT_URL,
Settings.Global.LANG_ID_UPDATE_METADATA_URL,
Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
@@ -377,6 +378,7 @@
Settings.Global.TETHER_SUPPORTED,
Settings.Global.TEXT_CLASSIFIER_CONSTANTS,
Settings.Global.THEATER_MODE_ON,
+ Settings.Global.TIME_ONLY_MODE_ENABLED,
Settings.Global.TRANSITION_ANIMATION_SCALE,
Settings.Global.TRUSTED_SOUND,
Settings.Global.TZINFO_UPDATE_CONTENT_URL,
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
index 8a81743..cf41eb8 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
@@ -86,15 +86,11 @@
.setSignature(signature)
.build();
- // Parcel and unparcel using ParcelableWrapper.
- final TextClassification.ParcelableWrapper parcelableReference = new TextClassification
- .ParcelableWrapper(reference);
+ // Parcel and unparcel
final Parcel parcel = Parcel.obtain();
- parcelableReference.writeToParcel(parcel, parcelableReference.describeContents());
+ reference.writeToParcel(parcel, reference.describeContents());
parcel.setDataPosition(0);
- final TextClassification result =
- TextClassification.ParcelableWrapper.CREATOR.createFromParcel(
- parcel).getTextClassification();
+ final TextClassification result = TextClassification.CREATOR.createFromParcel(parcel);
assertEquals(text, result.getText());
assertEquals(signature, result.getSignature());
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
index a82542c..d6ac845 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
@@ -68,8 +68,8 @@
public void testParcel() {
final String fullText = "this is just a test";
final TextLinks reference = new TextLinks.Builder(fullText)
- .addLink(new TextLinks.TextLink(fullText, 0, 4, getEntityScores(0.f, 0.f, 1.f)))
- .addLink(new TextLinks.TextLink(fullText, 5, 12, getEntityScores(.8f, .1f, .5f)))
+ .addLink(0, 4, getEntityScores(0.f, 0.f, 1.f))
+ .addLink(5, 12, getEntityScores(.8f, .1f, .5f))
.build();
// Parcel and unparcel.
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
index e920236..a6ea021 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
@@ -45,15 +45,11 @@
.setSignature(signature)
.build();
- // Parcel and unparcel using ParcelableWrapper.
- final TextSelection.ParcelableWrapper parcelableReference = new TextSelection
- .ParcelableWrapper(reference);
+ // Parcel and unparcel
final Parcel parcel = Parcel.obtain();
- parcelableReference.writeToParcel(parcel, parcelableReference.describeContents());
+ reference.writeToParcel(parcel, reference.describeContents());
parcel.setDataPosition(0);
- final TextSelection result =
- TextSelection.ParcelableWrapper.CREATOR.createFromParcel(
- parcel).getTextSelection();
+ final TextSelection result = TextSelection.CREATOR.createFromParcel(parcel);
assertEquals(startIndex, result.getSelectionStartIndex());
assertEquals(endIndex, result.getSelectionEndIndex());
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index bbca12f..69e5670 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -325,9 +325,9 @@
TextClassificationManager textClassificationManager =
mActivity.getSystemService(TextClassificationManager.class);
TextClassifier textClassifier = textClassificationManager.getTextClassifier();
- SpannableString content = new SpannableString("Call me at +19148277737");
+ Spannable content = new SpannableString("Call me at +19148277737");
TextLinks links = textClassifier.generateLinks(content);
- links.apply(content, null);
+ links.apply(content, TextLinks.APPLY_STRATEGY_REPLACE, null);
mActivityRule.runOnUiThread(() -> {
textView.setText(content);
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index c0bc3a8..b18fa74 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -24,7 +24,6 @@
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.Bundle;
-import android.os.IBinder;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.test.InstrumentationRegistry;
@@ -270,8 +269,8 @@
}
@Override
- public void startActivityAsCaller(Intent intent, @Nullable Bundle options,
- IBinder permissionToken, boolean ignoreTargetSecurity, int userId) {
+ public void startActivityAsCaller(Intent intent, @Nullable Bundle options, boolean
+ ignoreTargetSecurity, int userId) {
mStartActivityIntent = intent;
mUserIdActivityLaunchedIn = userId;
}
@@ -294,4 +293,4 @@
return mPm;
}
}
-}
+}
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
index 4d34721..ce3ffb9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
@@ -772,7 +772,8 @@
latch.countDown();
}
});
- launchIntent.putExtras(extras);
+ launchIntent.putExtras(extras)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sContext.startActivity(launchIntent);
if (latch.await(START_ACTIVITY_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
if (binders[0] == null) {
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
index 99bcd6c..a6c5373 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
@@ -36,10 +36,8 @@
include $(BUILD_PACKAGE)
-ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
$(hide) mkdir -p $(dir $@)
$(MAINDEXCLASSES) $< 1>$@
$(built_dex_intermediate): $(mainDexList)
-endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/AndroidManifest.xml
index e3068920..7cd01e54 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/AndroidManifest.xml
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/AndroidManifest.xml
@@ -7,6 +7,8 @@
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="19" />
+ <!-- Required for com.android.framework.multidexlegacytestservices.test2 -->
+ <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
<application
android:label="MultiDexLegacyTestServices">
@@ -124,6 +126,6 @@
<action android:name="com.android.framework.multidexlegacytestservices.action.Service19" />
</intent-filter>
</service>
- </application>
+ </application>
</manifest>
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java
index 7b83999..cb0a591 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/src/com/android/framework/multidexlegacytestservices/AbstractService.java
@@ -60,35 +60,40 @@
// of the result file will be too big.
RandomAccessFile raf = new RandomAccessFile(resultFile, "rw");
raf.seek(raf.length());
- Log.i(TAG, "Writing 0x42434445 at " + raf.length() + " in " + resultFile.getPath());
- raf.writeInt(0x42434445);
+ if (raf.length() == 0) {
+ Log.i(TAG, "Writing 0x42434445 at " + raf.length() + " in " + resultFile.getPath());
+ raf.writeInt(0x42434445);
+ } else {
+ Log.w(TAG, "Service was restarted appending 0x42434445 twice at " + raf.length()
+ + " in " + resultFile.getPath());
+ raf.writeInt(0x42434445);
+ raf.writeInt(0x42434445);
+ }
raf.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- MultiDex.install(applicationContext);
- Log.i(TAG, "Multi dex installation done.");
+ MultiDex.install(applicationContext);
+ Log.i(TAG, "Multi dex installation done.");
- int value = getValue();
- Log.i(TAG, "Saving the result (" + value + ") to " + resultFile.getPath());
- try {
+ int value = getValue();
+ Log.i(TAG, "Saving the result (" + value + ") to " + resultFile.getPath());
// Append the check value in result file, keeping the constant values already written.
- RandomAccessFile raf = new RandomAccessFile(resultFile, "rw");
+ raf = new RandomAccessFile(resultFile, "rw");
raf.seek(raf.length());
Log.i(TAG, "Writing result at " + raf.length() + " in " + resultFile.getPath());
raf.writeInt(value);
raf.close();
} catch (IOException e) {
- e.printStackTrace();
- }
- try {
- // Writing end of processing flags, the existence of the file is the criteria
- RandomAccessFile raf = new RandomAccessFile(new File(applicationContext.getFilesDir(), getId() + ".complete"), "rw");
- Log.i(TAG, "creating complete file " + resultFile.getPath());
- raf.writeInt(0x32333435);
- raf.close();
- } catch (IOException e) {
- e.printStackTrace();
+ throw new AssertionError(e);
+ } finally {
+ try {
+ // Writing end of processing flags, the existence of the file is the criteria
+ RandomAccessFile raf = new RandomAccessFile(
+ new File(applicationContext.getFilesDir(), getId() + ".complete"), "rw");
+ Log.i(TAG, "creating complete file " + resultFile.getPath());
+ raf.writeInt(0x32333435);
+ raf.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
}
@@ -119,9 +124,10 @@
intermediate = ReflectIntermediateClass.get(45, 80, 20 /* 5 seems enough on a nakasi,
using 20 to get some margin */);
} catch (Exception e) {
- e.printStackTrace();
+ throw new AssertionError(e);
}
- int value = new com.android.framework.multidexlegacytestservices.manymethods.Big001().get1() +
+ int value =
+ new com.android.framework.multidexlegacytestservices.manymethods.Big001().get1() +
new com.android.framework.multidexlegacytestservices.manymethods.Big002().get2() +
new com.android.framework.multidexlegacytestservices.manymethods.Big003().get3() +
new com.android.framework.multidexlegacytestservices.manymethods.Big004().get4() +
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk
new file mode 100644
index 0000000..f3d98a8
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := MultiDexLegacyTestServicesTests2
+
+LOCAL_JAVA_LIBRARIES := android-support-multidex
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SDK_VERSION := 9
+
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml
new file mode 100644
index 0000000..0ab2959
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.framework.multidexlegacytestservices.test2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="9" />
+ <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.framework.multidexlegacytestservices" />
+
+ <application
+ android:label="multidexlegacytestservices.test2" >
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java
new file mode 100644
index 0000000..900f203
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java
@@ -0,0 +1,381 @@
+/*
+ * 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.framework.multidexlegacytestservices.test2;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.concurrent.TimeoutException;
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Run the tests with: <code>adb shell am instrument -w
+ * com.android.framework.multidexlegacytestservices.test2/android.support.test.runner.AndroidJUnitRunner
+ * </code>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ServicesTests {
+ private static final String TAG = "ServicesTests";
+
+ static {
+ Log.i(TAG, "Initializing");
+ }
+
+ private class ExtensionFilter implements FileFilter {
+ private final String ext;
+
+ public ExtensionFilter(String ext) {
+ this.ext = ext;
+ }
+
+ @Override
+ public boolean accept(File file) {
+ return file.getName().endsWith(ext);
+ }
+ }
+
+ private class ExtractedZipFilter extends ExtensionFilter {
+ public ExtractedZipFilter() {
+ super(".zip");
+ }
+
+ @Override
+ public boolean accept(File file) {
+ return super.accept(file) && !file.getName().startsWith("tmp-");
+ }
+ }
+
+ private static final int ENDHDR = 22;
+
+ private static final String SERVICE_BASE_ACTION =
+ "com.android.framework.multidexlegacytestservices.action.Service";
+ private static final int MIN_SERVICE = 1;
+ private static final int MAX_SERVICE = 19;
+ private static final String COMPLETION_SUCCESS = "Success";
+
+ private File targetFilesDir;
+
+ @Before
+ public void setup() throws Exception {
+ Log.i(TAG, "setup");
+ killServices();
+
+ File applicationDataDir =
+ new File(InstrumentationRegistry.getTargetContext().getApplicationInfo().dataDir);
+ clearDirContent(applicationDataDir);
+ targetFilesDir = InstrumentationRegistry.getTargetContext().getFilesDir();
+
+ Log.i(TAG, "setup done");
+ }
+
+ @Test
+ public void testStressConcurentLaunch() throws Exception {
+ startServices();
+ waitServicesCompletion();
+ String completionStatus = getServicesCompletionStatus();
+ if (completionStatus != COMPLETION_SUCCESS) {
+ Assert.fail(completionStatus);
+ }
+ }
+
+ @Test
+ public void testRecoverFromZipCorruption() throws Exception {
+ int serviceId = 1;
+ // Ensure extraction.
+ initServicesWorkFiles();
+ startService(serviceId);
+ waitServicesCompletion(serviceId);
+
+ // Corruption of the extracted zips.
+ tamperAllExtractedZips();
+
+ killServices();
+ checkRecover();
+ }
+
+ @Test
+ public void testRecoverFromDexCorruption() throws Exception {
+ int serviceId = 1;
+ // Ensure extraction.
+ initServicesWorkFiles();
+ startService(serviceId);
+ waitServicesCompletion(serviceId);
+
+ // Corruption of the odex files.
+ tamperAllOdex();
+
+ killServices();
+ checkRecover();
+ }
+
+ @Test
+ public void testRecoverFromZipCorruptionStressTest() throws Exception {
+ Thread startServices =
+ new Thread() {
+ @Override
+ public void run() {
+ startServices();
+ }
+ };
+
+ startServices.start();
+
+ // Start services lasts more than 80s, lets cause a few corruptions during this interval.
+ for (int i = 0; i < 80; i++) {
+ Thread.sleep(1000);
+ tamperAllExtractedZips();
+ }
+ startServices.join();
+ try {
+ waitServicesCompletion();
+ } catch (TimeoutException e) {
+ // Can happen.
+ }
+
+ killServices();
+ checkRecover();
+ }
+
+ @Test
+ public void testRecoverFromDexCorruptionStressTest() throws Exception {
+ Thread startServices =
+ new Thread() {
+ @Override
+ public void run() {
+ startServices();
+ }
+ };
+
+ startServices.start();
+
+ // Start services lasts more than 80s, lets cause a few corruptions during this interval.
+ for (int i = 0; i < 80; i++) {
+ Thread.sleep(1000);
+ tamperAllOdex();
+ }
+ startServices.join();
+ try {
+ waitServicesCompletion();
+ } catch (TimeoutException e) {
+ // Will probably happen most of the time considering what we're doing...
+ }
+
+ killServices();
+ checkRecover();
+ }
+
+ private static void clearDirContent(File dir) {
+ for (File subElement : dir.listFiles()) {
+ if (subElement.isDirectory()) {
+ clearDirContent(subElement);
+ }
+ if (!subElement.delete()) {
+ throw new AssertionError("Failed to clear '" + subElement.getAbsolutePath() + "'");
+ }
+ }
+ }
+
+ private void startServices() {
+ Log.i(TAG, "start services");
+ initServicesWorkFiles();
+ for (int i = MIN_SERVICE; i <= MAX_SERVICE; i++) {
+ startService(i);
+ try {
+ Thread.sleep((i - 1) * (1 << (i / 5)));
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ private void startService(int serviceId) {
+ Log.i(TAG, "start service " + serviceId);
+ InstrumentationRegistry.getContext().startService(new Intent(SERVICE_BASE_ACTION + serviceId));
+ }
+
+ private void initServicesWorkFiles() {
+ for (int i = MIN_SERVICE; i <= MAX_SERVICE; i++) {
+ File resultFile = new File(targetFilesDir, "Service" + i);
+ resultFile.delete();
+ Assert.assertFalse(
+ "Failed to delete result file '" + resultFile.getAbsolutePath() + "'.",
+ resultFile.exists());
+ File completeFile = new File(targetFilesDir, "Service" + i + ".complete");
+ completeFile.delete();
+ Assert.assertFalse(
+ "Failed to delete completion file '" + completeFile.getAbsolutePath() + "'.",
+ completeFile.exists());
+ }
+ }
+
+ private void waitServicesCompletion() throws TimeoutException {
+ Log.i(TAG, "start sleeping");
+ int attempt = 0;
+ int maxAttempt = 50; // 10 is enough for a nexus S
+ do {
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ }
+ attempt++;
+ if (attempt >= maxAttempt) {
+ throw new TimeoutException();
+ }
+ } while (!areAllServicesCompleted());
+ }
+
+ private void waitServicesCompletion(int serviceId) throws TimeoutException {
+ Log.i(TAG, "start sleeping");
+ int attempt = 0;
+ int maxAttempt = 50; // 10 is enough for a nexus S
+ do {
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ }
+ attempt++;
+ if (attempt >= maxAttempt) {
+ throw new TimeoutException();
+ }
+ } while (isServiceRunning(serviceId));
+ }
+
+ private String getServicesCompletionStatus() {
+ String status = COMPLETION_SUCCESS;
+ for (int i = MIN_SERVICE; i <= MAX_SERVICE; i++) {
+ File resultFile = new File(targetFilesDir, "Service" + i);
+ if (!resultFile.isFile()) {
+ status = "Service" + i + " never completed.";
+ break;
+ }
+ if (resultFile.length() != 8) {
+ status = "Service" + i + " was restarted.";
+ break;
+ }
+ }
+ Log.i(TAG, "Services completion status: " + status);
+ return status;
+ }
+
+ private String getServiceCompletionStatus(int serviceId) {
+ String status = COMPLETION_SUCCESS;
+ File resultFile = new File(targetFilesDir, "Service" + serviceId);
+ if (!resultFile.isFile()) {
+ status = "Service" + serviceId + " never completed.";
+ } else if (resultFile.length() != 8) {
+ status = "Service" + serviceId + " was restarted.";
+ }
+ Log.i(TAG, "Service " + serviceId + " completion status: " + status);
+ return status;
+ }
+
+ private boolean areAllServicesCompleted() {
+ for (int i = MIN_SERVICE; i <= MAX_SERVICE; i++) {
+ if (isServiceRunning(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isServiceRunning(int i) {
+ File completeFile = new File(targetFilesDir, "Service" + i + ".complete");
+ return !completeFile.exists();
+ }
+
+ private File getSecondaryFolder() {
+ File dir =
+ new File(
+ new File(
+ InstrumentationRegistry.getTargetContext().getApplicationInfo().dataDir,
+ "code_cache"),
+ "secondary-dexes");
+ Assert.assertTrue(dir.getAbsolutePath(), dir.isDirectory());
+ return dir;
+ }
+
+ private void tamperAllExtractedZips() throws IOException {
+ // First attempt was to just overwrite zip entries but keep central directory, this was no
+ // trouble for Dalvik that was just ignoring those zip and using the odex files.
+ Log.i(TAG, "Tamper extracted zip files by overwriting all content by '\\0's.");
+ byte[] zeros = new byte[4 * 1024];
+ // Do not tamper tmp zip during their extraction.
+ for (File zip : getSecondaryFolder().listFiles(new ExtractedZipFilter())) {
+ long fileLength = zip.length();
+ Assert.assertTrue(fileLength > ENDHDR);
+ zip.setWritable(true);
+ RandomAccessFile raf = new RandomAccessFile(zip, "rw");
+ try {
+ int index = 0;
+ while (index < fileLength) {
+ int length = (int) Math.min(zeros.length, fileLength - index);
+ raf.write(zeros, 0, length);
+ index += length;
+ }
+ } finally {
+ raf.close();
+ }
+ }
+ }
+
+ private void tamperAllOdex() throws IOException {
+ Log.i(TAG, "Tamper odex files by overwriting some content by '\\0's.");
+ byte[] zeros = new byte[4 * 1024];
+ // I think max size would be 40 (u1[8] + 8 u4) but it's a test so lets take big margins.
+ int savedSizeForOdexHeader = 80;
+ for (File odex : getSecondaryFolder().listFiles(new ExtensionFilter(".dex"))) {
+ long fileLength = odex.length();
+ Assert.assertTrue(fileLength > zeros.length + savedSizeForOdexHeader);
+ odex.setWritable(true);
+ RandomAccessFile raf = new RandomAccessFile(odex, "rw");
+ try {
+ raf.seek(savedSizeForOdexHeader);
+ raf.write(zeros, 0, zeros.length);
+ } finally {
+ raf.close();
+ }
+ }
+ }
+
+ private void checkRecover() throws TimeoutException {
+ Log.i(TAG, "Check recover capability");
+ int serviceId = 1;
+ // Start one service and check it was able to run correctly even if a previous run failed.
+ initServicesWorkFiles();
+ startService(serviceId);
+ waitServicesCompletion(serviceId);
+ String completionStatus = getServiceCompletionStatus(serviceId);
+ if (completionStatus != COMPLETION_SUCCESS) {
+ Assert.fail(completionStatus);
+ }
+ }
+
+ private void killServices() {
+ ((ActivityManager)
+ InstrumentationRegistry.getContext().getSystemService(Context.ACTIVITY_SERVICE))
+ .killBackgroundProcesses("com.android.framework.multidexlegacytestservices");
+ }
+}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 09192f4..04006b1 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -179,6 +179,8 @@
<!-- This is a list of all the libraries available for application
code to link against. -->
+ <library name="android.test.base"
+ file="/system/framework/android.test.base.jar" />
<library name="android.test.mock"
file="/system/framework/android.test.mock.jar" />
<library name="android.test.runner"
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 6c8aaf0..8addffbb 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -369,7 +369,6 @@
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.REAL_GET_TASKS"/>
<permission name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE"/>
- <permission name="android.permission.START_ACTIVITY_AS_CALLER"/>
<permission name="android.permission.START_TASKS_FROM_RECENTS"/>
<permission name="android.permission.STATUS_BAR"/>
<permission name="android.permission.STOP_APP_SWITCHES"/>
diff --git a/docs/html/reference/images/text/style/clickablespan.png b/docs/html/reference/images/text/style/clickablespan.png
new file mode 100644
index 0000000..8e3e6bf
--- /dev/null
+++ b/docs/html/reference/images/text/style/clickablespan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/customquotespan.png b/docs/html/reference/images/text/style/customquotespan.png
new file mode 100644
index 0000000..27f521a
--- /dev/null
+++ b/docs/html/reference/images/text/style/customquotespan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/defaultquotespan.png b/docs/html/reference/images/text/style/defaultquotespan.png
new file mode 100644
index 0000000..6c5a41f
--- /dev/null
+++ b/docs/html/reference/images/text/style/defaultquotespan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/ltralignmentspan.png b/docs/html/reference/images/text/style/ltralignmentspan.png
new file mode 100644
index 0000000..6ee5943
--- /dev/null
+++ b/docs/html/reference/images/text/style/ltralignmentspan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/rtlalignmentspan.png b/docs/html/reference/images/text/style/rtlalignmentspan.png
new file mode 100644
index 0000000..952258d
--- /dev/null
+++ b/docs/html/reference/images/text/style/rtlalignmentspan.png
Binary files differ
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 3de050b..bbf2145 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -148,7 +148,7 @@
throw new FileNotFoundException(mUri.toString());
}
- return createFromStream(is);
+ return createFromStream(is, true);
}
final FileDescriptor fd = assetFd.getFileDescriptor();
@@ -160,7 +160,7 @@
Os.lseek(fd, offset, SEEK_SET);
decoder = nCreate(fd);
} catch (ErrnoException e) {
- decoder = createFromStream(new FileInputStream(fd));
+ decoder = createFromStream(new FileInputStream(fd), true);
}
} finally {
if (decoder == null) {
@@ -180,7 +180,7 @@
try {
Os.lseek(fd, 0, SEEK_CUR);
} catch (ErrnoException e) {
- return createFromStream(stream);
+ return createFromStream(stream, true);
}
ImageDecoder decoder = null;
@@ -191,13 +191,15 @@
IoUtils.closeQuietly(stream);
} else {
decoder.mInputStream = stream;
+ decoder.mOwnsInputStream = true;
}
}
return decoder;
}
@NonNull
- private static ImageDecoder createFromStream(@NonNull InputStream is) throws IOException {
+ private static ImageDecoder createFromStream(@NonNull InputStream is,
+ boolean closeInputStream) throws IOException {
// Arbitrary size matches BitmapFactory.
byte[] storage = new byte[16 * 1024];
ImageDecoder decoder = null;
@@ -205,9 +207,12 @@
decoder = nCreate(is, storage);
} finally {
if (decoder == null) {
- IoUtils.closeQuietly(is);
+ if (closeInputStream) {
+ IoUtils.closeQuietly(is);
+ }
} else {
decoder.mInputStream = is;
+ decoder.mOwnsInputStream = closeInputStream;
decoder.mTempStorage = storage;
}
}
@@ -215,6 +220,9 @@
return decoder;
}
+ /**
+ * For backwards compatibility, this does *not* close the InputStream.
+ */
private static class InputStreamSource extends Source {
InputStreamSource(Resources res, InputStream is, int inputDensity) {
if (is == null) {
@@ -244,7 +252,7 @@
}
InputStream is = mInputStream;
mInputStream = null;
- return createFromStream(is);
+ return createFromStream(is, false);
}
}
}
@@ -293,6 +301,7 @@
IoUtils.closeQuietly(is);
} else {
decoder.mInputStream = is;
+ decoder.mOwnsInputStream = true;
}
}
return decoder;
@@ -339,6 +348,16 @@
public String getMimeType() {
return mDecoder.getMimeType();
}
+
+ /**
+ * Whether the image is animated.
+ *
+ * <p>Calling {@link #decodeDrawable} will return an
+ * {@link AnimatedImageDrawable}.</p>
+ */
+ public boolean isAnimated() {
+ return mDecoder.mAnimated;
+ }
};
/**
@@ -426,6 +445,7 @@
// Objects for interacting with the input.
private InputStream mInputStream;
+ private boolean mOwnsInputStream;
private byte[] mTempStorage;
private AssetFileDescriptor mAssetFd;
private final AtomicBoolean mClosed = new AtomicBoolean();
@@ -454,6 +474,10 @@
mCloseGuard.warnIfOpen();
}
+ // Avoid closing these in finalizer.
+ mInputStream = null;
+ mAssetFd = null;
+
close();
} finally {
super.finalize();
@@ -797,7 +821,9 @@
nClose(mNativePtr);
mNativePtr = 0;
- IoUtils.closeQuietly(mInputStream);
+ if (mOwnsInputStream) {
+ IoUtils.closeQuietly(mInputStream);
+ }
IoUtils.closeQuietly(mAssetFd);
mInputStream = null;
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index 3034a10..bd49b87 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -16,18 +16,32 @@
package android.graphics.drawable;
+import dalvik.annotation.optimization.FastNative;
+
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.InflateException;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.ImageDecoder;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.os.SystemClock;
+import android.os.Handler;
+import android.os.Looper;
import android.util.DisplayMetrics;
+import android.util.TypedValue;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import libcore.io.IoUtils;
import libcore.util.NativeAllocationRegistry;
@@ -35,17 +49,37 @@
import java.io.IOException;
import java.io.InputStream;
import java.lang.Runnable;
+import java.util.ArrayList;
/**
- * @hide
+ * {@link Drawable} for drawing animated images (like GIF).
+ *
+ * <p>Created by {@link ImageDecoder#decodeDrawable}. A user needs to call
+ * {@link #start} to start the animation.</p>
*/
-public class AnimatedImageDrawable extends Drawable implements Animatable {
- private final long mNativePtr;
- private final InputStream mInputStream;
- private final AssetFileDescriptor mAssetFd;
+public class AnimatedImageDrawable extends Drawable implements Animatable2 {
+ private int mIntrinsicWidth;
+ private int mIntrinsicHeight;
- private final int mIntrinsicWidth;
- private final int mIntrinsicHeight;
+ private boolean mStarting;
+
+ private Handler mHandler;
+
+ private class State {
+ State(long nativePtr, InputStream is, AssetFileDescriptor afd) {
+ mNativePtr = nativePtr;
+ mInputStream = is;
+ mAssetFd = afd;
+ }
+
+ public final long mNativePtr;
+
+ // These just keep references so the native code can continue using them.
+ private final InputStream mInputStream;
+ private final AssetFileDescriptor mAssetFd;
+ }
+
+ private State mState;
private Runnable mRunnable = new Runnable() {
@Override
@@ -55,6 +89,95 @@
};
/**
+ * Pass this to {@link #setLoopCount} to loop infinitely.
+ *
+ * <p>{@link Animatable2.AnimationCallback#onAnimationEnd} will never be
+ * called unless there is an error.</p>
+ */
+ public static final int LOOP_INFINITE = -1;
+
+ /**
+ * Specify the number of times to loop the animation.
+ *
+ * <p>By default, the loop count in the encoded data is respected.</p>
+ */
+ public void setLoopCount(int loopCount) {
+ if (mState == null) {
+ throw new IllegalStateException("called setLoopCount on empty AnimatedImageDrawable");
+ }
+ nSetLoopCount(mState.mNativePtr, loopCount);
+ }
+
+ /**
+ * Create an empty AnimatedImageDrawable.
+ */
+ public AnimatedImageDrawable() {
+ mState = null;
+ }
+
+ @Override
+ public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
+ throws XmlPullParserException, IOException {
+ super.inflate(r, parser, attrs, theme);
+
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimatedImageDrawable);
+ updateStateFromTypedArray(a, mSrcDensityOverride);
+ }
+
+ private void updateStateFromTypedArray(TypedArray a, int srcDensityOverride)
+ throws XmlPullParserException {
+ final Resources r = a.getResources();
+ final int srcResId = a.getResourceId(R.styleable.AnimatedImageDrawable_src, 0);
+ if (srcResId != 0) {
+ // Follow the density handling in BitmapDrawable.
+ final TypedValue value = new TypedValue();
+ r.getValueForDensity(srcResId, srcDensityOverride, value, true);
+ if (srcDensityOverride > 0 && value.density > 0
+ && value.density != TypedValue.DENSITY_NONE) {
+ if (value.density == srcDensityOverride) {
+ value.density = r.getDisplayMetrics().densityDpi;
+ } else {
+ value.density =
+ (value.density * r.getDisplayMetrics().densityDpi) / srcDensityOverride;
+ }
+ }
+
+ int density = Bitmap.DENSITY_NONE;
+ if (value.density == TypedValue.DENSITY_DEFAULT) {
+ density = DisplayMetrics.DENSITY_DEFAULT;
+ } else if (value.density != TypedValue.DENSITY_NONE) {
+ density = value.density;
+ }
+
+ Drawable drawable = null;
+ try {
+ InputStream is = r.openRawResource(srcResId, value);
+ ImageDecoder.Source source = ImageDecoder.createSource(r, is, density);
+ drawable = ImageDecoder.decodeDrawable(source, (decoder, info, src) -> {
+ if (!info.isAnimated()) {
+ throw new IllegalArgumentException("image is not animated");
+ }
+ });
+ } catch (IOException e) {
+ throw new XmlPullParserException(a.getPositionDescription() +
+ ": <animated-image> requires a valid 'src' attribute", null, e);
+ }
+
+ if (!(drawable instanceof AnimatedImageDrawable)) {
+ throw new XmlPullParserException(a.getPositionDescription() +
+ ": <animated-image> did not decode animated");
+ }
+
+ // Transfer the state of other to this one. other will be discarded.
+ AnimatedImageDrawable other = (AnimatedImageDrawable) drawable;
+ mState = other.mState;
+ other.mState = null;
+ mIntrinsicWidth = other.mIntrinsicWidth;
+ mIntrinsicHeight = other.mIntrinsicHeight;
+ }
+ }
+
+ /**
* @hide
* This should only be called by ImageDecoder.
*
@@ -80,30 +203,14 @@
mIntrinsicHeight = cropRect.height();
}
- mNativePtr = nCreate(nativeImageDecoder, decoder, width, height, cropRect);
- mInputStream = inputStream;
- mAssetFd = afd;
+ mState = new State(nCreate(nativeImageDecoder, decoder, width, height, cropRect),
+ inputStream, afd);
// FIXME: Use the right size for the native allocation.
long nativeSize = 200;
NativeAllocationRegistry registry = new NativeAllocationRegistry(
AnimatedImageDrawable.class.getClassLoader(), nGetNativeFinalizer(), nativeSize);
- registry.registerNativeAllocation(this, mNativePtr);
- }
-
- @Override
- protected void finalize() throws Throwable {
- // FIXME: It's a shame that we have *both* a native finalizer and a Java
- // one. The native one is necessary to report how much memory is being
- // used natively, and this one is necessary to close the input. An
- // alternative might be to read the entire stream ahead of time, so we
- // can eliminate the Java finalizer.
- try {
- IoUtils.closeQuietly(mInputStream);
- IoUtils.closeQuietly(mAssetFd);
- } finally {
- super.finalize();
- }
+ registry.registerNativeAllocation(mState, mState.mNativePtr);
}
@Override
@@ -116,13 +223,29 @@
return mIntrinsicHeight;
}
+ // nDraw returns -1 if the animation has finished.
+ private static final int FINISHED = -1;
+
@Override
public void draw(@NonNull Canvas canvas) {
- long nextUpdate = nDraw(mNativePtr, canvas.getNativeCanvasWrapper());
+ if (mState == null) {
+ throw new IllegalStateException("called draw on empty AnimatedImageDrawable");
+ }
+
+ if (mStarting) {
+ mStarting = false;
+
+ postOnAnimationStart();
+ }
+
+ long nextUpdate = nDraw(mState.mNativePtr, canvas.getNativeCanvasWrapper());
// a value <= 0 indicates that the drawable is stopped or that renderThread
// will manage the animation
if (nextUpdate > 0) {
scheduleSelf(mRunnable, nextUpdate);
+ } else if (nextUpdate == FINISHED) {
+ // This means the animation was drawn in software mode and ended.
+ postOnAnimationEnd();
}
}
@@ -132,19 +255,31 @@
throw new IllegalArgumentException("Alpha must be between 0 and"
+ " 255! provided " + alpha);
}
- nSetAlpha(mNativePtr, alpha);
+
+ if (mState == null) {
+ throw new IllegalStateException("called setAlpha on empty AnimatedImageDrawable");
+ }
+
+ nSetAlpha(mState.mNativePtr, alpha);
invalidateSelf();
}
@Override
public int getAlpha() {
- return nGetAlpha(mNativePtr);
+ if (mState == null) {
+ throw new IllegalStateException("called getAlpha on empty AnimatedImageDrawable");
+ }
+ return nGetAlpha(mState.mNativePtr);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
+ if (mState == null) {
+ throw new IllegalStateException("called setColorFilter on empty AnimatedImageDrawable");
+ }
+
long nativeFilter = colorFilter == null ? 0 : colorFilter.getNativeInstance();
- nSetColorFilter(mNativePtr, nativeFilter);
+ nSetColorFilter(mState.mNativePtr, nativeFilter);
invalidateSelf();
}
@@ -153,39 +288,158 @@
return PixelFormat.TRANSLUCENT;
}
- // TODO: Add a Constant State?
- // @Override
- // public @Nullable ConstantState getConstantState() {}
-
-
- // Animatable overrides
@Override
- public boolean isRunning() {
- return nIsRunning(mNativePtr);
+ public boolean setVisible(boolean visible, boolean restart) {
+ if (!super.setVisible(visible, restart)) {
+ return false;
+ }
+
+ if (!visible) {
+ nMarkInvisible(mState.mNativePtr);
+ }
+
+ return true;
}
+ // Animatable overrides
+ /**
+ * Return whether the animation is currently running.
+ *
+ * <p>When this drawable is created, this will return {@code false}. A client
+ * needs to call {@link #start} to start the animation.</p>
+ */
+ @Override
+ public boolean isRunning() {
+ if (mState == null) {
+ throw new IllegalStateException("called isRunning on empty AnimatedImageDrawable");
+ }
+ return nIsRunning(mState.mNativePtr);
+ }
+
+ /**
+ * Start the animation.
+ *
+ * <p>Does nothing if the animation is already running. If the animation is stopped,
+ * this will reset it.</p>
+ *
+ * <p>If the animation starts, this will call
+ * {@link Animatable2.AnimationCallback#onAnimationStart}.</p>
+ */
@Override
public void start() {
- if (nStart(mNativePtr)) {
+ if (mState == null) {
+ throw new IllegalStateException("called start on empty AnimatedImageDrawable");
+ }
+
+ if (nStart(mState.mNativePtr)) {
+ mStarting = true;
invalidateSelf();
}
}
+ /**
+ * Stop the animation.
+ *
+ * <p>If the animation is stopped, it will continue to display the frame
+ * it was displaying when stopped.</p>
+ */
@Override
public void stop() {
- nStop(mNativePtr);
+ if (mState == null) {
+ throw new IllegalStateException("called stop on empty AnimatedImageDrawable");
+ }
+ nStop(mState.mNativePtr);
}
+ // Animatable2 overrides
+ private ArrayList<Animatable2.AnimationCallback> mAnimationCallbacks = null;
+
+ @Override
+ public void registerAnimationCallback(@NonNull AnimationCallback callback) {
+ if (callback == null) {
+ return;
+ }
+
+ if (mAnimationCallbacks == null) {
+ mAnimationCallbacks = new ArrayList<Animatable2.AnimationCallback>();
+ nSetOnAnimationEndListener(mState.mNativePtr, this);
+ }
+
+ mAnimationCallbacks.add(callback);
+ }
+
+ @Override
+ public boolean unregisterAnimationCallback(@NonNull AnimationCallback callback) {
+ if (callback == null || mAnimationCallbacks == null) {
+ return false;
+ }
+
+ return mAnimationCallbacks.remove(callback);
+ }
+
+ @Override
+ public void clearAnimationCallbacks() {
+ mAnimationCallbacks = null;
+ }
+
+ private void postOnAnimationStart() {
+ if (mAnimationCallbacks == null) {
+ return;
+ }
+
+ getHandler().post(() -> {
+ for (Animatable2.AnimationCallback callback : mAnimationCallbacks) {
+ callback.onAnimationStart(this);
+ }
+ });
+ }
+
+ private void postOnAnimationEnd() {
+ if (mAnimationCallbacks == null) {
+ return;
+ }
+
+ getHandler().post(() -> {
+ for (Animatable2.AnimationCallback callback : mAnimationCallbacks) {
+ callback.onAnimationEnd(this);
+ }
+ });
+ }
+
+ private Handler getHandler() {
+ if (mHandler == null) {
+ mHandler = new Handler(Looper.getMainLooper());
+ }
+ return mHandler;
+ }
+
+
private static native long nCreate(long nativeImageDecoder,
@Nullable ImageDecoder decoder, int width, int height, Rect cropRect)
throws IOException;
+ @FastNative
private static native long nGetNativeFinalizer();
private static native long nDraw(long nativePtr, long canvasNativePtr);
+ @FastNative
private static native void nSetAlpha(long nativePtr, int alpha);
+ @FastNative
private static native int nGetAlpha(long nativePtr);
+ @FastNative
private static native void nSetColorFilter(long nativePtr, long nativeFilter);
+ @FastNative
private static native boolean nIsRunning(long nativePtr);
+ // Return whether the animation started.
+ @FastNative
private static native boolean nStart(long nativePtr);
+ @FastNative
private static native void nStop(long nativePtr);
+ @FastNative
+ private static native void nSetLoopCount(long nativePtr, int loopCount);
+ // Pass the drawable down to native so it can call onAnimationEnd.
+ private static native void nSetOnAnimationEndListener(long nativePtr,
+ @Nullable AnimatedImageDrawable drawable);
+ @FastNative
private static native long nNativeByteSize(long nativePtr);
+ @FastNative
+ private static native void nMarkInvisible(long nativePtr);
}
diff --git a/graphics/java/android/graphics/drawable/DrawableInflater.java b/graphics/java/android/graphics/drawable/DrawableInflater.java
index eea7048..0ee9071 100644
--- a/graphics/java/android/graphics/drawable/DrawableInflater.java
+++ b/graphics/java/android/graphics/drawable/DrawableInflater.java
@@ -185,6 +185,8 @@
return new BitmapDrawable();
case "nine-patch":
return new NinePatchDrawable();
+ case "animated-image":
+ return new AnimatedImageDrawable();
default:
return null;
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index f721ed3..09b3b9b 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -248,7 +248,8 @@
spec.getUserAuthenticationValidityDurationSeconds(),
spec.isUserAuthenticationValidWhileOnBody(),
spec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
+ spec.isUserConfirmationRequired());
} catch (IllegalStateException | IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -289,7 +290,8 @@
spec.getUserAuthenticationValidityDurationSeconds(),
spec.isUserAuthenticationValidWhileOnBody(),
spec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
+ spec.isUserConfirmationRequired());
if (spec.isTrustedUserPresenceRequired()) {
args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index d1eb688..e33e3cd 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -349,7 +349,8 @@
mSpec.getUserAuthenticationValidityDurationSeconds(),
mSpec.isUserAuthenticationValidWhileOnBody(),
mSpec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
+ mSpec.isUserConfirmationRequired());
} catch (IllegalArgumentException | IllegalStateException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -545,7 +546,8 @@
mSpec.getUserAuthenticationValidityDurationSeconds(),
mSpec.isUserAuthenticationValidWhileOnBody(),
mSpec.isInvalidatedByBiometricEnrollment(),
- GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
+ mSpec.isUserConfirmationRequired());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
mSpec.getKeyValidityForOriginationEnd());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
index 9df37f5..7bbc099 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -190,6 +190,8 @@
&& !keymasterSecureUserIds.contains(getGateKeeperSecureUserId());
}
+ boolean userConfirmationRequired = keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
+
return new KeyInfo(entryAlias,
insideSecureHardware,
origin,
@@ -207,7 +209,8 @@
userAuthenticationRequirementEnforcedBySecureHardware,
userAuthenticationValidWhileOnBody,
trustedUserPresenceRequred,
- invalidatedByBiometricEnrollment);
+ invalidatedByBiometricEnrollment,
+ userConfirmationRequired);
}
private static BigInteger getGateKeeperSecureUserId() throws ProviderException {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 440e086..05cc74a 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -502,7 +502,8 @@
spec.getUserAuthenticationValidityDurationSeconds(),
spec.isUserAuthenticationValidWhileOnBody(),
spec.isInvalidatedByBiometricEnrollment(),
- spec.getBoundToSpecificSecureUserId());
+ spec.getBoundToSpecificSecureUserId(),
+ spec.isUserConfirmationRequired());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
spec.getKeyValidityStart());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
@@ -704,7 +705,8 @@
params.getUserAuthenticationValidityDurationSeconds(),
params.isUserAuthenticationValidWhileOnBody(),
params.isInvalidatedByBiometricEnrollment(),
- params.getBoundToSpecificSecureUserId());
+ params.getBoundToSpecificSecureUserId(),
+ params.isUserConfirmationRequired());
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
keymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index a896c72..da23c70 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -264,6 +264,7 @@
private final boolean mUserAuthenticationValidWhileOnBody;
private final boolean mInvalidatedByBiometricEnrollment;
private final boolean mIsStrongBoxBacked;
+ private final boolean mUserConfirmationRequired;
/**
* @hide should be built with Builder
@@ -293,7 +294,8 @@
boolean uniqueIdIncluded,
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
- boolean isStrongBoxBacked) {
+ boolean isStrongBoxBacked,
+ boolean userConfirmationRequired) {
if (TextUtils.isEmpty(keyStoreAlias)) {
throw new IllegalArgumentException("keyStoreAlias must not be empty");
}
@@ -341,6 +343,7 @@
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
mIsStrongBoxBacked = isStrongBoxBacked;
+ mUserConfirmationRequired = userConfirmationRequired;
}
/**
@@ -547,6 +550,26 @@
}
/**
+ * Returns {@code true} if the key is authorized to be used only for messages confirmed by the
+ * user.
+ *
+ * Confirmation is separate from user authentication (see
+ * {@link Builder#setUserAuthenticationRequired(boolean)}). Keys can be created that require
+ * confirmation but not user authentication, or user authentication but not confirmation, or
+ * both. Confirmation verifies that some user with physical possession of the device has
+ * approved a displayed message. User authentication verifies that the correct user is present
+ * and has authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see Builder#setUserConfirmationRequired(boolean)
+ */
+ public boolean isUserConfirmationRequired() {
+ return mUserConfirmationRequired;
+ }
+
+ /**
* Gets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect only if user authentication is required
* (see {@link #isUserAuthenticationRequired()}).
@@ -675,6 +698,7 @@
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
private boolean mIsStrongBoxBacked = false;
+ private boolean mUserConfirmationRequired;
/**
* Creates a new instance of the {@code Builder}.
@@ -1063,6 +1087,29 @@
}
/**
+ * Sets whether this key is authorized to be used only for messages confirmed by the
+ * user.
+ *
+ * Confirmation is separate from user authentication (see
+ * {@link #setUserAuthenticationRequired(boolean)}). Keys can be created that require
+ * confirmation but not user authentication, or user authentication but not confirmation,
+ * or both. Confirmation verifies that some user with physical possession of the device has
+ * approved a displayed message. User authentication verifies that the correct user is
+ * present and has authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see {@link android.security.ConfirmationPrompter ConfirmationPrompter} class for
+ * more details about user confirmations.
+ */
+ @NonNull
+ public Builder setUserConfirmationRequired(boolean required) {
+ mUserConfirmationRequired = required;
+ return this;
+ }
+
+ /**
* Sets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect if the key requires user
* authentication for its use (see {@link #setUserAuthenticationRequired(boolean)}).
@@ -1249,7 +1296,8 @@
mUniqueIdIncluded,
mUserAuthenticationValidWhileOnBody,
mInvalidatedByBiometricEnrollment,
- mIsStrongBoxBacked);
+ mIsStrongBoxBacked,
+ mUserConfirmationRequired);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index 864f62a..0a75cd5 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -82,6 +82,7 @@
private final boolean mUserAuthenticationValidWhileOnBody;
private final boolean mTrustedUserPresenceRequired;
private final boolean mInvalidatedByBiometricEnrollment;
+ private final boolean mUserConfirmationRequired;
/**
* @hide
@@ -103,7 +104,8 @@
boolean userAuthenticationRequirementEnforcedBySecureHardware,
boolean userAuthenticationValidWhileOnBody,
boolean trustedUserPresenceRequired,
- boolean invalidatedByBiometricEnrollment) {
+ boolean invalidatedByBiometricEnrollment,
+ boolean userConfirmationRequired) {
mKeystoreAlias = keystoreKeyAlias;
mInsideSecureHardware = insideSecureHardware;
mOrigin = origin;
@@ -125,6 +127,7 @@
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
mTrustedUserPresenceRequired = trustedUserPresenceRequired;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
+ mUserConfirmationRequired = userConfirmationRequired;
}
/**
@@ -260,6 +263,27 @@
}
/**
+ * Returns {@code true} if the key is authorized to be used only for messages confirmed by the
+ * user.
+ *
+ * Confirmation is separate from user authentication (see
+ * {@link #isUserAuthenticationRequired()}). Keys can be created that require confirmation but
+ * not user authentication, or user authentication but not confirmation, or both. Confirmation
+ * verifies that some user with physical possession of the device has approved a displayed
+ * message. User authentication verifies that the correct user is present and has
+ * authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see KeyGenParameterSpec.Builder#setUserConfirmationRequired(boolean)
+ * @see KeyProtection.Builder#setUserConfirmationRequired(boolean)
+ */
+ public boolean isUserConfirmationRequired() {
+ return mUserConfirmationRequired;
+ }
+
+ /**
* Gets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect only if user authentication is required
* (see {@link #isUserAuthenticationRequired()}).
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index dbacb9c..b5b3281 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -228,6 +228,7 @@
private final boolean mInvalidatedByBiometricEnrollment;
private final long mBoundToSecureUserId;
private final boolean mCriticalToDeviceEncryption;
+ private final boolean mUserConfirmationRequired;
private KeyProtection(
Date keyValidityStart,
@@ -244,7 +245,8 @@
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
long boundToSecureUserId,
- boolean criticalToDeviceEncryption) {
+ boolean criticalToDeviceEncryption,
+ boolean userConfirmationRequired) {
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
@@ -262,6 +264,7 @@
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
mBoundToSecureUserId = boundToSecureUserId;
mCriticalToDeviceEncryption = criticalToDeviceEncryption;
+ mUserConfirmationRequired = userConfirmationRequired;
}
/**
@@ -396,6 +399,26 @@
}
/**
+ * Returns {@code true} if the key is authorized to be used only for messages confirmed by the
+ * user.
+ *
+ * Confirmation is separate from user authentication (see
+ * {@link #isUserAuthenticationRequired()}). Keys can be created that require confirmation but
+ * not user authentication, or user authentication but not confirmation, or both. Confirmation
+ * verifies that some user with physical possession of the device has approved a displayed
+ * message. User authentication verifies that the correct user is present and has
+ * authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see Builder#setUserConfirmationRequired(boolean)
+ */
+ public boolean isUserConfirmationRequired() {
+ return mUserConfirmationRequired;
+ }
+
+ /**
* Gets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect only if user authentication is required
* (see {@link #isUserAuthenticationRequired()}).
@@ -488,6 +511,7 @@
private int mUserAuthenticationValidityDurationSeconds = -1;
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
+ private boolean mUserConfirmationRequired;
private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
private boolean mCriticalToDeviceEncryption = false;
@@ -719,6 +743,29 @@
}
/**
+ * Sets whether this key is authorized to be used only for messages confirmed by the
+ * user.
+ *
+ * Confirmation is separate from user authentication (see
+ * {@link #setUserAuthenticationRequired(boolean)}). Keys can be created that require
+ * confirmation but not user authentication, or user authentication but not confirmation,
+ * or both. Confirmation verifies that some user with physical possession of the device has
+ * approved a displayed message. User authentication verifies that the correct user is
+ * present and has authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see {@link android.security.ConfirmationPrompter ConfirmationPrompter} class for
+ * more details about user confirmations.
+ */
+ @NonNull
+ public Builder setUserConfirmationRequired(boolean required) {
+ mUserConfirmationRequired = required;
+ return this;
+ }
+
+ /**
* Sets the duration of time (seconds) for which this key is authorized to be used after the
* user is successfully authenticated. This has effect if the key requires user
* authentication for its use (see {@link #setUserAuthenticationRequired(boolean)}).
@@ -866,7 +913,8 @@
mUserAuthenticationValidWhileOnBody,
mInvalidatedByBiometricEnrollment,
mBoundToSecureUserId,
- mCriticalToDeviceEncryption);
+ mCriticalToDeviceEncryption,
+ mUserConfirmationRequired);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index 34c8d1f..4e28601 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -16,6 +16,7 @@
package android.security.keystore;
+import android.util.Log;
import android.hardware.fingerprint.FingerprintManager;
import android.security.GateKeeper;
import android.security.KeyStore;
@@ -93,6 +94,8 @@
* overriding the default logic in this method where the key is bound to either the root
* SID of the current user, or the fingerprint SID if explicit fingerprint authorization
* is requested.
+ * @param userConfirmationRequired whether user confirmation is required to authorize the use
+ * of the key.
* @throws IllegalStateException if user authentication is required but the system is in a wrong
* state (e.g., secure lock screen not set up) for generating or importing keys that
* require user authentication.
@@ -102,7 +105,12 @@
int userAuthenticationValidityDurationSeconds,
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
- long boundToSpecificSecureUserId) {
+ long boundToSpecificSecureUserId,
+ boolean userConfirmationRequired) {
+ if (userConfirmationRequired) {
+ args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
+ }
+
if (!userAuthenticationRequired) {
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
return;
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 70d5216..251b2e7 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -145,7 +145,6 @@
"tests/TypeWrappers_test.cpp",
"tests/ZipUtils_test.cpp",
],
- static_libs: ["libgmock"],
target: {
android: {
srcs: [
@@ -172,7 +171,6 @@
// Actual benchmarks.
"tests/AssetManager2_bench.cpp",
- "tests/AttributeResolution_bench.cpp",
"tests/SparseEntry_bench.cpp",
"tests/Theme_bench.cpp",
],
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 0485625..a5698af 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -73,6 +73,7 @@
const char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
+const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
const char* AssetManager::TARGET_PACKAGE_NAME = "android";
const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index a558ff7..415d3e3 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -36,31 +36,6 @@
namespace android {
-struct FindEntryResult {
- // A pointer to the resource table entry for this resource.
- // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
- // a ResTable_map_entry and processed as a bag/map.
- const ResTable_entry* entry;
-
- // The configuration for which the resulting entry was defined. This is already swapped to host
- // endianness.
- ResTable_config config;
-
- // The bitmask of configuration axis with which the resource value varies.
- uint32_t type_flags;
-
- // The dynamic package ID map for the package from which this resource came from.
- const DynamicRefTable* dynamic_ref_table;
-
- // The string pool reference to the type's name. This uses a different string pool than
- // the global string pool, but this is hidden from the caller.
- StringPoolRef type_string_ref;
-
- // The string pool reference to the entry's name. This uses a different string pool than
- // the global string pool, but this is hidden from the caller.
- StringPoolRef entry_string_ref;
-};
-
AssetManager2::AssetManager2() {
memset(&configuration_, 0, sizeof(configuration_));
}
@@ -69,7 +44,6 @@
bool invalidate_caches) {
apk_assets_ = apk_assets;
BuildDynamicRefTable();
- RebuildFilterList();
if (invalidate_caches) {
InvalidateCaches(static_cast<uint32_t>(-1));
}
@@ -105,7 +79,7 @@
PackageGroup* package_group = &package_groups_[idx];
// Add the package and to the set of packages with the same ID.
- package_group->packages_.push_back(ConfiguredPackage{package.get(), {}});
+ package_group->packages_.push_back(package.get());
package_group->cookies_.push_back(static_cast<ApkAssetsCookie>(i));
// Add the package name -> build time ID mappings.
@@ -120,7 +94,7 @@
// Now assign the runtime IDs so that we have a build-time to runtime ID map.
const auto package_groups_end = package_groups_.end();
for (auto iter = package_groups_.begin(); iter != package_groups_end; ++iter) {
- const std::string& package_name = iter->packages_[0].loaded_package_->GetPackageName();
+ const std::string& package_name = iter->packages_[0]->GetPackageName();
for (auto iter2 = package_groups_.begin(); iter2 != package_groups_end; ++iter2) {
iter2->dynamic_ref_table.addMapping(String16(package_name.c_str(), package_name.size()),
iter->dynamic_ref_table.mAssignedPackageId);
@@ -134,20 +108,17 @@
std::string list;
for (size_t i = 0; i < package_ids_.size(); i++) {
if (package_ids_[i] != 0xff) {
- base::StringAppendF(&list, "%02x -> %d, ", (int)i, package_ids_[i]);
+ base::StringAppendF(&list, "%02x -> %d, ", (int) i, package_ids_[i]);
}
}
LOG(INFO) << "Package ID map: " << list;
- for (const auto& package_group : package_groups_) {
- list = "";
- for (const auto& package : package_group.packages_) {
- base::StringAppendF(&list, "%s(%02x), ", package.loaded_package_->GetPackageName().c_str(),
- package.loaded_package_->GetPackageId());
- }
- LOG(INFO) << base::StringPrintf("PG (%02x): ",
- package_group.dynamic_ref_table.mAssignedPackageId)
- << list;
+ for (const auto& package_group: package_groups_) {
+ list = "";
+ for (const auto& package : package_group.packages_) {
+ base::StringAppendF(&list, "%s(%02x), ", package->GetPackageName().c_str(), package->GetPackageId());
+ }
+ LOG(INFO) << base::StringPrintf("PG (%02x): ", package_group.dynamic_ref_table.mAssignedPackageId) << list;
}
}
@@ -186,54 +157,52 @@
configuration_ = configuration;
if (diff) {
- RebuildFilterList();
InvalidateCaches(static_cast<uint32_t>(diff));
}
}
std::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_system,
- bool exclude_mipmap) const {
+ bool exclude_mipmap) {
ATRACE_CALL();
std::set<ResTable_config> configurations;
for (const PackageGroup& package_group : package_groups_) {
- for (const ConfiguredPackage& package : package_group.packages_) {
- if (exclude_system && package.loaded_package_->IsSystem()) {
+ for (const LoadedPackage* package : package_group.packages_) {
+ if (exclude_system && package->IsSystem()) {
continue;
}
- package.loaded_package_->CollectConfigurations(exclude_mipmap, &configurations);
+ package->CollectConfigurations(exclude_mipmap, &configurations);
}
}
return configurations;
}
std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system,
- bool merge_equivalent_languages) const {
+ bool merge_equivalent_languages) {
ATRACE_CALL();
std::set<std::string> locales;
for (const PackageGroup& package_group : package_groups_) {
- for (const ConfiguredPackage& package : package_group.packages_) {
- if (exclude_system && package.loaded_package_->IsSystem()) {
+ for (const LoadedPackage* package : package_group.packages_) {
+ if (exclude_system && package->IsSystem()) {
continue;
}
- package.loaded_package_->CollectLocales(merge_equivalent_languages, &locales);
+ package->CollectLocales(merge_equivalent_languages, &locales);
}
}
return locales;
}
-std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename,
- Asset::AccessMode mode) const {
+std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, Asset::AccessMode mode) {
const std::string new_path = "assets/" + filename;
return OpenNonAsset(new_path, mode);
}
std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, ApkAssetsCookie cookie,
- Asset::AccessMode mode) const {
+ Asset::AccessMode mode) {
const std::string new_path = "assets/" + filename;
return OpenNonAsset(new_path, cookie, mode);
}
-std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) const {
+std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) {
ATRACE_CALL();
std::string full_path = "assets/" + dirname;
@@ -267,7 +236,7 @@
// is inconsistent for split APKs.
std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
Asset::AccessMode mode,
- ApkAssetsCookie* out_cookie) const {
+ ApkAssetsCookie* out_cookie) {
ATRACE_CALL();
for (int32_t i = apk_assets_.size() - 1; i >= 0; i--) {
std::unique_ptr<Asset> asset = apk_assets_[i]->Open(filename, mode);
@@ -286,8 +255,7 @@
}
std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
- ApkAssetsCookie cookie,
- Asset::AccessMode mode) const {
+ ApkAssetsCookie cookie, Asset::AccessMode mode) {
ATRACE_CALL();
if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) {
return {};
@@ -296,13 +264,14 @@
}
ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_override,
- bool /*stop_at_first_match*/,
- FindEntryResult* out_entry) const {
+ bool stop_at_first_match, FindEntryResult* out_entry) {
+ ATRACE_CALL();
+
// Might use this if density_override != 0.
ResTable_config density_override_config;
// Select our configuration or generate a density override configuration.
- const ResTable_config* desired_config = &configuration_;
+ ResTable_config* desired_config = &configuration_;
if (density_override != 0 && density_override != configuration_.density) {
density_override_config = configuration_;
density_override_config.density = density_override;
@@ -316,135 +285,53 @@
const uint32_t package_id = get_package_id(resid);
const uint8_t type_idx = get_type_id(resid) - 1;
- const uint16_t entry_idx = get_entry_id(resid);
+ const uint16_t entry_id = get_entry_id(resid);
- const uint8_t package_idx = package_ids_[package_id];
- if (package_idx == 0xff) {
+ const uint8_t idx = package_ids_[package_id];
+ if (idx == 0xff) {
LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.", package_id, resid);
return kInvalidCookie;
}
- const PackageGroup& package_group = package_groups_[package_idx];
- const size_t package_count = package_group.packages_.size();
-
+ FindEntryResult best_entry;
ApkAssetsCookie best_cookie = kInvalidCookie;
- const LoadedPackage* best_package = nullptr;
- const ResTable_type* best_type = nullptr;
- const ResTable_config* best_config = nullptr;
- ResTable_config best_config_copy;
- uint32_t best_offset = 0u;
- uint32_t type_flags = 0u;
+ uint32_t cumulated_flags = 0u;
- // If desired_config is the same as the set configuration, then we can use our filtered list
- // and we don't need to match the configurations, since they already matched.
- const bool use_fast_path = desired_config == &configuration_;
-
- for (size_t pi = 0; pi < package_count; pi++) {
- const ConfiguredPackage& loaded_package_impl = package_group.packages_[pi];
- const LoadedPackage* loaded_package = loaded_package_impl.loaded_package_;
- ApkAssetsCookie cookie = package_group.cookies_[pi];
-
- // If the type IDs are offset in this package, we need to take that into account when searching
- // for a type.
- const TypeSpec* type_spec = loaded_package->GetTypeSpecByTypeIndex(type_idx);
- if (UNLIKELY(type_spec == nullptr)) {
+ const PackageGroup& package_group = package_groups_[idx];
+ const size_t package_count = package_group.packages_.size();
+ FindEntryResult current_entry;
+ for (size_t i = 0; i < package_count; i++) {
+ const LoadedPackage* loaded_package = package_group.packages_[i];
+ if (!loaded_package->FindEntry(type_idx, entry_id, *desired_config, ¤t_entry)) {
continue;
}
- uint16_t local_entry_idx = entry_idx;
+ cumulated_flags |= current_entry.type_flags;
- // If there is an IDMAP supplied with this package, translate the entry ID.
- if (type_spec->idmap_entries != nullptr) {
- if (!LoadedIdmap::Lookup(type_spec->idmap_entries, local_entry_idx, &local_entry_idx)) {
- // There is no mapping, so the resource is not meant to be in this overlay package.
- continue;
- }
- }
-
- type_flags |= type_spec->GetFlagsForEntryIndex(local_entry_idx);
-
- // If the package is an overlay, then even configurations that are the same MUST be chosen.
- const bool package_is_overlay = loaded_package->IsOverlay();
-
- const FilteredConfigGroup& filtered_group = loaded_package_impl.filtered_configs_[type_idx];
- if (use_fast_path) {
- const std::vector<ResTable_config>& candidate_configs = filtered_group.configurations;
- const size_t type_count = candidate_configs.size();
- for (uint32_t i = 0; i < type_count; i++) {
- const ResTable_config& this_config = candidate_configs[i];
-
- // We can skip calling ResTable_config::match() because we know that all candidate
- // configurations that do NOT match have been filtered-out.
- if ((best_config == nullptr || this_config.isBetterThan(*best_config, desired_config)) ||
- (package_is_overlay && this_config.compare(*best_config) == 0)) {
- // The configuration matches and is better than the previous selection.
- // Find the entry value if it exists for this configuration.
- const ResTable_type* type_chunk = filtered_group.types[i];
- const uint32_t offset = LoadedPackage::GetEntryOffset(type_chunk, local_entry_idx);
- if (offset == ResTable_type::NO_ENTRY) {
- continue;
- }
-
- best_cookie = cookie;
- best_package = loaded_package;
- best_type = type_chunk;
- best_config = &this_config;
- best_offset = offset;
- }
- }
- } else {
- // This is the slower path, which doesn't use the filtered list of configurations.
- // Here we must read the ResTable_config from the mmapped APK, convert it to host endianness
- // and fill in any new fields that did not exist when the APK was compiled.
- // Furthermore when selecting configurations we can't just record the pointer to the
- // ResTable_config, we must copy it.
- const auto iter_end = type_spec->types + type_spec->type_count;
- for (auto iter = type_spec->types; iter != iter_end; ++iter) {
- ResTable_config this_config;
- this_config.copyFromDtoH((*iter)->config);
-
- if (this_config.match(*desired_config)) {
- if ((best_config == nullptr || this_config.isBetterThan(*best_config, desired_config)) ||
- (package_is_overlay && this_config.compare(*best_config) == 0)) {
- // The configuration matches and is better than the previous selection.
- // Find the entry value if it exists for this configuration.
- const uint32_t offset = LoadedPackage::GetEntryOffset(*iter, local_entry_idx);
- if (offset == ResTable_type::NO_ENTRY) {
- continue;
- }
-
- best_cookie = cookie;
- best_package = loaded_package;
- best_type = *iter;
- best_config_copy = this_config;
- best_config = &best_config_copy;
- best_offset = offset;
- }
- }
+ const ResTable_config* current_config = current_entry.config;
+ const ResTable_config* best_config = best_entry.config;
+ if (best_cookie == kInvalidCookie ||
+ current_config->isBetterThan(*best_config, desired_config) ||
+ (loaded_package->IsOverlay() && current_config->compare(*best_config) == 0)) {
+ best_entry = current_entry;
+ best_cookie = package_group.cookies_[i];
+ if (stop_at_first_match) {
+ break;
}
}
}
- if (UNLIKELY(best_cookie == kInvalidCookie)) {
+ if (best_cookie == kInvalidCookie) {
return kInvalidCookie;
}
- const ResTable_entry* best_entry = LoadedPackage::GetEntryFromOffset(best_type, best_offset);
- if (UNLIKELY(best_entry == nullptr)) {
- return kInvalidCookie;
- }
-
- out_entry->entry = best_entry;
- out_entry->config = *best_config;
- out_entry->type_flags = type_flags;
- out_entry->type_string_ref = StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1);
- out_entry->entry_string_ref =
- StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
+ *out_entry = best_entry;
out_entry->dynamic_ref_table = &package_group.dynamic_ref_table;
+ out_entry->type_flags = cumulated_flags;
return best_cookie;
}
-bool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) const {
+bool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) {
ATRACE_CALL();
FindEntryResult entry;
@@ -454,8 +341,7 @@
return false;
}
- const LoadedPackage* package =
- apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
+ const LoadedPackage* package = apk_assets_[cookie]->GetLoadedArsc()->GetPackageForId(resid);
if (package == nullptr) {
return false;
}
@@ -483,7 +369,7 @@
return true;
}
-bool AssetManager2::GetResourceFlags(uint32_t resid, uint32_t* out_flags) const {
+bool AssetManager2::GetResourceFlags(uint32_t resid, uint32_t* out_flags) {
FindEntryResult entry;
ApkAssetsCookie cookie =
FindEntry(resid, 0u /* density_override */, false /* stop_at_first_match */, &entry);
@@ -497,7 +383,7 @@
ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag,
uint16_t density_override, Res_value* out_value,
ResTable_config* out_selected_config,
- uint32_t* out_flags) const {
+ uint32_t* out_flags) {
ATRACE_CALL();
FindEntryResult entry;
@@ -516,7 +402,7 @@
// Create a reference since we can't represent this complex type as a Res_value.
out_value->dataType = Res_value::TYPE_REFERENCE;
out_value->data = resid;
- *out_selected_config = entry.config;
+ *out_selected_config = *entry.config;
*out_flags = entry.type_flags;
return cookie;
}
@@ -528,7 +414,7 @@
// Convert the package ID to the runtime assigned package ID.
entry.dynamic_ref_table->lookupResourceValue(out_value);
- *out_selected_config = entry.config;
+ *out_selected_config = *entry.config;
*out_flags = entry.type_flags;
return cookie;
}
@@ -536,14 +422,16 @@
ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
ResTable_config* in_out_selected_config,
uint32_t* in_out_flags,
- uint32_t* out_last_reference) const {
+ uint32_t* out_last_reference) {
ATRACE_CALL();
constexpr const int kMaxIterations = 20;
for (size_t iteration = 0u; in_out_value->dataType == Res_value::TYPE_REFERENCE &&
in_out_value->data != 0u && iteration < kMaxIterations;
iteration++) {
- *out_last_reference = in_out_value->data;
+ if (out_last_reference != nullptr) {
+ *out_last_reference = in_out_value->data;
+ }
uint32_t new_flags = 0u;
cookie = GetResource(in_out_value->data, true /*may_be_bag*/, 0u /*density_override*/,
in_out_value, in_out_selected_config, &new_flags);
@@ -604,8 +492,7 @@
// Attributes, arrays, etc don't have a resource id as the name. They specify
// other data, which would be wrong to change via a lookup.
if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
- LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key,
- resid);
+ LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
return nullptr;
}
}
@@ -637,8 +524,7 @@
const ResolvedBag* parent_bag = GetBag(parent_resid);
if (parent_bag == nullptr) {
// Failed to get the parent that should exist.
- LOG(ERROR) << base::StringPrintf("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid,
- resid);
+ LOG(ERROR) << base::StringPrintf("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid, resid);
return nullptr;
}
@@ -657,8 +543,7 @@
uint32_t child_key = dtohl(map_entry->name.ident);
if (!is_internal_resid(child_key)) {
if (entry.dynamic_ref_table->lookupResourceId(&child_key) != NO_ERROR) {
- LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", child_key,
- resid);
+ LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", child_key, resid);
return nullptr;
}
}
@@ -697,8 +582,7 @@
uint32_t new_key = dtohl(map_entry->name.ident);
if (!is_internal_resid(new_key)) {
if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
- LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key,
- resid);
+ LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
return nullptr;
}
}
@@ -754,7 +638,7 @@
uint32_t AssetManager2::GetResourceId(const std::string& resource_name,
const std::string& fallback_type,
- const std::string& fallback_package) const {
+ const std::string& fallback_package) {
StringPiece package_name, type, entry;
if (!ExtractResourceName(resource_name, &package_name, &type, &entry)) {
return 0u;
@@ -786,8 +670,7 @@
const static std::u16string kAttrPrivate16 = u"^attr-private";
for (const PackageGroup& package_group : package_groups_) {
- for (const ConfiguredPackage& package_impl : package_group.packages_) {
- const LoadedPackage* package = package_impl.loaded_package_;
+ for (const LoadedPackage* package : package_group.packages_) {
if (package_name != package->GetPackageName()) {
// All packages in the same group are expected to have the same package name.
break;
@@ -809,32 +692,6 @@
return 0u;
}
-void AssetManager2::RebuildFilterList() {
- for (PackageGroup& group : package_groups_) {
- for (ConfiguredPackage& impl : group.packages_) {
- // Destroy it.
- impl.filtered_configs_.~ByteBucketArray();
-
- // Re-create it.
- new (&impl.filtered_configs_) ByteBucketArray<FilteredConfigGroup>();
-
- // Create the filters here.
- impl.loaded_package_->ForEachTypeSpec([&](const TypeSpec* spec, uint8_t type_index) {
- FilteredConfigGroup& group = impl.filtered_configs_.editItemAt(type_index);
- const auto iter_end = spec->types + spec->type_count;
- for (auto iter = spec->types; iter != iter_end; ++iter) {
- ResTable_config this_config;
- this_config.copyFromDtoH((*iter)->config);
- if (this_config.match(configuration_)) {
- group.configurations.push_back(this_config);
- group.types.push_back(*iter);
- }
- }
- });
- }
- }
-}
-
void AssetManager2::InvalidateCaches(uint32_t diff) {
if (diff == 0xffffffffu) {
// Everything must go.
@@ -1015,7 +872,7 @@
ApkAssetsCookie Theme::ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value,
ResTable_config* in_out_selected_config,
uint32_t* in_out_type_spec_flags,
- uint32_t* out_last_ref) const {
+ uint32_t* out_last_ref) {
if (in_out_value->dataType == Res_value::TYPE_ATTRIBUTE) {
uint32_t new_flags;
cookie = GetAttribute(in_out_value->data, in_out_value, &new_flags);
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index f912af4..60e3845 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -20,18 +20,13 @@
#include <log/log.h>
-#include "androidfw/AssetManager2.h"
#include "androidfw/AttributeFinder.h"
+#include "androidfw/ResourceTypes.h"
constexpr bool kDebugStyles = false;
namespace android {
-// Java asset cookies have 0 as an invalid cookie, but TypedArray expects < 0.
-static uint32_t ApkAssetsCookieToJavaCookie(ApkAssetsCookie cookie) {
- return cookie != kInvalidCookie ? static_cast<uint32_t>(cookie + 1) : static_cast<uint32_t>(-1);
-}
-
class XmlAttributeFinder
: public BackTrackingAttributeFinder<XmlAttributeFinder, size_t> {
public:
@@ -49,53 +44,58 @@
};
class BagAttributeFinder
- : public BackTrackingAttributeFinder<BagAttributeFinder, const ResolvedBag::Entry*> {
+ : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
public:
- BagAttributeFinder(const ResolvedBag* bag)
- : BackTrackingAttributeFinder(bag != nullptr ? bag->entries : nullptr,
- bag != nullptr ? bag->entries + bag->entry_count : nullptr) {
- }
+ BagAttributeFinder(const ResTable::bag_entry* start,
+ const ResTable::bag_entry* end)
+ : BackTrackingAttributeFinder(start, end) {}
- inline uint32_t GetAttribute(const ResolvedBag::Entry* entry) const {
- return entry->key;
+ inline uint32_t GetAttribute(const ResTable::bag_entry* entry) const {
+ return entry->map.name.ident;
}
};
-bool ResolveAttrs(Theme* theme, uint32_t def_style_attr, uint32_t def_style_res,
- uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
- size_t attrs_length, uint32_t* out_values, uint32_t* out_indices) {
+bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
+ uint32_t def_style_res, uint32_t* src_values,
+ size_t src_values_length, uint32_t* attrs,
+ size_t attrs_length, uint32_t* out_values,
+ uint32_t* out_indices) {
if (kDebugStyles) {
ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme,
def_style_attr, def_style_res);
}
- AssetManager2* assetmanager = theme->GetAssetManager();
+ const ResTable& res = theme->getResTable();
ResTable_config config;
Res_value value;
int indices_idx = 0;
// Load default style from attribute, if specified...
- uint32_t def_style_flags = 0u;
+ uint32_t def_style_bag_type_set_flags = 0;
if (def_style_attr != 0) {
Res_value value;
- if (theme->GetAttribute(def_style_attr, &value, &def_style_flags) != kInvalidCookie) {
+ if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) {
if (value.dataType == Res_value::TYPE_REFERENCE) {
def_style_res = value.data;
}
}
}
- // Retrieve the default style bag, if requested.
- const ResolvedBag* default_style_bag = nullptr;
- if (def_style_res != 0) {
- default_style_bag = assetmanager->GetBag(def_style_res);
- if (default_style_bag != nullptr) {
- def_style_flags |= default_style_bag->type_spec_flags;
- }
- }
+ // Now lock down the resource object and start pulling stuff from it.
+ res.lock();
- BagAttributeFinder def_style_attr_finder(default_style_bag);
+ // Retrieve the default style bag, if requested.
+ const ResTable::bag_entry* def_style_start = nullptr;
+ uint32_t def_style_type_set_flags = 0;
+ ssize_t bag_off = def_style_res != 0
+ ? res.getBagLocked(def_style_res, &def_style_start,
+ &def_style_type_set_flags)
+ : -1;
+ def_style_type_set_flags |= def_style_bag_type_set_flags;
+ const ResTable::bag_entry* const def_style_end =
+ def_style_start + (bag_off >= 0 ? bag_off : 0);
+ BagAttributeFinder def_style_attr_finder(def_style_start, def_style_end);
// Now iterate through all of the attributes that the client has requested,
// filling in each with whatever data we can find.
@@ -106,7 +106,7 @@
ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident);
}
- ApkAssetsCookie cookie = kInvalidCookie;
+ ssize_t block = -1;
uint32_t type_set_flags = 0;
value.dataType = Res_value::TYPE_NULL;
@@ -122,14 +122,15 @@
value.dataType = Res_value::TYPE_ATTRIBUTE;
value.data = src_values[ii];
if (kDebugStyles) {
- ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
} else {
- const ResolvedBag::Entry* const entry = def_style_attr_finder.Find(cur_ident);
- if (entry != def_style_attr_finder.end()) {
- cookie = entry->cookie;
- type_set_flags = def_style_flags;
- value = entry->value;
+ const ResTable::bag_entry* const def_style_entry = def_style_attr_finder.Find(cur_ident);
+ if (def_style_entry != def_style_end) {
+ block = def_style_entry->stringBlock;
+ type_set_flags = def_style_type_set_flags;
+ value = def_style_entry->map.value;
if (kDebugStyles) {
ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
}
@@ -139,26 +140,22 @@
uint32_t resid = 0;
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
- ApkAssetsCookie new_cookie =
- theme->ResolveAttributeReference(cookie, &value, &config, &type_set_flags, &resid);
- if (new_cookie != kInvalidCookie) {
- cookie = new_cookie;
- }
+ ssize_t new_block =
+ theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
+ if (new_block >= 0) block = new_block;
if (kDebugStyles) {
ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
}
} else if (value.data != Res_value::DATA_NULL_EMPTY) {
- // If we still don't have a value for this attribute, try to find it in the theme!
- ApkAssetsCookie new_cookie = theme->GetAttribute(cur_ident, &value, &type_set_flags);
- if (new_cookie != kInvalidCookie) {
+ // If we still don't have a value for this attribute, try to find
+ // it in the theme!
+ ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
+ if (new_block >= 0) {
if (kDebugStyles) {
ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
}
- new_cookie =
- assetmanager->ResolveReference(new_cookie, &value, &config, &type_set_flags, &resid);
- if (new_cookie != kInvalidCookie) {
- cookie = new_cookie;
- }
+ new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
+ if (new_block >= 0) block = new_block;
if (kDebugStyles) {
ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
}
@@ -172,7 +169,7 @@
}
value.dataType = Res_value::TYPE_NULL;
value.data = Res_value::DATA_NULL_UNDEFINED;
- cookie = kInvalidCookie;
+ block = -1;
}
if (kDebugStyles) {
@@ -182,7 +179,9 @@
// Write the final value back to Java.
out_values[STYLE_TYPE] = value.dataType;
out_values[STYLE_DATA] = value.data;
- out_values[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
+ out_values[STYLE_ASSET_COOKIE] =
+ block != -1 ? static_cast<uint32_t>(res.getTableCookie(block))
+ : static_cast<uint32_t>(-1);
out_values[STYLE_RESOURCE_ID] = resid;
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
@@ -196,80 +195,90 @@
out_values += STYLE_NUM_ENTRIES;
}
+ res.unlock();
+
if (out_indices != nullptr) {
out_indices[0] = indices_idx;
}
return true;
}
-void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
- uint32_t def_style_resid, const uint32_t* attrs, size_t attrs_length,
+void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
+ uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
uint32_t* out_values, uint32_t* out_indices) {
if (kDebugStyles) {
- ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p", theme,
- def_style_attr, def_style_resid, xml_parser);
+ ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p",
+ theme, def_style_attr, def_style_res, xml_parser);
}
- AssetManager2* assetmanager = theme->GetAssetManager();
+ const ResTable& res = theme->getResTable();
ResTable_config config;
Res_value value;
int indices_idx = 0;
// Load default style from attribute, if specified...
- uint32_t def_style_flags = 0u;
+ uint32_t def_style_bag_type_set_flags = 0;
if (def_style_attr != 0) {
Res_value value;
- if (theme->GetAttribute(def_style_attr, &value, &def_style_flags) != kInvalidCookie) {
+ if (theme->getAttribute(def_style_attr, &value,
+ &def_style_bag_type_set_flags) >= 0) {
if (value.dataType == Res_value::TYPE_REFERENCE) {
- def_style_resid = value.data;
+ def_style_res = value.data;
}
}
}
- // Retrieve the style resource ID associated with the current XML tag's style attribute.
- uint32_t style_resid = 0u;
- uint32_t style_flags = 0u;
+ // Retrieve the style class associated with the current XML tag.
+ int style = 0;
+ uint32_t style_bag_type_set_flags = 0;
if (xml_parser != nullptr) {
ssize_t idx = xml_parser->indexOfStyle();
if (idx >= 0 && xml_parser->getAttributeValue(idx, &value) >= 0) {
if (value.dataType == value.TYPE_ATTRIBUTE) {
- // Resolve the attribute with out theme.
- if (theme->GetAttribute(value.data, &value, &style_flags) == kInvalidCookie) {
+ if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) < 0) {
value.dataType = Res_value::TYPE_NULL;
}
}
-
if (value.dataType == value.TYPE_REFERENCE) {
- style_resid = value.data;
+ style = value.data;
}
}
}
- // Retrieve the default style bag, if requested.
- const ResolvedBag* default_style_bag = nullptr;
- if (def_style_resid != 0) {
- default_style_bag = assetmanager->GetBag(def_style_resid);
- if (default_style_bag != nullptr) {
- def_style_flags |= default_style_bag->type_spec_flags;
- }
- }
+ // Now lock down the resource object and start pulling stuff from it.
+ res.lock();
- BagAttributeFinder def_style_attr_finder(default_style_bag);
+ // Retrieve the default style bag, if requested.
+ const ResTable::bag_entry* def_style_attr_start = nullptr;
+ uint32_t def_style_type_set_flags = 0;
+ ssize_t bag_off = def_style_res != 0
+ ? res.getBagLocked(def_style_res, &def_style_attr_start,
+ &def_style_type_set_flags)
+ : -1;
+ def_style_type_set_flags |= def_style_bag_type_set_flags;
+ const ResTable::bag_entry* const def_style_attr_end =
+ def_style_attr_start + (bag_off >= 0 ? bag_off : 0);
+ BagAttributeFinder def_style_attr_finder(def_style_attr_start,
+ def_style_attr_end);
// Retrieve the style class bag, if requested.
- const ResolvedBag* xml_style_bag = nullptr;
- if (style_resid != 0) {
- xml_style_bag = assetmanager->GetBag(style_resid);
- if (xml_style_bag != nullptr) {
- style_flags |= xml_style_bag->type_spec_flags;
- }
- }
-
- BagAttributeFinder xml_style_attr_finder(xml_style_bag);
+ const ResTable::bag_entry* style_attr_start = nullptr;
+ uint32_t style_type_set_flags = 0;
+ bag_off =
+ style != 0
+ ? res.getBagLocked(style, &style_attr_start, &style_type_set_flags)
+ : -1;
+ style_type_set_flags |= style_bag_type_set_flags;
+ const ResTable::bag_entry* const style_attr_end =
+ style_attr_start + (bag_off >= 0 ? bag_off : 0);
+ BagAttributeFinder style_attr_finder(style_attr_start, style_attr_end);
// Retrieve the XML attributes, if requested.
+ static const ssize_t kXmlBlock = 0x10000000;
XmlAttributeFinder xml_attr_finder(xml_parser);
+ const size_t xml_attr_end =
+ xml_parser != nullptr ? xml_parser->getAttributeCount() : 0;
// Now iterate through all of the attributes that the client has requested,
// filling in each with whatever data we can find.
@@ -280,8 +289,8 @@
ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident);
}
- ApkAssetsCookie cookie = kInvalidCookie;
- uint32_t type_set_flags = 0u;
+ ssize_t block = kXmlBlock;
+ uint32_t type_set_flags = 0;
value.dataType = Res_value::TYPE_NULL;
value.data = Res_value::DATA_NULL_UNDEFINED;
@@ -293,7 +302,7 @@
// Walk through the xml attributes looking for the requested attribute.
const size_t xml_attr_idx = xml_attr_finder.Find(cur_ident);
- if (xml_attr_idx != xml_attr_finder.end()) {
+ if (xml_attr_idx != xml_attr_end) {
// We found the attribute we were looking for.
xml_parser->getAttributeValue(xml_attr_idx, &value);
if (kDebugStyles) {
@@ -303,12 +312,12 @@
if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
// Walk through the style class values looking for the requested attribute.
- const ResolvedBag::Entry* entry = xml_style_attr_finder.Find(cur_ident);
- if (entry != xml_style_attr_finder.end()) {
+ const ResTable::bag_entry* const style_attr_entry = style_attr_finder.Find(cur_ident);
+ if (style_attr_entry != style_attr_end) {
// We found the attribute we were looking for.
- cookie = entry->cookie;
- type_set_flags = style_flags;
- value = entry->value;
+ block = style_attr_entry->stringBlock;
+ type_set_flags = style_type_set_flags;
+ value = style_attr_entry->map.value;
if (kDebugStyles) {
ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
}
@@ -317,25 +326,25 @@
if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
// Walk through the default style values looking for the requested attribute.
- const ResolvedBag::Entry* entry = def_style_attr_finder.Find(cur_ident);
- if (entry != def_style_attr_finder.end()) {
+ const ResTable::bag_entry* const def_style_attr_entry = def_style_attr_finder.Find(cur_ident);
+ if (def_style_attr_entry != def_style_attr_end) {
// We found the attribute we were looking for.
- cookie = entry->cookie;
- type_set_flags = def_style_flags;
- value = entry->value;
+ block = def_style_attr_entry->stringBlock;
+ type_set_flags = style_type_set_flags;
+ value = def_style_attr_entry->map.value;
if (kDebugStyles) {
ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
}
}
}
- uint32_t resid = 0u;
+ uint32_t resid = 0;
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
- ApkAssetsCookie new_cookie =
- theme->ResolveAttributeReference(cookie, &value, &config, &type_set_flags, &resid);
- if (new_cookie != kInvalidCookie) {
- cookie = new_cookie;
+ ssize_t new_block =
+ theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
+ if (new_block >= 0) {
+ block = new_block;
}
if (kDebugStyles) {
@@ -343,15 +352,14 @@
}
} else if (value.data != Res_value::DATA_NULL_EMPTY) {
// If we still don't have a value for this attribute, try to find it in the theme!
- ApkAssetsCookie new_cookie = theme->GetAttribute(cur_ident, &value, &type_set_flags);
- if (new_cookie != kInvalidCookie) {
+ ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
+ if (new_block >= 0) {
if (kDebugStyles) {
ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
}
- new_cookie =
- assetmanager->ResolveReference(new_cookie, &value, &config, &type_set_flags, &resid);
- if (new_cookie != kInvalidCookie) {
- cookie = new_cookie;
+ new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
+ if (new_block >= 0) {
+ block = new_block;
}
if (kDebugStyles) {
@@ -367,7 +375,7 @@
}
value.dataType = Res_value::TYPE_NULL;
value.data = Res_value::DATA_NULL_UNDEFINED;
- cookie = kInvalidCookie;
+ block = kXmlBlock;
}
if (kDebugStyles) {
@@ -377,7 +385,9 @@
// Write the final value back to Java.
out_values[STYLE_TYPE] = value.dataType;
out_values[STYLE_DATA] = value.data;
- out_values[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
+ out_values[STYLE_ASSET_COOKIE] =
+ block != kXmlBlock ? static_cast<uint32_t>(res.getTableCookie(block))
+ : static_cast<uint32_t>(-1);
out_values[STYLE_RESOURCE_ID] = resid;
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
@@ -392,28 +402,36 @@
out_values += STYLE_NUM_ENTRIES;
}
+ res.unlock();
+
// out_indices must NOT be nullptr.
out_indices[0] = indices_idx;
}
-bool RetrieveAttributes(AssetManager2* assetmanager, ResXMLParser* xml_parser, uint32_t* attrs,
- size_t attrs_length, uint32_t* out_values, uint32_t* out_indices) {
+bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser,
+ uint32_t* attrs, size_t attrs_length,
+ uint32_t* out_values, uint32_t* out_indices) {
ResTable_config config;
Res_value value;
int indices_idx = 0;
+ // Now lock down the resource object and start pulling stuff from it.
+ res->lock();
+
// Retrieve the XML attributes, if requested.
const size_t xml_attr_count = xml_parser->getAttributeCount();
size_t ix = 0;
uint32_t cur_xml_attr = xml_parser->getAttributeNameResID(ix);
+ static const ssize_t kXmlBlock = 0x10000000;
+
// Now iterate through all of the attributes that the client has requested,
// filling in each with whatever data we can find.
for (size_t ii = 0; ii < attrs_length; ii++) {
const uint32_t cur_ident = attrs[ii];
- ApkAssetsCookie cookie = kInvalidCookie;
- uint32_t type_set_flags = 0u;
+ ssize_t block = kXmlBlock;
+ uint32_t type_set_flags = 0;
value.dataType = Res_value::TYPE_NULL;
value.data = Res_value::DATA_NULL_UNDEFINED;
@@ -432,27 +450,28 @@
cur_xml_attr = xml_parser->getAttributeNameResID(ix);
}
- uint32_t resid = 0u;
+ uint32_t resid = 0;
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
- ApkAssetsCookie new_cookie =
- assetmanager->ResolveReference(cookie, &value, &config, &type_set_flags, &resid);
- if (new_cookie != kInvalidCookie) {
- cookie = new_cookie;
- }
+ // printf("Resolving attribute reference\n");
+ ssize_t new_block = res->resolveReference(&value, block, &resid,
+ &type_set_flags, &config);
+ if (new_block >= 0) block = new_block;
}
// Deal with the special @null value -- it turns back to TYPE_NULL.
if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
value.dataType = Res_value::TYPE_NULL;
value.data = Res_value::DATA_NULL_UNDEFINED;
- cookie = kInvalidCookie;
+ block = kXmlBlock;
}
// Write the final value back to Java.
out_values[STYLE_TYPE] = value.dataType;
out_values[STYLE_DATA] = value.data;
- out_values[STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
+ out_values[STYLE_ASSET_COOKIE] =
+ block != kXmlBlock ? static_cast<uint32_t>(res->getTableCookie(block))
+ : static_cast<uint32_t>(-1);
out_values[STYLE_RESOURCE_ID] = resid;
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
@@ -466,6 +485,8 @@
out_values += STYLE_NUM_ENTRIES;
}
+ res->unlock();
+
if (out_indices != nullptr) {
out_indices[0] = indices_idx;
}
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 1d2c597..28548e2 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -44,6 +44,44 @@
constexpr const static int kAppPackageId = 0x7f;
+// Element of a TypeSpec array. See TypeSpec.
+struct Type {
+ // The configuration for which this type defines entries.
+ // This is already converted to host endianness.
+ ResTable_config configuration;
+
+ // Pointer to the mmapped data where entry definitions are kept.
+ const ResTable_type* type;
+};
+
+// TypeSpec is going to be immediately proceeded by
+// an array of Type structs, all in the same block of memory.
+struct TypeSpec {
+ // Pointer to the mmapped data where flags are kept.
+ // Flags denote whether the resource entry is public
+ // and under which configurations it varies.
+ const ResTable_typeSpec* type_spec;
+
+ // Pointer to the mmapped data where the IDMAP mappings for this type
+ // exist. May be nullptr if no IDMAP exists.
+ const IdmapEntry_header* idmap_entries;
+
+ // The number of types that follow this struct.
+ // There is a type for each configuration
+ // that entries are defined for.
+ size_t type_count;
+
+ // Trick to easily access a variable number of Type structs
+ // proceeding this struct, and to ensure their alignment.
+ const Type types[0];
+};
+
+// TypeSpecPtr points to the block of memory that holds
+// a TypeSpec struct, followed by an array of Type structs.
+// TypeSpecPtr is a managed pointer that knows how to delete
+// itself.
+using TypeSpecPtr = util::unique_cptr<TypeSpec>;
+
namespace {
// Builder that helps accumulate Type structs and then create a single
@@ -57,22 +95,21 @@
}
void AddType(const ResTable_type* type) {
- types_.push_back(type);
+ ResTable_config config;
+ config.copyFromDtoH(type->config);
+ types_.push_back(Type{config, type});
}
TypeSpecPtr Build() {
// Check for overflow.
- using ElementType = const ResTable_type*;
- if ((std::numeric_limits<size_t>::max() - sizeof(TypeSpec)) / sizeof(ElementType) <
- types_.size()) {
+ if ((std::numeric_limits<size_t>::max() - sizeof(TypeSpec)) / sizeof(Type) < types_.size()) {
return {};
}
- TypeSpec* type_spec =
- (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(ElementType)));
+ TypeSpec* type_spec = (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(Type)));
type_spec->type_spec = header_;
type_spec->idmap_entries = idmap_header_;
type_spec->type_count = types_.size();
- memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(ElementType));
+ memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(Type));
return TypeSpecPtr(type_spec);
}
@@ -81,7 +118,7 @@
const ResTable_typeSpec* header_;
const IdmapEntry_header* idmap_header_;
- std::vector<const ResTable_type*> types_;
+ std::vector<Type> types_;
};
} // namespace
@@ -125,17 +162,18 @@
return true;
}
-static bool VerifyResTableEntry(const ResTable_type* type, uint32_t entry_offset) {
+static bool VerifyResTableEntry(const ResTable_type* type, uint32_t entry_offset,
+ size_t entry_idx) {
// Check that the offset is aligned.
if (entry_offset & 0x03) {
- LOG(ERROR) << "Entry at offset " << entry_offset << " is not 4-byte aligned.";
+ LOG(ERROR) << "Entry offset at index " << entry_idx << " is not 4-byte aligned.";
return false;
}
// Check that the offset doesn't overflow.
if (entry_offset > std::numeric_limits<uint32_t>::max() - dtohl(type->entriesStart)) {
// Overflow in offset.
- LOG(ERROR) << "Entry at offset " << entry_offset << " is too large.";
+ LOG(ERROR) << "Entry offset at index " << entry_idx << " is too large.";
return false;
}
@@ -143,7 +181,7 @@
entry_offset += dtohl(type->entriesStart);
if (entry_offset > chunk_size - sizeof(ResTable_entry)) {
- LOG(ERROR) << "Entry at offset " << entry_offset
+ LOG(ERROR) << "Entry offset at index " << entry_idx
<< " is too large. No room for ResTable_entry.";
return false;
}
@@ -153,13 +191,13 @@
const size_t entry_size = dtohs(entry->size);
if (entry_size < sizeof(*entry)) {
- LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset
+ LOG(ERROR) << "ResTable_entry size " << entry_size << " at index " << entry_idx
<< " is too small.";
return false;
}
if (entry_size > chunk_size || entry_offset > chunk_size - entry_size) {
- LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset
+ LOG(ERROR) << "ResTable_entry size " << entry_size << " at index " << entry_idx
<< " is too large.";
return false;
}
@@ -167,7 +205,7 @@
if (entry_size < sizeof(ResTable_map_entry)) {
// There needs to be room for one Res_value struct.
if (entry_offset + entry_size > chunk_size - sizeof(Res_value)) {
- LOG(ERROR) << "No room for Res_value after ResTable_entry at offset " << entry_offset
+ LOG(ERROR) << "No room for Res_value after ResTable_entry at index " << entry_idx
<< " for type " << (int)type->id << ".";
return false;
}
@@ -176,12 +214,12 @@
reinterpret_cast<const Res_value*>(reinterpret_cast<const uint8_t*>(entry) + entry_size);
const size_t value_size = dtohs(value->size);
if (value_size < sizeof(Res_value)) {
- LOG(ERROR) << "Res_value at offset " << entry_offset << " is too small.";
+ LOG(ERROR) << "Res_value at index " << entry_idx << " is too small.";
return false;
}
if (value_size > chunk_size || entry_offset + entry_size > chunk_size - value_size) {
- LOG(ERROR) << "Res_value size " << value_size << " at offset " << entry_offset
+ LOG(ERROR) << "Res_value size " << value_size << " at index " << entry_idx
<< " is too large.";
return false;
}
@@ -190,76 +228,119 @@
const size_t map_entry_count = dtohl(map->count);
size_t map_entries_start = entry_offset + entry_size;
if (map_entries_start & 0x03) {
- LOG(ERROR) << "Map entries at offset " << entry_offset << " start at unaligned offset.";
+ LOG(ERROR) << "Map entries at index " << entry_idx << " start at unaligned offset.";
return false;
}
// Each entry is sizeof(ResTable_map) big.
if (map_entry_count > ((chunk_size - map_entries_start) / sizeof(ResTable_map))) {
- LOG(ERROR) << "Too many map entries in ResTable_map_entry at offset " << entry_offset << ".";
+ LOG(ERROR) << "Too many map entries in ResTable_map_entry at index " << entry_idx << ".";
return false;
}
}
return true;
}
-const ResTable_entry* LoadedPackage::GetEntry(const ResTable_type* type_chunk,
- uint16_t entry_index) {
- uint32_t entry_offset = GetEntryOffset(type_chunk, entry_index);
- if (entry_offset == ResTable_type::NO_ENTRY) {
- return nullptr;
- }
- return GetEntryFromOffset(type_chunk, entry_offset);
-}
+bool LoadedPackage::FindEntry(const TypeSpecPtr& type_spec_ptr, uint16_t entry_idx,
+ const ResTable_config& config, FindEntryResult* out_entry) const {
+ const ResTable_config* best_config = nullptr;
+ const ResTable_type* best_type = nullptr;
+ uint32_t best_offset = 0;
-uint32_t LoadedPackage::GetEntryOffset(const ResTable_type* type_chunk, uint16_t entry_index) {
- // The configuration matches and is better than the previous selection.
- // Find the entry value if it exists for this configuration.
- const size_t entry_count = dtohl(type_chunk->entryCount);
- const size_t offsets_offset = dtohs(type_chunk->header.headerSize);
+ for (uint32_t i = 0; i < type_spec_ptr->type_count; i++) {
+ const Type* type = &type_spec_ptr->types[i];
+ const ResTable_type* type_chunk = type->type;
- // Check if there is the desired entry in this type.
+ if (type->configuration.match(config) &&
+ (best_config == nullptr || type->configuration.isBetterThan(*best_config, &config))) {
+ // The configuration matches and is better than the previous selection.
+ // Find the entry value if it exists for this configuration.
+ const size_t entry_count = dtohl(type_chunk->entryCount);
+ const size_t offsets_offset = dtohs(type_chunk->header.headerSize);
- if (type_chunk->flags & ResTable_type::FLAG_SPARSE) {
- // This is encoded as a sparse map, so perform a binary search.
- const ResTable_sparseTypeEntry* sparse_indices =
- reinterpret_cast<const ResTable_sparseTypeEntry*>(
+ // Check if there is the desired entry in this type.
+
+ if (type_chunk->flags & ResTable_type::FLAG_SPARSE) {
+ // This is encoded as a sparse map, so perform a binary search.
+ const ResTable_sparseTypeEntry* sparse_indices =
+ reinterpret_cast<const ResTable_sparseTypeEntry*>(
+ reinterpret_cast<const uint8_t*>(type_chunk) + offsets_offset);
+ const ResTable_sparseTypeEntry* sparse_indices_end = sparse_indices + entry_count;
+ const ResTable_sparseTypeEntry* result =
+ std::lower_bound(sparse_indices, sparse_indices_end, entry_idx,
+ [](const ResTable_sparseTypeEntry& entry, uint16_t entry_idx) {
+ return dtohs(entry.idx) < entry_idx;
+ });
+
+ if (result == sparse_indices_end || dtohs(result->idx) != entry_idx) {
+ // No entry found.
+ continue;
+ }
+
+ // Extract the offset from the entry. Each offset must be a multiple of 4 so we store it as
+ // the real offset divided by 4.
+ best_offset = uint32_t{dtohs(result->offset)} * 4u;
+ } else {
+ if (entry_idx >= entry_count) {
+ // This entry cannot be here.
+ continue;
+ }
+
+ const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
reinterpret_cast<const uint8_t*>(type_chunk) + offsets_offset);
- const ResTable_sparseTypeEntry* sparse_indices_end = sparse_indices + entry_count;
- const ResTable_sparseTypeEntry* result =
- std::lower_bound(sparse_indices, sparse_indices_end, entry_index,
- [](const ResTable_sparseTypeEntry& entry, uint16_t entry_idx) {
- return dtohs(entry.idx) < entry_idx;
- });
+ const uint32_t offset = dtohl(entry_offsets[entry_idx]);
+ if (offset == ResTable_type::NO_ENTRY) {
+ continue;
+ }
- if (result == sparse_indices_end || dtohs(result->idx) != entry_index) {
- // No entry found.
- return ResTable_type::NO_ENTRY;
+ // There is an entry for this resource, record it.
+ best_offset = offset;
+ }
+
+ best_config = &type->configuration;
+ best_type = type_chunk;
}
-
- // Extract the offset from the entry. Each offset must be a multiple of 4 so we store it as
- // the real offset divided by 4.
- return uint32_t{dtohs(result->offset)} * 4u;
}
- // This type is encoded as a dense array.
- if (entry_index >= entry_count) {
- // This entry cannot be here.
- return ResTable_type::NO_ENTRY;
+ if (best_type == nullptr) {
+ return false;
}
- const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
- reinterpret_cast<const uint8_t*>(type_chunk) + offsets_offset);
- return dtohl(entry_offsets[entry_index]);
+ if (UNLIKELY(!VerifyResTableEntry(best_type, best_offset, entry_idx))) {
+ return false;
+ }
+
+ const ResTable_entry* best_entry = reinterpret_cast<const ResTable_entry*>(
+ reinterpret_cast<const uint8_t*>(best_type) + best_offset + dtohl(best_type->entriesStart));
+
+ const uint32_t* flags = reinterpret_cast<const uint32_t*>(type_spec_ptr->type_spec + 1);
+ out_entry->type_flags = dtohl(flags[entry_idx]);
+ out_entry->entry = best_entry;
+ out_entry->config = best_config;
+ out_entry->type_string_ref = StringPoolRef(&type_string_pool_, best_type->id - 1);
+ out_entry->entry_string_ref = StringPoolRef(&key_string_pool_, dtohl(best_entry->key.index));
+ return true;
}
-const ResTable_entry* LoadedPackage::GetEntryFromOffset(const ResTable_type* type_chunk,
- uint32_t offset) {
- if (UNLIKELY(!VerifyResTableEntry(type_chunk, offset))) {
- return nullptr;
+bool LoadedPackage::FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
+ FindEntryResult* out_entry) const {
+ ATRACE_CALL();
+
+ // If the type IDs are offset in this package, we need to take that into account when searching
+ // for a type.
+ const TypeSpecPtr& ptr = type_specs_[type_idx - type_id_offset_];
+ if (UNLIKELY(ptr == nullptr)) {
+ return false;
}
- return reinterpret_cast<const ResTable_entry*>(reinterpret_cast<const uint8_t*>(type_chunk) +
- offset + dtohl(type_chunk->entriesStart));
+
+ // If there is an IDMAP supplied with this package, translate the entry ID.
+ if (ptr->idmap_entries != nullptr) {
+ if (!LoadedIdmap::Lookup(ptr->idmap_entries, entry_idx, &entry_idx)) {
+ // There is no mapping, so the resource is not meant to be in this overlay package.
+ return false;
+ }
+ }
+ return FindEntry(ptr, entry_idx, config, out_entry);
}
void LoadedPackage::CollectConfigurations(bool exclude_mipmap,
@@ -267,7 +348,7 @@
const static std::u16string kMipMap = u"mipmap";
const size_t type_count = type_specs_.size();
for (size_t i = 0; i < type_count; i++) {
- const TypeSpecPtr& type_spec = type_specs_[i];
+ const util::unique_cptr<TypeSpec>& type_spec = type_specs_[i];
if (type_spec != nullptr) {
if (exclude_mipmap) {
const int type_idx = type_spec->type_spec->id - 1;
@@ -288,11 +369,8 @@
}
}
- const auto iter_end = type_spec->types + type_spec->type_count;
- for (auto iter = type_spec->types; iter != iter_end; ++iter) {
- ResTable_config config;
- config.copyFromDtoH((*iter)->config);
- out_configs->insert(config);
+ for (size_t j = 0; j < type_spec->type_count; j++) {
+ out_configs->insert(type_spec->types[j].configuration);
}
}
}
@@ -302,12 +380,10 @@
char temp_locale[RESTABLE_MAX_LOCALE_LEN];
const size_t type_count = type_specs_.size();
for (size_t i = 0; i < type_count; i++) {
- const TypeSpecPtr& type_spec = type_specs_[i];
+ const util::unique_cptr<TypeSpec>& type_spec = type_specs_[i];
if (type_spec != nullptr) {
- const auto iter_end = type_spec->types + type_spec->type_count;
- for (auto iter = type_spec->types; iter != iter_end; ++iter) {
- ResTable_config configuration;
- configuration.copyFromDtoH((*iter)->config);
+ for (size_t j = 0; j < type_spec->type_count; j++) {
+ const ResTable_config& configuration = type_spec->types[j].configuration;
if (configuration.locale != 0) {
configuration.getBcp47Locale(temp_locale, canonicalize);
std::string locale(temp_locale);
@@ -335,17 +411,17 @@
return 0u;
}
- const auto iter_end = type_spec->types + type_spec->type_count;
- for (auto iter = type_spec->types; iter != iter_end; ++iter) {
- const ResTable_type* type = *iter;
- size_t entry_count = dtohl(type->entryCount);
+ for (size_t ti = 0; ti < type_spec->type_count; ti++) {
+ const Type* type = &type_spec->types[ti];
+ size_t entry_count = dtohl(type->type->entryCount);
for (size_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
- reinterpret_cast<const uint8_t*>(type) + dtohs(type->header.headerSize));
+ reinterpret_cast<const uint8_t*>(type->type) + dtohs(type->type->header.headerSize));
const uint32_t offset = dtohl(entry_offsets[entry_idx]);
if (offset != ResTable_type::NO_ENTRY) {
- const ResTable_entry* entry = reinterpret_cast<const ResTable_entry*>(
- reinterpret_cast<const uint8_t*>(type) + dtohl(type->entriesStart) + offset);
+ const ResTable_entry* entry =
+ reinterpret_cast<const ResTable_entry*>(reinterpret_cast<const uint8_t*>(type->type) +
+ dtohl(type->type->entriesStart) + offset);
if (dtohl(entry->key.index) == static_cast<uint32_t>(key_idx)) {
// The package ID will be overridden by the caller (due to runtime assignment of package
// IDs for shared libraries).
@@ -357,7 +433,8 @@
return 0u;
}
-const LoadedPackage* LoadedArsc::GetPackageById(uint8_t package_id) const {
+const LoadedPackage* LoadedArsc::GetPackageForId(uint32_t resid) const {
+ const uint8_t package_id = get_package_id(resid);
for (const auto& loaded_package : packages_) {
if (loaded_package->GetPackageId() == package_id) {
return loaded_package.get();
@@ -605,6 +682,26 @@
return std::move(loaded_package);
}
+bool LoadedArsc::FindEntry(uint32_t resid, const ResTable_config& config,
+ FindEntryResult* out_entry) const {
+ ATRACE_CALL();
+
+ const uint8_t package_id = get_package_id(resid);
+ const uint8_t type_id = get_type_id(resid);
+ const uint16_t entry_id = get_entry_id(resid);
+
+ if (UNLIKELY(type_id == 0)) {
+ LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid);
+ return false;
+ }
+
+ for (const auto& loaded_package : packages_) {
+ if (loaded_package->GetPackageId() == package_id) {
+ return loaded_package->FindEntry(type_id - 1, entry_id, config, out_entry);
+ }
+ }
+ return false;
+}
bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
bool load_as_shared_library) {
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index ecc5dc1..08da731 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -60,6 +60,7 @@
static const char* RESOURCES_FILENAME;
static const char* IDMAP_BIN;
static const char* OVERLAY_DIR;
+ static const char* PRODUCT_OVERLAY_DIR;
/*
* If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay
* APKs in OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index ef08897..b033137 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -69,8 +69,6 @@
Entry entries[0];
};
-struct FindEntryResult;
-
// AssetManager2 is the main entry point for accessing assets and resources.
// AssetManager2 provides caching of resources retrieved via the underlying ApkAssets.
class AssetManager2 {
@@ -129,7 +127,7 @@
// If `exclude_mipmap` is set to true, resource configurations defined for resource type 'mipmap'
// will be excluded from the list.
std::set<ResTable_config> GetResourceConfigurations(bool exclude_system = false,
- bool exclude_mipmap = false) const;
+ bool exclude_mipmap = false);
// Returns all the locales for which there are resources defined. This includes resource
// locales in all the ApkAssets set for this AssetManager.
@@ -138,24 +136,24 @@
// If `merge_equivalent_languages` is set to true, resource locales will be canonicalized
// and de-duped in the resulting list.
std::set<std::string> GetResourceLocales(bool exclude_system = false,
- bool merge_equivalent_languages = false) const;
+ bool merge_equivalent_languages = false);
// Searches the set of APKs loaded by this AssetManager and opens the first one found located
// in the assets/ directory.
// `mode` controls how the file is opened.
//
// NOTE: The loaded APKs are searched in reverse order.
- std::unique_ptr<Asset> Open(const std::string& filename, Asset::AccessMode mode) const;
+ std::unique_ptr<Asset> Open(const std::string& filename, Asset::AccessMode mode);
// Opens a file within the assets/ directory of the APK specified by `cookie`.
// `mode` controls how the file is opened.
std::unique_ptr<Asset> Open(const std::string& filename, ApkAssetsCookie cookie,
- Asset::AccessMode mode) const;
+ Asset::AccessMode mode);
// Opens the directory specified by `dirname`. The result is an AssetDir that is the combination
// of all directories matching `dirname` under the assets/ directory of every ApkAssets loaded.
// The entries are sorted by their ASCII name.
- std::unique_ptr<AssetDir> OpenDir(const std::string& dirname) const;
+ std::unique_ptr<AssetDir> OpenDir(const std::string& dirname);
// Searches the set of APKs loaded by this AssetManager and opens the first one found.
// `mode` controls how the file is opened.
@@ -163,24 +161,24 @@
//
// NOTE: The loaded APKs are searched in reverse order.
std::unique_ptr<Asset> OpenNonAsset(const std::string& filename, Asset::AccessMode mode,
- ApkAssetsCookie* out_cookie = nullptr) const;
+ ApkAssetsCookie* out_cookie = nullptr);
// Opens a file in the APK specified by `cookie`. `mode` controls how the file is opened.
// This is typically used to open a specific AndroidManifest.xml, or a binary XML file
// referenced by a resource lookup with GetResource().
std::unique_ptr<Asset> OpenNonAsset(const std::string& filename, ApkAssetsCookie cookie,
- Asset::AccessMode mode) const;
+ Asset::AccessMode mode);
// Populates the `out_name` parameter with resource name information.
// Utf8 strings are preferred, and only if they are unavailable are
// the Utf16 variants populated.
// Returns false if the resource was not found or the name was missing/corrupt.
- bool GetResourceName(uint32_t resid, ResourceName* out_name) const;
+ bool GetResourceName(uint32_t resid, ResourceName* out_name);
// Populates `out_flags` with the bitmask of configuration axis that this resource varies with.
// See ResTable_config for the list of configuration axis.
// Returns false if the resource was not found.
- bool GetResourceFlags(uint32_t resid, uint32_t* out_flags) const;
+ bool GetResourceFlags(uint32_t resid, uint32_t* out_flags);
// Finds the resource ID assigned to `resource_name`.
// `resource_name` must be of the form '[package:][type/]entry'.
@@ -188,7 +186,7 @@
// If no type is specified in `resource_name`, then `fallback_type` is used as the type.
// Returns 0x0 if no resource by that name was found.
uint32_t GetResourceId(const std::string& resource_name, const std::string& fallback_type = {},
- const std::string& fallback_package = {}) const;
+ const std::string& fallback_package = {});
// Retrieves the best matching resource with ID `resid`. The resource value is filled into
// `out_value` and the configuration for the selected value is populated in `out_selected_config`.
@@ -201,7 +199,7 @@
// this function logs if the resource was a map/bag type before returning kInvalidCookie.
ApkAssetsCookie GetResource(uint32_t resid, bool may_be_bag, uint16_t density_override,
Res_value* out_value, ResTable_config* out_selected_config,
- uint32_t* out_flags) const;
+ uint32_t* out_flags);
// Resolves the resource reference in `in_out_value` if the data type is
// Res_value::TYPE_REFERENCE.
@@ -217,7 +215,7 @@
// it was not found.
ApkAssetsCookie ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
ResTable_config* in_out_selected_config, uint32_t* in_out_flags,
- uint32_t* out_last_reference) const;
+ uint32_t* out_last_reference);
// Retrieves the best matching bag/map resource with ID `resid`.
// This method will resolve all parent references for this bag and merge keys with the child.
@@ -235,9 +233,9 @@
std::unique_ptr<Theme> NewTheme();
template <typename Func>
- void ForEachPackage(Func func) const {
+ void ForEachPackage(Func func) {
for (const PackageGroup& package_group : package_groups_) {
- func(package_group.packages_.front().loaded_package_->GetPackageName(),
+ func(package_group.packages_.front()->GetPackageName(),
package_group.dynamic_ref_table.mAssignedPackageId);
}
}
@@ -262,7 +260,7 @@
// NOTE: FindEntry takes care of ensuring that structs within FindEntryResult have been properly
// bounds-checked. Callers of FindEntry are free to trust the data if this method succeeds.
ApkAssetsCookie FindEntry(uint32_t resid, uint16_t density_override, bool stop_at_first_match,
- FindEntryResult* out_entry) const;
+ FindEntryResult* out_entry);
// Assigns package IDs to all shared library ApkAssets.
// Should be called whenever the ApkAssets are changed.
@@ -272,43 +270,13 @@
// bitmask `diff`.
void InvalidateCaches(uint32_t diff);
- // Triggers the re-construction of lists of types that match the set configuration.
- // This should always be called when mutating the AssetManager's configuration or ApkAssets set.
- void RebuildFilterList();
-
// The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must
// have a longer lifetime.
std::vector<const ApkAssets*> apk_assets_;
- // A collection of configurations and their associated ResTable_type that match the current
- // AssetManager configuration.
- struct FilteredConfigGroup {
- std::vector<ResTable_config> configurations;
- std::vector<const ResTable_type*> types;
- };
-
- // Represents an single package.
- struct ConfiguredPackage {
- // A pointer to the immutable, loaded package info.
- const LoadedPackage* loaded_package_;
-
- // A mutable AssetManager-specific list of configurations that match the AssetManager's
- // current configuration. This is used as an optimization to avoid checking every single
- // candidate configuration when looking up resources.
- ByteBucketArray<FilteredConfigGroup> filtered_configs_;
- };
-
- // Represents a logical package, which can be made up of many individual packages. Each package
- // in a PackageGroup shares the same package name and package ID.
struct PackageGroup {
- // The set of packages that make-up this group.
- std::vector<ConfiguredPackage> packages_;
-
- // The cookies associated with each package in the group. They share the same order as
- // packages_.
+ std::vector<const LoadedPackage*> packages_;
std::vector<ApkAssetsCookie> cookies_;
-
- // A library reference table that contains build-package ID to runtime-package ID mappings.
DynamicRefTable dynamic_ref_table;
};
@@ -382,7 +350,7 @@
ApkAssetsCookie ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value,
ResTable_config* in_out_selected_config = nullptr,
uint32_t* in_out_type_spec_flags = nullptr,
- uint32_t* out_last_ref = nullptr) const;
+ uint32_t* out_last_ref = nullptr);
private:
DISALLOW_COPY_AND_ASSIGN(Theme);
diff --git a/libs/androidfw/include/androidfw/AttributeFinder.h b/libs/androidfw/include/androidfw/AttributeFinder.h
index 03fad49..f281921 100644
--- a/libs/androidfw/include/androidfw/AttributeFinder.h
+++ b/libs/androidfw/include/androidfw/AttributeFinder.h
@@ -58,7 +58,6 @@
BackTrackingAttributeFinder(const Iterator& begin, const Iterator& end);
Iterator Find(uint32_t attr);
- inline Iterator end();
private:
void JumpToClosestAttribute(uint32_t package_id);
@@ -202,11 +201,6 @@
return end_;
}
-template <typename Derived, typename Iterator>
-Iterator BackTrackingAttributeFinder<Derived, Iterator>::end() {
- return end_;
-}
-
} // namespace android
#endif // ANDROIDFW_ATTRIBUTE_FINDER_H
diff --git a/libs/androidfw/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h
index 35ef98d..69b76041 100644
--- a/libs/androidfw/include/androidfw/AttributeResolution.h
+++ b/libs/androidfw/include/androidfw/AttributeResolution.h
@@ -17,8 +17,7 @@
#ifndef ANDROIDFW_ATTRIBUTERESOLUTION_H
#define ANDROIDFW_ATTRIBUTERESOLUTION_H
-#include "androidfw/AssetManager2.h"
-#include "androidfw/ResourceTypes.h"
+#include <androidfw/ResourceTypes.h>
namespace android {
@@ -43,19 +42,19 @@
// `out_values` must NOT be nullptr.
// `out_indices` may be nullptr.
-bool ResolveAttrs(Theme* theme, uint32_t def_style_attr, uint32_t def_style_resid,
+bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr, uint32_t def_style_res,
uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
// `out_values` must NOT be nullptr.
// `out_indices` is NOT optional and must NOT be nullptr.
-void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
- uint32_t def_style_resid, const uint32_t* attrs, size_t attrs_length,
+void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
+ uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
uint32_t* out_values, uint32_t* out_indices);
// `out_values` must NOT be nullptr.
// `out_indices` may be nullptr.
-bool RetrieveAttributes(AssetManager2* assetmanager, ResXMLParser* xml_parser, uint32_t* attrs,
+bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, uint32_t* attrs,
size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
} // namespace android
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 35ae5fc..965e2db 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -41,40 +41,32 @@
int package_id = 0;
};
-// TypeSpec is going to be immediately proceeded by
-// an array of Type structs, all in the same block of memory.
-struct TypeSpec {
- // Pointer to the mmapped data where flags are kept.
- // Flags denote whether the resource entry is public
- // and under which configurations it varies.
- const ResTable_typeSpec* type_spec;
+struct FindEntryResult {
+ // A pointer to the resource table entry for this resource.
+ // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
+ // a ResTable_map_entry and processed as a bag/map.
+ const ResTable_entry* entry = nullptr;
- // Pointer to the mmapped data where the IDMAP mappings for this type
- // exist. May be nullptr if no IDMAP exists.
- const IdmapEntry_header* idmap_entries;
+ // The configuration for which the resulting entry was defined.
+ const ResTable_config* config = nullptr;
- // The number of types that follow this struct.
- // There is a type for each configuration that entries are defined for.
- size_t type_count;
+ // Stores the resulting bitmask of configuration axis with which the resource value varies.
+ uint32_t type_flags = 0u;
- // Trick to easily access a variable number of Type structs
- // proceeding this struct, and to ensure their alignment.
- const ResTable_type* types[0];
+ // The dynamic package ID map for the package from which this resource came from.
+ const DynamicRefTable* dynamic_ref_table = nullptr;
- inline uint32_t GetFlagsForEntryIndex(uint16_t entry_index) const {
- if (entry_index >= dtohl(type_spec->entryCount)) {
- return 0u;
- }
+ // The string pool reference to the type's name. This uses a different string pool than
+ // the global string pool, but this is hidden from the caller.
+ StringPoolRef type_string_ref;
- const uint32_t* flags = reinterpret_cast<const uint32_t*>(type_spec + 1);
- return flags[entry_index];
- }
+ // The string pool reference to the entry's name. This uses a different string pool than
+ // the global string pool, but this is hidden from the caller.
+ StringPoolRef entry_string_ref;
};
-// TypeSpecPtr points to a block of memory that holds a TypeSpec struct, followed by an array of
-// ResTable_type pointers.
-// TypeSpecPtr is a managed pointer that knows how to delete itself.
-using TypeSpecPtr = util::unique_cptr<TypeSpec>;
+struct TypeSpec;
+class LoadedArsc;
class LoadedPackage {
public:
@@ -84,6 +76,9 @@
~LoadedPackage();
+ bool FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
+ FindEntryResult* out_entry) const;
+
// Finds the entry with the specified type name and entry name. The names are in UTF-16 because
// the underlying ResStringPool API expects this. For now this is acceptable, but since
// the default policy in AAPT2 is to build UTF-8 string pools, this needs to change.
@@ -91,12 +86,6 @@
// for patching the correct package ID to the resource ID.
uint32_t FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const;
- static const ResTable_entry* GetEntry(const ResTable_type* type_chunk, uint16_t entry_index);
-
- static uint32_t GetEntryOffset(const ResTable_type* type_chunk, uint16_t entry_index);
-
- static const ResTable_entry* GetEntryFromOffset(const ResTable_type* type_chunk, uint32_t offset);
-
// Returns the string pool where type names are stored.
inline const ResStringPool* GetTypeStringPool() const {
return &type_string_pool_;
@@ -146,32 +135,14 @@
// before being inserted into the set. This may cause some equivalent locales to de-dupe.
void CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const;
- // type_idx is TT - 1 from 0xPPTTEEEE.
- inline const TypeSpec* GetTypeSpecByTypeIndex(uint8_t type_index) const {
- // If the type IDs are offset in this package, we need to take that into account when searching
- // for a type.
- return type_specs_[type_index - type_id_offset_].get();
- }
-
- template <typename Func>
- void ForEachTypeSpec(Func f) const {
- for (size_t i = 0; i < type_specs_.size(); i++) {
- const TypeSpecPtr& ptr = type_specs_[i];
- if (ptr != nullptr) {
- uint8_t type_id = ptr->type_spec->id;
- if (ptr->idmap_entries != nullptr) {
- type_id = ptr->idmap_entries->target_type_id;
- }
- f(ptr.get(), type_id - 1);
- }
- }
- }
-
private:
DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
LoadedPackage();
+ bool FindEntry(const util::unique_cptr<TypeSpec>& type_spec_ptr, uint16_t entry_idx,
+ const ResTable_config& config, FindEntryResult* out_entry) const;
+
ResStringPool type_string_pool_;
ResStringPool key_string_pool_;
std::string package_name_;
@@ -181,7 +152,7 @@
bool system_ = false;
bool overlay_ = false;
- ByteBucketArray<TypeSpecPtr> type_specs_;
+ ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
std::vector<DynamicPackageEntry> dynamic_package_map_;
};
@@ -209,20 +180,25 @@
return &global_string_pool_;
}
- // Gets a pointer to the package with the specified package ID, or nullptr if no such package
- // exists.
- const LoadedPackage* GetPackageById(uint8_t package_id) const;
+ // Finds the resource with ID `resid` with the best value for configuration `config`.
+ // The parameter `out_entry` will be filled with the resulting resource entry.
+ // The resource entry can be a simple entry (ResTable_entry) or a complex bag
+ // (ResTable_entry_map).
+ bool FindEntry(uint32_t resid, const ResTable_config& config, FindEntryResult* out_entry) const;
- // Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc.
- inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
- return packages_;
- }
+ // Gets a pointer to the name of the package in `resid`, or nullptr if the package doesn't exist.
+ const LoadedPackage* GetPackageForId(uint32_t resid) const;
// Returns true if this is a system provided resource.
inline bool IsSystem() const {
return system_;
}
+ // Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc.
+ inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
+ return packages_;
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
diff --git a/libs/androidfw/include/androidfw/MutexGuard.h b/libs/androidfw/include/androidfw/MutexGuard.h
deleted file mode 100644
index 64924f4..0000000
--- a/libs/androidfw/include/androidfw/MutexGuard.h
+++ /dev/null
@@ -1,101 +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.
- */
-
-#ifndef ANDROIDFW_MUTEXGUARD_H
-#define ANDROIDFW_MUTEXGUARD_H
-
-#include <mutex>
-#include <type_traits>
-
-#include "android-base/macros.h"
-
-namespace android {
-
-template <typename T>
-class ScopedLock;
-
-// Owns the guarded object and protects access to it via a mutex.
-// The guarded object is inaccessible via this class.
-// The mutex is locked and the object accessed via the ScopedLock<T> class.
-//
-// NOTE: The template parameter T should not be a raw pointer, since ownership
-// is ambiguous and error-prone. Instead use an std::unique_ptr<>.
-//
-// Example use:
-//
-// Guarded<std::string> shared_string("hello");
-// {
-// ScopedLock<std::string> locked_string(shared_string);
-// *locked_string += " world";
-// }
-//
-template <typename T>
-class Guarded {
- static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer");
-
- public:
- explicit Guarded() : guarded_() {
- }
-
- template <typename U = T>
- explicit Guarded(const T& guarded,
- typename std::enable_if<std::is_copy_constructible<U>::value>::type = void())
- : guarded_(guarded) {
- }
-
- template <typename U = T>
- explicit Guarded(T&& guarded,
- typename std::enable_if<std::is_move_constructible<U>::value>::type = void())
- : guarded_(std::move(guarded)) {
- }
-
- private:
- friend class ScopedLock<T>;
-
- DISALLOW_COPY_AND_ASSIGN(Guarded);
-
- std::mutex lock_;
- T guarded_;
-};
-
-template <typename T>
-class ScopedLock {
- public:
- explicit ScopedLock(Guarded<T>& guarded) : lock_(guarded.lock_), guarded_(guarded.guarded_) {
- }
-
- T& operator*() {
- return guarded_;
- }
-
- T* operator->() {
- return &guarded_;
- }
-
- T* get() {
- return &guarded_;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ScopedLock);
-
- std::lock_guard<std::mutex> lock_;
- T& guarded_;
-};
-
-} // namespace android
-
-#endif // ANDROIDFW_MUTEXGUARD_H
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index e2b9f00..6c43a67 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -26,56 +26,58 @@
using ::android::base::unique_fd;
using ::com::android::basic::R;
-using ::testing::Eq;
-using ::testing::Ge;
-using ::testing::NotNull;
-using ::testing::SizeIs;
-using ::testing::StrEq;
namespace android {
TEST(ApkAssetsTest, LoadApk) {
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
- ASSERT_THAT(loaded_apk, NotNull());
+ ASSERT_NE(nullptr, loaded_apk);
const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
- ASSERT_THAT(loaded_arsc, NotNull());
- ASSERT_THAT(loaded_arsc->GetPackageById(0x7fu), NotNull());
- ASSERT_THAT(loaded_apk->Open("res/layout/main.xml"), NotNull());
+ ASSERT_NE(nullptr, loaded_arsc);
+
+ const LoadedPackage* loaded_package = loaded_arsc->GetPackageForId(0x7f010000);
+ ASSERT_NE(nullptr, loaded_package);
+
+ std::unique_ptr<Asset> asset = loaded_apk->Open("res/layout/main.xml");
+ ASSERT_NE(nullptr, asset);
}
TEST(ApkAssetsTest, LoadApkFromFd) {
const std::string path = GetTestDataPath() + "/basic/basic.apk";
unique_fd fd(::open(path.c_str(), O_RDONLY | O_BINARY));
- ASSERT_THAT(fd.get(), Ge(0));
+ ASSERT_GE(fd.get(), 0);
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::LoadFromFd(std::move(fd), path, false /*system*/, false /*force_shared_lib*/);
- ASSERT_THAT(loaded_apk, NotNull());
+ ASSERT_NE(nullptr, loaded_apk);
const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
- ASSERT_THAT(loaded_arsc, NotNull());
- ASSERT_THAT(loaded_arsc->GetPackageById(0x7fu), NotNull());
- ASSERT_THAT(loaded_apk->Open("res/layout/main.xml"), NotNull());
+ ASSERT_NE(nullptr, loaded_arsc);
+
+ const LoadedPackage* loaded_package = loaded_arsc->GetPackageForId(0x7f010000);
+ ASSERT_NE(nullptr, loaded_package);
+
+ std::unique_ptr<Asset> asset = loaded_apk->Open("res/layout/main.xml");
+ ASSERT_NE(nullptr, asset);
}
TEST(ApkAssetsTest, LoadApkAsSharedLibrary) {
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
- ASSERT_THAT(loaded_apk, NotNull());
-
+ ASSERT_NE(nullptr, loaded_apk);
const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
- ASSERT_THAT(loaded_arsc, NotNull());
- ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u));
+ ASSERT_NE(nullptr, loaded_arsc);
+ ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
EXPECT_FALSE(loaded_arsc->GetPackages()[0]->IsDynamic());
loaded_apk = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/appaslib/appaslib.apk");
- ASSERT_THAT(loaded_apk, NotNull());
+ ASSERT_NE(nullptr, loaded_apk);
loaded_arsc = loaded_apk->GetLoadedArsc();
- ASSERT_THAT(loaded_arsc, NotNull());
- ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u));
+ ASSERT_NE(nullptr, loaded_arsc);
+ ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
EXPECT_TRUE(loaded_arsc->GetPackages()[0]->IsDynamic());
}
@@ -84,22 +86,19 @@
ResTable target_table;
const std::string target_path = GetTestDataPath() + "/basic/basic.apk";
ASSERT_TRUE(ReadFileFromZipToString(target_path, "resources.arsc", &contents));
- ASSERT_THAT(target_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
- Eq(NO_ERROR));
+ ASSERT_EQ(NO_ERROR, target_table.add(contents.data(), contents.size(), 0, true /*copyData*/));
ResTable overlay_table;
const std::string overlay_path = GetTestDataPath() + "/overlay/overlay.apk";
ASSERT_TRUE(ReadFileFromZipToString(overlay_path, "resources.arsc", &contents));
- ASSERT_THAT(overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
- Eq(NO_ERROR));
+ ASSERT_EQ(NO_ERROR, overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/));
util::unique_cptr<void> idmap_data;
void* temp_data;
size_t idmap_len;
- ASSERT_THAT(target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
- overlay_path.c_str(), &temp_data, &idmap_len),
- Eq(NO_ERROR));
+ ASSERT_EQ(NO_ERROR, target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
+ overlay_path.c_str(), &temp_data, &idmap_len));
idmap_data.reset(temp_data);
TemporaryFile tf;
@@ -109,30 +108,37 @@
// Open something so that the destructor of TemporaryFile closes a valid fd.
tf.fd = open("/dev/null", O_WRONLY);
- ASSERT_THAT(ApkAssets::LoadOverlay(tf.path), NotNull());
+ std::unique_ptr<const ApkAssets> loaded_overlay_apk = ApkAssets::LoadOverlay(tf.path);
+ ASSERT_NE(nullptr, loaded_overlay_apk);
}
TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) {
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
- ASSERT_THAT(loaded_apk, NotNull());
+ ASSERT_NE(nullptr, loaded_apk);
- { ASSERT_THAT(loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER), NotNull()); }
+ {
+ std::unique_ptr<Asset> assets = loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER);
+ ASSERT_NE(nullptr, assets);
+ }
- { ASSERT_THAT(loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER), NotNull()); }
+ {
+ std::unique_ptr<Asset> assets = loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER);
+ ASSERT_NE(nullptr, assets);
+ }
}
TEST(ApkAssetsTest, OpenUncompressedAssetFd) {
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
- ASSERT_THAT(loaded_apk, NotNull());
+ ASSERT_NE(nullptr, loaded_apk);
auto asset = loaded_apk->Open("assets/uncompressed.txt", Asset::ACCESS_UNKNOWN);
- ASSERT_THAT(asset, NotNull());
+ ASSERT_NE(nullptr, asset);
off64_t start, length;
unique_fd fd(asset->openFileDescriptor(&start, &length));
- ASSERT_THAT(fd.get(), Ge(0));
+ EXPECT_GE(fd.get(), 0);
lseek64(fd.get(), start, SEEK_SET);
@@ -140,7 +146,7 @@
buffer.resize(length);
ASSERT_TRUE(base::ReadFully(fd.get(), &*buffer.begin(), length));
- EXPECT_THAT(buffer, StrEq("This should be uncompressed.\n\n"));
+ EXPECT_EQ("This should be uncompressed.\n\n", buffer);
}
} // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index 437e147..85e8f25 100644
--- a/libs/androidfw/tests/AssetManager2_bench.cpp
+++ b/libs/androidfw/tests/AssetManager2_bench.cpp
@@ -81,18 +81,17 @@
}
BENCHMARK(BM_AssetManagerLoadFrameworkAssetsOld);
-static void BM_AssetManagerGetResource(benchmark::State& state, uint32_t resid) {
- GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/, resid, state);
+static void BM_AssetManagerGetResource(benchmark::State& state) {
+ GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
+ basic::R::integer::number1, state);
}
-BENCHMARK_CAPTURE(BM_AssetManagerGetResource, number1, basic::R::integer::number1);
-BENCHMARK_CAPTURE(BM_AssetManagerGetResource, deep_ref, basic::R::integer::deep_ref);
+BENCHMARK(BM_AssetManagerGetResource);
-static void BM_AssetManagerGetResourceOld(benchmark::State& state, uint32_t resid) {
- GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/, resid,
- state);
+static void BM_AssetManagerGetResourceOld(benchmark::State& state) {
+ GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
+ basic::R::integer::number1, state);
}
-BENCHMARK_CAPTURE(BM_AssetManagerGetResourceOld, number1, basic::R::integer::number1);
-BENCHMARK_CAPTURE(BM_AssetManagerGetResourceOld, deep_ref, basic::R::integer::deep_ref);
+BENCHMARK(BM_AssetManagerGetResourceOld);
static void BM_AssetManagerGetLibraryResource(benchmark::State& state) {
GetResourceBenchmark(
@@ -197,7 +196,7 @@
static void BM_AssetManagerGetResourceLocalesOld(benchmark::State& state) {
AssetManager assets;
if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
- true /*isSystemAssets*/)) {
+ false /*isSystemAssets*/)) {
state.SkipWithError("Failed to load assets");
return;
}
@@ -212,44 +211,4 @@
}
BENCHMARK(BM_AssetManagerGetResourceLocalesOld);
-static void BM_AssetManagerSetConfigurationFramework(benchmark::State& state) {
- std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
- if (apk == nullptr) {
- state.SkipWithError("Failed to load assets");
- return;
- }
-
- AssetManager2 assets;
- assets.SetApkAssets({apk.get()});
-
- ResTable_config config;
- memset(&config, 0, sizeof(config));
-
- while (state.KeepRunning()) {
- config.sdkVersion = ~config.sdkVersion;
- assets.SetConfiguration(config);
- }
-}
-BENCHMARK(BM_AssetManagerSetConfigurationFramework);
-
-static void BM_AssetManagerSetConfigurationFrameworkOld(benchmark::State& state) {
- AssetManager assets;
- if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
- true /*isSystemAssets*/)) {
- state.SkipWithError("Failed to load assets");
- return;
- }
-
- const ResTable& table = assets.getResources(true);
-
- ResTable_config config;
- memset(&config, 0, sizeof(config));
-
- while (state.KeepRunning()) {
- config.sdkVersion = ~config.sdkVersion;
- assets.setConfiguration(config);
- }
-}
-BENCHMARK(BM_AssetManagerSetConfigurationFrameworkOld);
-
} // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_bench.cpp b/libs/androidfw/tests/AttributeResolution_bench.cpp
deleted file mode 100644
index fa300c5..0000000
--- a/libs/androidfw/tests/AttributeResolution_bench.cpp
+++ /dev/null
@@ -1,175 +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.
- */
-
-#include "benchmark/benchmark.h"
-
-//#include "android-base/stringprintf.h"
-#include "androidfw/ApkAssets.h"
-#include "androidfw/AssetManager.h"
-#include "androidfw/AssetManager2.h"
-#include "androidfw/AttributeResolution.h"
-#include "androidfw/ResourceTypes.h"
-
-#include "BenchmarkHelpers.h"
-#include "data/basic/R.h"
-#include "data/styles/R.h"
-
-namespace app = com::android::app;
-namespace basic = com::android::basic;
-
-namespace android {
-
-constexpr const static char* kFrameworkPath = "/system/framework/framework-res.apk";
-constexpr const static uint32_t Theme_Material_Light = 0x01030237u;
-
-static void BM_ApplyStyle(benchmark::State& state) {
- std::unique_ptr<const ApkAssets> styles_apk =
- ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
- if (styles_apk == nullptr) {
- state.SkipWithError("failed to load assets");
- return;
- }
-
- AssetManager2 assetmanager;
- assetmanager.SetApkAssets({styles_apk.get()});
-
- std::unique_ptr<Asset> asset =
- assetmanager.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER);
- if (asset == nullptr) {
- state.SkipWithError("failed to load layout");
- return;
- }
-
- ResXMLTree xml_tree;
- if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
- state.SkipWithError("corrupt xml layout");
- return;
- }
-
- // Skip to the first tag.
- while (xml_tree.next() != ResXMLParser::START_TAG) {
- }
-
- std::unique_ptr<Theme> theme = assetmanager.NewTheme();
- theme->ApplyStyle(app::R::style::StyleTwo);
-
- std::array<uint32_t, 6> attrs{{app::R::attr::attr_one, app::R::attr::attr_two,
- app::R::attr::attr_three, app::R::attr::attr_four,
- app::R::attr::attr_five, app::R::attr::attr_empty}};
- std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
- std::array<uint32_t, attrs.size() + 1> indices;
-
- while (state.KeepRunning()) {
- ApplyStyle(theme.get(), &xml_tree, 0u /*def_style_attr*/, 0u /*def_style_res*/, attrs.data(),
- attrs.size(), values.data(), indices.data());
- }
-}
-BENCHMARK(BM_ApplyStyle);
-
-static void BM_ApplyStyleFramework(benchmark::State& state) {
- std::unique_ptr<const ApkAssets> framework_apk = ApkAssets::Load(kFrameworkPath);
- if (framework_apk == nullptr) {
- state.SkipWithError("failed to load framework assets");
- return;
- }
-
- std::unique_ptr<const ApkAssets> basic_apk =
- ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
- if (basic_apk == nullptr) {
- state.SkipWithError("failed to load assets");
- return;
- }
-
- AssetManager2 assetmanager;
- assetmanager.SetApkAssets({framework_apk.get(), basic_apk.get()});
-
- ResTable_config device_config;
- memset(&device_config, 0, sizeof(device_config));
- device_config.language[0] = 'e';
- device_config.language[1] = 'n';
- device_config.country[0] = 'U';
- device_config.country[1] = 'S';
- device_config.orientation = ResTable_config::ORIENTATION_PORT;
- device_config.smallestScreenWidthDp = 700;
- device_config.screenWidthDp = 700;
- device_config.screenHeightDp = 1024;
- device_config.sdkVersion = 27;
-
- Res_value value;
- ResTable_config config;
- uint32_t flags = 0u;
- ApkAssetsCookie cookie =
- assetmanager.GetResource(basic::R::layout::layoutt, false /*may_be_bag*/,
- 0u /*density_override*/, &value, &config, &flags);
- if (cookie == kInvalidCookie) {
- state.SkipWithError("failed to find R.layout.layout");
- return;
- }
-
- size_t len = 0u;
- const char* layout_path =
- assetmanager.GetStringPoolForCookie(cookie)->string8At(value.data, &len);
- if (layout_path == nullptr || len == 0u) {
- state.SkipWithError("failed to lookup layout path");
- return;
- }
-
- std::unique_ptr<Asset> asset = assetmanager.OpenNonAsset(
- StringPiece(layout_path, len).to_string(), cookie, Asset::ACCESS_BUFFER);
- if (asset == nullptr) {
- state.SkipWithError("failed to load layout");
- return;
- }
-
- ResXMLTree xml_tree;
- if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
- state.SkipWithError("corrupt xml layout");
- return;
- }
-
- // Skip to the first tag.
- while (xml_tree.next() != ResXMLParser::START_TAG) {
- }
-
- std::unique_ptr<Theme> theme = assetmanager.NewTheme();
- theme->ApplyStyle(Theme_Material_Light);
-
- std::array<uint32_t, 92> attrs{
- {0x0101000e, 0x01010034, 0x01010095, 0x01010096, 0x01010097, 0x01010098, 0x01010099,
- 0x0101009a, 0x0101009b, 0x010100ab, 0x010100af, 0x010100b0, 0x010100b1, 0x0101011f,
- 0x01010120, 0x0101013f, 0x01010140, 0x0101014e, 0x0101014f, 0x01010150, 0x01010151,
- 0x01010152, 0x01010153, 0x01010154, 0x01010155, 0x01010156, 0x01010157, 0x01010158,
- 0x01010159, 0x0101015a, 0x0101015b, 0x0101015c, 0x0101015d, 0x0101015e, 0x0101015f,
- 0x01010160, 0x01010161, 0x01010162, 0x01010163, 0x01010164, 0x01010165, 0x01010166,
- 0x01010167, 0x01010168, 0x01010169, 0x0101016a, 0x0101016b, 0x0101016c, 0x0101016d,
- 0x0101016e, 0x0101016f, 0x01010170, 0x01010171, 0x01010217, 0x01010218, 0x0101021d,
- 0x01010220, 0x01010223, 0x01010224, 0x01010264, 0x01010265, 0x01010266, 0x010102c5,
- 0x010102c6, 0x010102c7, 0x01010314, 0x01010315, 0x01010316, 0x0101035e, 0x0101035f,
- 0x01010362, 0x01010374, 0x0101038c, 0x01010392, 0x01010393, 0x010103ac, 0x0101045d,
- 0x010104b6, 0x010104b7, 0x010104d6, 0x010104d7, 0x010104dd, 0x010104de, 0x010104df,
- 0x01010535, 0x01010536, 0x01010537, 0x01010538, 0x01010546, 0x01010567, 0x011100c9,
- 0x011100ca}};
-
- std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
- std::array<uint32_t, attrs.size() + 1> indices;
- while (state.KeepRunning()) {
- ApplyStyle(theme.get(), &xml_tree, 0x01010084u /*def_style_attr*/, 0u /*def_style_res*/,
- attrs.data(), attrs.size(), values.data(), indices.data());
- }
-}
-BENCHMARK(BM_ApplyStyleFramework);
-
-} // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp
index cc30537..2d73ce8 100644
--- a/libs/androidfw/tests/AttributeResolution_test.cpp
+++ b/libs/androidfw/tests/AttributeResolution_test.cpp
@@ -21,7 +21,6 @@
#include "android-base/file.h"
#include "android-base/logging.h"
#include "android-base/macros.h"
-#include "androidfw/AssetManager2.h"
#include "TestHelpers.h"
#include "data/styles/R.h"
@@ -33,14 +32,15 @@
class AttributeResolutionTest : public ::testing::Test {
public:
virtual void SetUp() override {
- styles_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
- ASSERT_NE(nullptr, styles_assets_);
- assetmanager_.SetApkAssets({styles_assets_.get()});
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(
+ GetTestDataPath() + "/styles/styles.apk", "resources.arsc", &contents));
+ ASSERT_EQ(NO_ERROR, table_.add(contents.data(), contents.size(),
+ 1 /*cookie*/, true /*copyData*/));
}
protected:
- std::unique_ptr<const ApkAssets> styles_assets_;
- AssetManager2 assetmanager_;
+ ResTable table_;
};
class AttributeResolutionXmlTest : public AttributeResolutionTest {
@@ -48,12 +48,13 @@
virtual void SetUp() override {
AttributeResolutionTest::SetUp();
- std::unique_ptr<Asset> asset =
- assetmanager_.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER);
- ASSERT_NE(nullptr, asset);
+ std::string contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk",
+ "res/layout/layout.xml", &contents));
- ASSERT_EQ(NO_ERROR,
- xml_parser_.setTo(asset->getBuffer(true), asset->getLength(), true /*copyData*/));
+ ASSERT_EQ(NO_ERROR, xml_parser_.setTo(contents.data(), contents.size(),
+ true /*copyData*/));
// Skip to the first tag.
while (xml_parser_.next() != ResXMLParser::START_TAG) {
@@ -65,14 +66,14 @@
};
TEST_F(AttributeResolutionTest, Theme) {
- std::unique_ptr<Theme> theme = assetmanager_.NewTheme();
- ASSERT_TRUE(theme->ApplyStyle(R::style::StyleTwo));
+ ResTable::Theme theme(table_);
+ ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
R::attr::attr_four, R::attr::attr_empty}};
std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
- ASSERT_TRUE(ResolveAttrs(theme.get(), 0u /*def_style_attr*/, 0u /*def_style_res*/,
+ ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/,
nullptr /*src_values*/, 0 /*src_values_length*/, attrs.data(),
attrs.size(), values.data(), nullptr /*out_indices*/));
@@ -125,8 +126,8 @@
R::attr::attr_four, R::attr::attr_empty}};
std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
- ASSERT_TRUE(RetrieveAttributes(&assetmanager_, &xml_parser_, attrs.data(), attrs.size(),
- values.data(), nullptr /*out_indices*/));
+ ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs.data(), attrs.size(), values.data(),
+ nullptr /*out_indices*/));
uint32_t* values_cursor = values.data();
EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
@@ -170,15 +171,15 @@
}
TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
- std::unique_ptr<Theme> theme = assetmanager_.NewTheme();
- ASSERT_TRUE(theme->ApplyStyle(R::style::StyleTwo));
+ ResTable::Theme theme(table_);
+ ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
std::array<uint32_t, 6> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
R::attr::attr_four, R::attr::attr_five, R::attr::attr_empty}};
std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
std::array<uint32_t, attrs.size() + 1> indices;
- ApplyStyle(theme.get(), &xml_parser_, 0u /*def_style_attr*/, 0u /*def_style_res*/, attrs.data(),
+ ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs.data(),
attrs.size(), values.data(), indices.data());
const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
diff --git a/libs/androidfw/tests/BenchmarkHelpers.cpp b/libs/androidfw/tests/BenchmarkHelpers.cpp
index faddfe5..7149bee 100644
--- a/libs/androidfw/tests/BenchmarkHelpers.cpp
+++ b/libs/androidfw/tests/BenchmarkHelpers.cpp
@@ -33,21 +33,19 @@
}
}
- // Make sure to force creation of the ResTable first, or else the configuration doesn't get set.
- const ResTable& table = assetmanager.getResources(true);
if (config != nullptr) {
assetmanager.setConfiguration(*config);
}
+ const ResTable& table = assetmanager.getResources(true);
+
Res_value value;
ResTable_config selected_config;
uint32_t flags;
- uint32_t last_ref = 0u;
while (state.KeepRunning()) {
- ssize_t block = table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
- &selected_config);
- table.resolveReference(&value, block, &last_ref, &flags, &selected_config);
+ table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
+ &selected_config);
}
}
@@ -74,12 +72,10 @@
Res_value value;
ResTable_config selected_config;
uint32_t flags;
- uint32_t last_id = 0u;
while (state.KeepRunning()) {
- ApkAssetsCookie cookie = assetmanager.GetResource(
- resid, false /* may_be_bag */, 0u /* density_override */, &value, &selected_config, &flags);
- assetmanager.ResolveReference(cookie, &value, &selected_config, &flags, &last_id);
+ assetmanager.GetResource(resid, false /* may_be_bag */, 0u /* density_override */, &value,
+ &selected_config, &flags);
}
}
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index bedebd6..37ddafb 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -16,8 +16,6 @@
#include "androidfw/LoadedArsc.h"
-#include "androidfw/ResourceUtils.h"
-
#include "TestHelpers.h"
#include "data/basic/R.h"
#include "data/libclient/R.h"
@@ -29,13 +27,6 @@
namespace libclient = com::android::libclient;
namespace sparse = com::android::sparse;
-using ::testing::Eq;
-using ::testing::Ge;
-using ::testing::IsNull;
-using ::testing::NotNull;
-using ::testing::SizeIs;
-using ::testing::StrEq;
-
namespace android {
TEST(LoadedArscTest, LoadSinglePackageArsc) {
@@ -44,24 +35,39 @@
&contents));
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_THAT(loaded_arsc, NotNull());
+ ASSERT_NE(nullptr, loaded_arsc);
- const LoadedPackage* package =
- loaded_arsc->GetPackageById(get_package_id(app::R::string::string_one));
- ASSERT_THAT(package, NotNull());
- EXPECT_THAT(package->GetPackageName(), StrEq("com.android.app"));
- EXPECT_THAT(package->GetPackageId(), Eq(0x7f));
+ const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
+ ASSERT_EQ(1u, packages.size());
+ EXPECT_EQ(std::string("com.android.app"), packages[0]->GetPackageName());
+ EXPECT_EQ(0x7f, packages[0]->GetPackageId());
- const uint8_t type_index = get_type_id(app::R::string::string_one) - 1;
- const uint16_t entry_index = get_entry_id(app::R::string::string_one);
+ ResTable_config config;
+ memset(&config, 0, sizeof(config));
+ config.sdkVersion = 24;
- const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
- ASSERT_THAT(type_spec, NotNull());
- ASSERT_THAT(type_spec->type_count, Ge(1u));
+ FindEntryResult entry;
- const ResTable_type* type = type_spec->types[0];
- ASSERT_THAT(type, NotNull());
- ASSERT_THAT(LoadedPackage::GetEntry(type, entry_index), NotNull());
+ ASSERT_TRUE(loaded_arsc->FindEntry(app::R::string::string_one, config, &entry));
+ ASSERT_NE(nullptr, entry.entry);
+}
+
+TEST(LoadedArscTest, FindDefaultEntry) {
+ std::string contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
+
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
+ ASSERT_NE(nullptr, loaded_arsc);
+
+ ResTable_config desired_config;
+ memset(&desired_config, 0, sizeof(desired_config));
+ desired_config.language[0] = 'd';
+ desired_config.language[1] = 'e';
+
+ FindEntryResult entry;
+ ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test1, desired_config, &entry));
+ ASSERT_NE(nullptr, entry.entry);
}
TEST(LoadedArscTest, LoadSparseEntryApp) {
@@ -70,22 +76,15 @@
&contents));
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_THAT(loaded_arsc, NotNull());
+ ASSERT_NE(nullptr, loaded_arsc);
- const LoadedPackage* package =
- loaded_arsc->GetPackageById(get_package_id(sparse::R::integer::foo_9));
- ASSERT_THAT(package, NotNull());
+ ResTable_config config;
+ memset(&config, 0, sizeof(config));
+ config.sdkVersion = 26;
- const uint8_t type_index = get_type_id(sparse::R::integer::foo_9) - 1;
- const uint16_t entry_index = get_entry_id(sparse::R::integer::foo_9);
-
- const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
- ASSERT_THAT(type_spec, NotNull());
- ASSERT_THAT(type_spec->type_count, Ge(1u));
-
- const ResTable_type* type = type_spec->types[0];
- ASSERT_THAT(type, NotNull());
- ASSERT_THAT(LoadedPackage::GetEntry(type, entry_index), NotNull());
+ FindEntryResult entry;
+ ASSERT_TRUE(loaded_arsc->FindEntry(sparse::R::integer::foo_9, config, &entry));
+ ASSERT_NE(nullptr, entry.entry);
}
TEST(LoadedArscTest, LoadSharedLibrary) {
@@ -94,13 +93,14 @@
&contents));
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_THAT(loaded_arsc, NotNull());
+ ASSERT_NE(nullptr, loaded_arsc);
const auto& packages = loaded_arsc->GetPackages();
- ASSERT_THAT(packages, SizeIs(1u));
+ ASSERT_EQ(1u, packages.size());
+
EXPECT_TRUE(packages[0]->IsDynamic());
- EXPECT_THAT(packages[0]->GetPackageName(), StrEq("com.android.lib_one"));
- EXPECT_THAT(packages[0]->GetPackageId(), Eq(0));
+ EXPECT_EQ(std::string("com.android.lib_one"), packages[0]->GetPackageName());
+ EXPECT_EQ(0, packages[0]->GetPackageId());
const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
@@ -114,23 +114,25 @@
"resources.arsc", &contents));
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_THAT(loaded_arsc, NotNull());
+ ASSERT_NE(nullptr, loaded_arsc);
const auto& packages = loaded_arsc->GetPackages();
- ASSERT_THAT(packages, SizeIs(1u));
+ ASSERT_EQ(1u, packages.size());
+
EXPECT_FALSE(packages[0]->IsDynamic());
- EXPECT_THAT(packages[0]->GetPackageName(), StrEq("com.android.libclient"));
- EXPECT_THAT(packages[0]->GetPackageId(), Eq(0x7f));
+ EXPECT_EQ(std::string("com.android.libclient"), packages[0]->GetPackageName());
+ EXPECT_EQ(0x7f, packages[0]->GetPackageId());
const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
// The library has two dependencies.
- ASSERT_THAT(dynamic_pkg_map, SizeIs(2u));
- EXPECT_THAT(dynamic_pkg_map[0].package_name, StrEq("com.android.lib_one"));
- EXPECT_THAT(dynamic_pkg_map[0].package_id, Eq(0x02));
+ ASSERT_EQ(2u, dynamic_pkg_map.size());
- EXPECT_THAT(dynamic_pkg_map[1].package_name, StrEq("com.android.lib_two"));
- EXPECT_THAT(dynamic_pkg_map[1].package_id, Eq(0x03));
+ EXPECT_EQ(std::string("com.android.lib_one"), dynamic_pkg_map[0].package_name);
+ EXPECT_EQ(0x02, dynamic_pkg_map[0].package_id);
+
+ EXPECT_EQ(std::string("com.android.lib_two"), dynamic_pkg_map[1].package_name);
+ EXPECT_EQ(0x03, dynamic_pkg_map[1].package_id);
}
TEST(LoadedArscTest, LoadAppAsSharedLibrary) {
@@ -141,12 +143,13 @@
std::unique_ptr<const LoadedArsc> loaded_arsc =
LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/,
true /*load_as_shared_library*/);
- ASSERT_THAT(loaded_arsc, NotNull());
+ ASSERT_NE(nullptr, loaded_arsc);
const auto& packages = loaded_arsc->GetPackages();
- ASSERT_THAT(packages, SizeIs(1u));
+ ASSERT_EQ(1u, packages.size());
+
EXPECT_TRUE(packages[0]->IsDynamic());
- EXPECT_THAT(packages[0]->GetPackageId(), Eq(0x7f));
+ EXPECT_EQ(0x7f, packages[0]->GetPackageId());
}
TEST(LoadedArscTest, LoadFeatureSplit) {
@@ -154,27 +157,21 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk", "resources.arsc",
&contents));
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_THAT(loaded_arsc, NotNull());
+ ASSERT_NE(nullptr, loaded_arsc);
- const LoadedPackage* package =
- loaded_arsc->GetPackageById(get_package_id(basic::R::string::test3));
- ASSERT_THAT(package, NotNull());
+ ResTable_config desired_config;
+ memset(&desired_config, 0, sizeof(desired_config));
- uint8_t type_index = get_type_id(basic::R::string::test3) - 1;
- uint8_t entry_index = get_entry_id(basic::R::string::test3);
-
- const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
- ASSERT_THAT(type_spec, NotNull());
- ASSERT_THAT(type_spec->type_count, Ge(1u));
- ASSERT_THAT(type_spec->types[0], NotNull());
+ FindEntryResult entry;
+ ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test3, desired_config, &entry));
size_t len;
- const char16_t* type_name16 =
- package->GetTypeStringPool()->stringAt(type_spec->type_spec->id - 1, &len);
- ASSERT_THAT(type_name16, NotNull());
- EXPECT_THAT(util::Utf16ToUtf8(StringPiece16(type_name16, len)), StrEq("string"));
+ const char16_t* type_name16 = entry.type_string_ref.string16(&len);
+ ASSERT_NE(nullptr, type_name16);
+ ASSERT_NE(0u, len);
- ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], entry_index), NotNull());
+ std::string type_name = util::Utf16ToUtf8(StringPiece16(type_name16, len));
+ EXPECT_EQ(std::string("string"), type_name);
}
class MockLoadedIdmap : public LoadedIdmap {
@@ -202,33 +199,23 @@
};
TEST(LoadedArscTest, LoadOverlay) {
- std::string contents;
+ std::string contents, overlay_contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk", "resources.arsc",
- &contents));
+ &overlay_contents));
MockLoadedIdmap loaded_idmap;
std::unique_ptr<const LoadedArsc> loaded_arsc =
- LoadedArsc::Load(StringPiece(contents), &loaded_idmap);
- ASSERT_THAT(loaded_arsc, NotNull());
+ LoadedArsc::Load(StringPiece(overlay_contents), &loaded_idmap);
+ ASSERT_NE(nullptr, loaded_arsc);
- const LoadedPackage* package = loaded_arsc->GetPackageById(0x08u);
- ASSERT_THAT(package, NotNull());
+ ResTable_config desired_config;
+ memset(&desired_config, 0, sizeof(desired_config));
- const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0x03u - 1);
- ASSERT_THAT(type_spec, NotNull());
- ASSERT_THAT(type_spec->type_count, Ge(1u));
- ASSERT_THAT(type_spec->types[0], NotNull());
-
- // The entry being overlaid doesn't exist at the original entry index.
- ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0001u), IsNull());
-
- // Since this is an overlay, the actual entry ID must be mapped.
- ASSERT_THAT(type_spec->idmap_entries, NotNull());
- uint16_t target_entry_id = 0u;
- ASSERT_TRUE(LoadedIdmap::Lookup(type_spec->idmap_entries, 0x0001u, &target_entry_id));
- ASSERT_THAT(target_entry_id, Eq(0x0u));
- ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0000), NotNull());
+ FindEntryResult entry;
+ ASSERT_TRUE(loaded_arsc->FindEntry(0x08030001u, desired_config, &entry));
}
// structs with size fields (like Res_value, ResTable_entry) should be
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index df0c642..43a9955 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -20,7 +20,6 @@
#include <string>
#include "androidfw/ResourceTypes.h"
-#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "CommonHelpers.h"
diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h
index b7e814f..94a2a14 100644
--- a/libs/androidfw/tests/data/basic/R.h
+++ b/libs/androidfw/tests/data/basic/R.h
@@ -34,7 +34,6 @@
struct layout {
enum : uint32_t {
main = 0x7f020000,
- layoutt = 0x7f020001,
};
};
@@ -56,7 +55,6 @@
number2 = 0x7f040001,
ref1 = 0x7f040002,
ref2 = 0x7f040003,
- deep_ref = 0x7f040004,
// From feature
number3 = 0x80030000,
diff --git a/libs/androidfw/tests/data/basic/basic.apk b/libs/androidfw/tests/data/basic/basic.apk
index 1733b6a..18ef75e 100644
--- a/libs/androidfw/tests/data/basic/basic.apk
+++ b/libs/androidfw/tests/data/basic/basic.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml
index b343562..6c47459 100644
--- a/libs/androidfw/tests/data/basic/res/values/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values/values.xml
@@ -22,7 +22,6 @@
<attr name="attr2" format="reference|integer" />
<public type="layout" name="main" id="0x7f020000" />
- <public type="layout" name="layout" id="0x7f020001" />
<public type="string" name="test1" id="0x7f030000" />
<string name="test1">test1</string>
@@ -44,18 +43,6 @@
<public type="integer" name="ref2" id="0x7f040003" />
<integer name="ref2">12000</integer>
- <public type="integer" name="deep_ref" id="0x7f040004" />
- <integer name="deep_ref">@integer/deep_ref_1</integer>
- <integer name="deep_ref_1">@integer/deep_ref_2</integer>
- <integer name="deep_ref_2">@integer/deep_ref_3</integer>
- <integer name="deep_ref_3">@integer/deep_ref_4</integer>
- <integer name="deep_ref_4">@integer/deep_ref_5</integer>
- <integer name="deep_ref_5">@integer/deep_ref_6</integer>
- <integer name="deep_ref_6">@integer/deep_ref_7</integer>
- <integer name="deep_ref_7">@integer/deep_ref_8</integer>
- <integer name="deep_ref_8">@integer/deep_ref_9</integer>
- <integer name="deep_ref_9">100</integer>
-
<public type="style" name="Theme1" id="0x7f050000" />
<style name="Theme1">
<item name="com.android.basic:attr1">100</item>
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 17f9b7c..3323bce 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -138,6 +138,7 @@
srcs: [
"hwui/AnimatedImageDrawable.cpp",
+ "hwui/AnimatedImageThread.cpp",
"hwui/Bitmap.cpp",
"font/CacheTexture.cpp",
"font/Font.cpp",
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 3d2c252..55f4d89 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -507,12 +507,20 @@
getOutline().getAlpha() != 0.0f;
}
- SkColor getShadowColor() const {
- return mPrimitiveFields.mShadowColor;
+ SkColor getSpotShadowColor() const {
+ return mPrimitiveFields.mSpotShadowColor;
}
- bool setShadowColor(SkColor shadowColor) {
- return RP_SET(mPrimitiveFields.mShadowColor, shadowColor);
+ bool setSpotShadowColor(SkColor shadowColor) {
+ return RP_SET(mPrimitiveFields.mSpotShadowColor, shadowColor);
+ }
+
+ SkColor getAmbientShadowColor() const {
+ return mPrimitiveFields.mAmbientShadowColor;
+ }
+
+ bool setAmbientShadowColor(SkColor shadowColor) {
+ return RP_SET(mPrimitiveFields.mAmbientShadowColor, shadowColor);
}
bool fitsOnLayer() const {
@@ -538,7 +546,8 @@
int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
int mWidth = 0, mHeight = 0;
int mClippingFlags = CLIP_TO_BOUNDS;
- SkColor mShadowColor = SK_ColorBLACK;
+ SkColor mSpotShadowColor = SK_ColorBLACK;
+ SkColor mAmbientShadowColor = SK_ColorBLACK;
float mAlpha = 1;
float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
float mElevation = 0;
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index e01bf3d..5356d3b 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -15,21 +15,21 @@
*/
#include "AnimatedImageDrawable.h"
+#include "AnimatedImageThread.h"
-#include "thread/Task.h"
-#include "thread/TaskManager.h"
-#include "thread/TaskProcessor.h"
#include "utils/TraceUtils.h"
#include <SkPicture.h>
#include <SkRefCnt.h>
-#include <SkTime.h>
#include <SkTLazy.h>
+#include <SkTime.h>
namespace android {
AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage)
- : mSkAnimatedImage(std::move(animatedImage)) { }
+ : mSkAnimatedImage(std::move(animatedImage)) {
+ mTimeToShowNextSnapshot = mSkAnimatedImage->currentFrameDuration();
+}
void AnimatedImageDrawable::syncProperties() {
mAlpha = mStagingAlpha;
@@ -37,88 +37,81 @@
}
bool AnimatedImageDrawable::start() {
- SkAutoExclusive lock(mLock);
- if (mSkAnimatedImage->isRunning()) {
+ if (mRunning) {
return false;
}
- if (!mSnapshot) {
- mSnapshot.reset(mSkAnimatedImage->newPictureSnapshot());
- }
+ // This will trigger a reset.
+ mFinished = true;
- // While stopped, update() does not decode, but it does advance the time.
- // This prevents us from skipping ahead when we resume.
- const double currentTime = SkTime::GetMSecs();
- mSkAnimatedImage->update(currentTime);
- mSkAnimatedImage->start();
- return mSkAnimatedImage->isRunning();
+ mRunning = true;
+ return true;
}
void AnimatedImageDrawable::stop() {
- SkAutoExclusive lock(mLock);
- mSkAnimatedImage->stop();
+ mRunning = false;
}
bool AnimatedImageDrawable::isRunning() {
- return mSkAnimatedImage->isRunning();
+ return mRunning;
}
-// This is really a Task<void> but that doesn't really work when Future<>
-// expects to be able to get/set a value
-class AnimatedImageDrawable::AnimatedImageTask : public uirenderer::Task<bool> {
-public:
- AnimatedImageTask(AnimatedImageDrawable* animatedImageDrawable)
- : mAnimatedImageDrawable(sk_ref_sp(animatedImageDrawable)) {}
-
- sk_sp<AnimatedImageDrawable> mAnimatedImageDrawable;
- bool mIsCompleted = false;
-};
-
-class AnimatedImageDrawable::AnimatedImageTaskProcessor : public uirenderer::TaskProcessor<bool> {
-public:
- explicit AnimatedImageTaskProcessor(uirenderer::TaskManager* taskManager)
- : uirenderer::TaskProcessor<bool>(taskManager) {}
- ~AnimatedImageTaskProcessor() {}
-
- virtual void onProcess(const sp<uirenderer::Task<bool>>& task) override {
- ATRACE_NAME("Updating AnimatedImageDrawables");
- AnimatedImageTask* t = static_cast<AnimatedImageTask*>(task.get());
- t->mAnimatedImageDrawable->update();
- t->mIsCompleted = true;
- task->setResult(true);
- };
-};
-
-void AnimatedImageDrawable::scheduleUpdate(uirenderer::TaskManager* taskManager) {
- if (!mSkAnimatedImage->isRunning()
- || (mDecodeTask.get() != nullptr && !mDecodeTask->mIsCompleted)) {
- return;
- }
-
- if (!mDecodeTaskProcessor.get()) {
- mDecodeTaskProcessor = new AnimatedImageTaskProcessor(taskManager);
- }
-
- // TODO get one frame ahead and only schedule updates when you need to replenish
- mDecodeTask = new AnimatedImageTask(this);
- mDecodeTaskProcessor->add(mDecodeTask);
+bool AnimatedImageDrawable::nextSnapshotReady() const {
+ return mNextSnapshot.valid() &&
+ mNextSnapshot.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
-void AnimatedImageDrawable::update() {
- SkAutoExclusive lock(mLock);
-
- if (!mSkAnimatedImage->isRunning()) {
- return;
- }
-
+// Only called on the RenderThread while UI thread is locked.
+bool AnimatedImageDrawable::isDirty() {
const double currentTime = SkTime::GetMSecs();
- if (currentTime >= mNextFrameTime) {
- mNextFrameTime = mSkAnimatedImage->update(currentTime);
- mSnapshot.reset(mSkAnimatedImage->newPictureSnapshot());
- mIsDirty = true;
+ const double lastWallTime = mLastWallTime;
+
+ mLastWallTime = currentTime;
+ if (!mRunning) {
+ mDidDraw = false;
+ return false;
}
+
+ std::unique_lock lock{mSwapLock};
+ if (mDidDraw) {
+ mCurrentTime += currentTime - lastWallTime;
+ mDidDraw = false;
+ }
+
+ if (!mNextSnapshot.valid()) {
+ // Need to trigger onDraw in order to start decoding the next frame.
+ return true;
+ }
+
+ return nextSnapshotReady() && mCurrentTime >= mTimeToShowNextSnapshot;
}
+// Only called on the AnimatedImageThread.
+AnimatedImageDrawable::Snapshot AnimatedImageDrawable::decodeNextFrame() {
+ Snapshot snap;
+ {
+ std::unique_lock lock{mImageLock};
+ snap.mDuration = mSkAnimatedImage->decodeNextFrame();
+ snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot());
+ }
+
+ return snap;
+}
+
+// Only called on the AnimatedImageThread.
+AnimatedImageDrawable::Snapshot AnimatedImageDrawable::reset() {
+ Snapshot snap;
+ {
+ std::unique_lock lock{mImageLock};
+ mSkAnimatedImage->reset();
+ snap.mPic.reset(mSkAnimatedImage->newPictureSnapshot());
+ snap.mDuration = mSkAnimatedImage->currentFrameDuration();
+ }
+
+ return snap;
+}
+
+// Only called on the RenderThread.
void AnimatedImageDrawable::onDraw(SkCanvas* canvas) {
SkTLazy<SkPaint> lazyPaint;
if (mAlpha != SK_AlphaOPAQUE || mColorFilter.get()) {
@@ -128,25 +121,71 @@
lazyPaint.get()->setFilterQuality(kLow_SkFilterQuality);
}
- SkAutoExclusive lock(mLock);
- if (mSnapshot) {
- canvas->drawPicture(mSnapshot, nullptr, lazyPaint.getMaybeNull());
- } else {
- // TODO: we could potentially keep the cached surface around if there is a paint and we know
- // the drawable is attached to the view system
+ mDidDraw = true;
+
+ bool drewDirectly = false;
+ if (!mSnapshot.mPic) {
+ // 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());
}
+
+ std::unique_lock lock{mImageLock};
mSkAnimatedImage->draw(canvas);
+ drewDirectly = true;
}
- mIsDirty = false;
+ if (mRunning && mFinished) {
+ auto& thread = uirenderer::AnimatedImageThread::getInstance();
+ mNextSnapshot = thread.reset(sk_ref_sp(this));
+ mFinished = false;
+ }
+
+ bool finalFrame = false;
+ if (mRunning && nextSnapshotReady()) {
+ std::unique_lock lock{mSwapLock};
+ if (mCurrentTime >= mTimeToShowNextSnapshot) {
+ mSnapshot = mNextSnapshot.get();
+ const double timeToShowCurrentSnap = mTimeToShowNextSnapshot;
+ if (mSnapshot.mDuration == SkAnimatedImage::kFinished) {
+ finalFrame = true;
+ mRunning = false;
+ mFinished = true;
+ } else {
+ mTimeToShowNextSnapshot += mSnapshot.mDuration;
+ if (mCurrentTime >= mTimeToShowNextSnapshot) {
+ // This would mean showing the current frame very briefly. It's
+ // possible that not being displayed for a time resulted in
+ // mCurrentTime being far ahead. Prevent showing many frames
+ // rapidly by going back to the beginning of this frame time.
+ mCurrentTime = timeToShowCurrentSnap;
+ }
+ }
+ }
+ }
+
+ if (mRunning && !mNextSnapshot.valid()) {
+ auto& thread = uirenderer::AnimatedImageThread::getInstance();
+ mNextSnapshot = thread.decodeNextFrame(sk_ref_sp(this));
+ }
+
+ if (!drewDirectly) {
+ // No other thread will modify mCurrentSnap so this should be safe to
+ // use without locking.
+ canvas->drawPicture(mSnapshot.mPic, nullptr, lazyPaint.getMaybeNull());
+ }
+
+ if (finalFrame) {
+ if (mEndListener) {
+ mEndListener->onAnimationEnd();
+ mEndListener = nullptr;
+ }
+ }
}
double AnimatedImageDrawable::drawStaging(SkCanvas* canvas) {
- // update the drawable with the current time
- double nextUpdate = mSkAnimatedImage->update(SkTime::GetMSecs());
SkAutoCanvasRestore acr(canvas, false);
if (mStagingAlpha != SK_AlphaOPAQUE || mStagingColorFilter.get()) {
SkPaint paint;
@@ -154,8 +193,59 @@
paint.setColorFilter(mStagingColorFilter);
canvas->saveLayer(mSkAnimatedImage->getBounds(), &paint);
}
- canvas->drawDrawable(mSkAnimatedImage.get());
- return nextUpdate;
+
+ if (mFinished && !mRunning) {
+ // Continue drawing the last frame, and return 0 to indicate no need to
+ // redraw.
+ std::unique_lock lock{mImageLock};
+ canvas->drawDrawable(mSkAnimatedImage.get());
+ return 0.0;
+ }
+
+ bool update = false;
+ {
+ const double currentTime = SkTime::GetMSecs();
+ std::unique_lock lock{mSwapLock};
+ // mLastWallTime starts off at 0. If it is still 0, just update it to
+ // the current time and avoid updating
+ if (mLastWallTime == 0.0) {
+ mCurrentTime = currentTime;
+ } else if (mRunning) {
+ if (mFinished) {
+ mCurrentTime = currentTime;
+ {
+ std::unique_lock lock{mImageLock};
+ mSkAnimatedImage->reset();
+ }
+ mTimeToShowNextSnapshot = currentTime + mSkAnimatedImage->currentFrameDuration();
+ } else {
+ mCurrentTime += currentTime - mLastWallTime;
+ update = mCurrentTime >= mTimeToShowNextSnapshot;
+ }
+ }
+ mLastWallTime = currentTime;
+ }
+
+ double duration = 0.0;
+ {
+ std::unique_lock lock{mImageLock};
+ if (update) {
+ duration = mSkAnimatedImage->decodeNextFrame();
+ }
+
+ canvas->drawDrawable(mSkAnimatedImage.get());
+ }
+
+ std::unique_lock lock{mSwapLock};
+ if (update) {
+ if (duration == SkAnimatedImage::kFinished) {
+ mRunning = false;
+ mFinished = true;
+ } else {
+ mTimeToShowNextSnapshot += duration;
+ }
+ }
+ return mTimeToShowNextSnapshot;
}
-}; // namespace android
+} // namespace android
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h
index 1ebb585..9d84ed5 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.h
+++ b/libs/hwui/hwui/AnimatedImageDrawable.h
@@ -17,76 +17,124 @@
#pragma once
#include <cutils/compiler.h>
+#include <utils/Macros.h>
#include <utils/RefBase.h>
#include <SkAnimatedImage.h>
#include <SkCanvas.h>
#include <SkColorFilter.h>
#include <SkDrawable.h>
-#include <SkMutex.h>
+#include <SkPicture.h>
-class SkPicture;
+#include <future>
+#include <mutex>
namespace android {
-namespace uirenderer {
-class TaskManager;
-}
+class OnAnimationEndListener {
+public:
+ virtual ~OnAnimationEndListener() {}
+
+ virtual void onAnimationEnd() = 0;
+};
/**
- * Native component of android.graphics.drawable.AnimatedImageDrawables.java. This class can be
- * drawn into Canvas.h and maintains the state needed to drive the animation from the RenderThread.
+ * Native component of android.graphics.drawable.AnimatedImageDrawables.java.
+ * This class can be drawn into Canvas.h and maintains the state needed to drive
+ * the animation from the RenderThread.
*/
class ANDROID_API AnimatedImageDrawable : public SkDrawable {
public:
AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage);
/**
- * This returns true if the animation has updated and signals that the next draw will contain
- * new content.
+ * This updates the internal time and returns true if the animation needs
+ * to be redrawn.
+ *
+ * This is called on RenderThread, while the UI thread is locked.
*/
- bool isDirty() const { return mIsDirty; }
+ bool isDirty();
int getStagingAlpha() const { return mStagingAlpha; }
void setStagingAlpha(int alpha) { mStagingAlpha = alpha; }
void setStagingColorFilter(sk_sp<SkColorFilter> filter) { mStagingColorFilter = filter; }
void syncProperties();
- virtual SkRect onGetBounds() override {
- return mSkAnimatedImage->getBounds();
- }
+ virtual SkRect onGetBounds() override { return mSkAnimatedImage->getBounds(); }
+ // Draw to software canvas, and return time to next draw.
double drawStaging(SkCanvas* canvas);
- // Returns true if the animation was started; false otherwise (e.g. it was already running)
+ // Returns true if the animation was started; false otherwise (e.g. it was
+ // already running)
bool start();
void stop();
bool isRunning();
+ void setRepetitionCount(int count) { mSkAnimatedImage->setRepetitionCount(count); }
- void scheduleUpdate(uirenderer::TaskManager* taskManager);
+ void setOnAnimationEndListener(std::unique_ptr<OnAnimationEndListener> listener) {
+ mEndListener = std::move(listener);
+ }
+
+ void markInvisible() { mDidDraw = false; }
+
+ struct Snapshot {
+ sk_sp<SkPicture> mPic;
+ int mDuration;
+
+ Snapshot() = default;
+
+ Snapshot(Snapshot&&) = default;
+ Snapshot& operator=(Snapshot&&) = default;
+
+ PREVENT_COPY_AND_ASSIGN(Snapshot);
+ };
+
+ // These are only called on AnimatedImageThread.
+ Snapshot decodeNextFrame();
+ Snapshot reset();
protected:
virtual void onDraw(SkCanvas* canvas) override;
private:
- void update();
-
sk_sp<SkAnimatedImage> mSkAnimatedImage;
- sk_sp<SkPicture> mSnapshot;
- SkMutex mLock;
+ bool mRunning = false;
+ bool mFinished = false;
+
+ // A snapshot of the current frame to draw.
+ Snapshot mSnapshot;
+
+ std::future<Snapshot> mNextSnapshot;
+
+ bool nextSnapshotReady() const;
+
+ // When to switch from mSnapshot to mNextSnapshot.
+ double mTimeToShowNextSnapshot = 0.0;
+
+ // The current time for the drawable itself.
+ double mCurrentTime = 0.0;
+
+ // The wall clock of the last time we called isDirty.
+ double mLastWallTime = 0.0;
+
+ // Whether we drew since the last call to isDirty.
+ bool mDidDraw = false;
+
+ // Locked when assigning snapshots and times. Operations while this is held
+ // should be short.
+ std::mutex mSwapLock;
+
+ // Locked when mSkAnimatedImage is being updated or drawn.
+ std::mutex mImageLock;
int mStagingAlpha = SK_AlphaOPAQUE;
sk_sp<SkColorFilter> mStagingColorFilter;
int mAlpha = SK_AlphaOPAQUE;
sk_sp<SkColorFilter> mColorFilter;
- double mNextFrameTime = 0.0;
- bool mIsDirty = false;
- class AnimatedImageTask;
- class AnimatedImageTaskProcessor;
- sp<AnimatedImageTask> mDecodeTask;
- sp<AnimatedImageTaskProcessor> mDecodeTaskProcessor;
+ std::unique_ptr<OnAnimationEndListener> mEndListener;
};
-}; // namespace android
+} // namespace android
diff --git a/libs/hwui/hwui/AnimatedImageThread.cpp b/libs/hwui/hwui/AnimatedImageThread.cpp
new file mode 100644
index 0000000..c899003
--- /dev/null
+++ b/libs/hwui/hwui/AnimatedImageThread.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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 "AnimatedImageThread.h"
+
+#include <sys/resource.h>
+
+namespace android {
+namespace uirenderer {
+
+AnimatedImageThread& AnimatedImageThread::getInstance() {
+ static AnimatedImageThread* sInstance = new AnimatedImageThread();
+ return *sInstance;
+}
+
+AnimatedImageThread::AnimatedImageThread() {
+ setpriority(PRIO_PROCESS, 0, PRIORITY_NORMAL + PRIORITY_MORE_FAVORABLE);
+ start("AnimatedImageThread");
+}
+
+std::future<AnimatedImageDrawable::Snapshot> AnimatedImageThread::decodeNextFrame(
+ const sk_sp<AnimatedImageDrawable>& drawable) {
+ return queue().async([drawable]() { return drawable->decodeNextFrame(); });
+}
+
+std::future<AnimatedImageDrawable::Snapshot> AnimatedImageThread::reset(
+ const sk_sp<AnimatedImageDrawable>& drawable) {
+ return queue().async([drawable]() { return drawable->reset(); });
+}
+
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/hwui/AnimatedImageThread.h b/libs/hwui/hwui/AnimatedImageThread.h
new file mode 100644
index 0000000..9e35374
--- /dev/null
+++ b/libs/hwui/hwui/AnimatedImageThread.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef ANIMATEDIMAGETHREAD_H_
+#define ANIMATEDIMAGETHREAD_H_
+
+#include "AnimatedImageDrawable.h"
+#include "thread/ThreadBase.h"
+
+#include <SkRefCnt.h>
+
+namespace android {
+
+namespace uirenderer {
+
+class AnimatedImageThread : private ThreadBase {
+ PREVENT_COPY_AND_ASSIGN(AnimatedImageThread);
+
+public:
+ static AnimatedImageThread& getInstance();
+
+ std::future<AnimatedImageDrawable::Snapshot> decodeNextFrame(
+ const sk_sp<AnimatedImageDrawable>&);
+ std::future<AnimatedImageDrawable::Snapshot> reset(const sk_sp<AnimatedImageDrawable>&);
+
+private:
+ AnimatedImageThread();
+};
+
+} // namespace uirenderer
+
+} // namespace android
+
+#endif // ANIMATEDIMAGETHREAD_H_
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index ba877d3..43f46ef 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -31,7 +31,7 @@
const Typeface* typeface) {
const Typeface* resolvedFace = Typeface::resolveDefault(typeface);
- minikin::MinikinPaint minikinPaint;
+ minikin::MinikinPaint minikinPaint(resolvedFace->fFontCollection);
/* Prepare minikin Paint */
minikinPaint.size =
paint->isLinearText() ? paint->getTextSize() : static_cast<int>(paint->getTextSize());
@@ -53,21 +53,20 @@
size_t count, size_t bufSize, minikin::MeasuredText* mt,
int mtOffset) {
minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface);
- const auto& fc = Typeface::resolveDefault(typeface)->fFontCollection;
minikin::Layout layout;
if (mt == nullptr) {
- layout.doLayout(buf, start, count, bufSize, bidiFlags, minikinPaint, fc);
+ layout.doLayout(buf, start, count, bufSize, bidiFlags, minikinPaint);
return layout;
}
if (mt->buildLayout(minikin::U16StringPiece(buf, bufSize),
minikin::Range(start, start + count),
- minikinPaint, fc, bidiFlags, mtOffset, &layout)) {
+ minikinPaint, bidiFlags, mtOffset, &layout)) {
return layout;
}
- layout.doLayout(buf, start, count, bufSize, bidiFlags, minikinPaint, fc);
+ layout.doLayout(buf, start, count, bufSize, bidiFlags, minikinPaint);
return layout;
}
@@ -75,10 +74,8 @@
const Typeface* typeface, const uint16_t* buf, size_t start,
size_t count, size_t bufSize, float* advances) {
minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface);
- const Typeface* resolvedTypeface = Typeface::resolveDefault(typeface);
return minikin::Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinPaint,
- resolvedTypeface->fFontCollection, advances,
- nullptr /* extent */);
+ advances, nullptr /* extent */);
}
bool MinikinUtils::hasVariationSelector(const Typeface* typeface, uint32_t codepoint, uint32_t vs) {
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 7b59ccf..25c51f2 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -111,6 +111,10 @@
}
}
+static SkColor multiplyAlpha(SkColor color, float alpha) {
+ return SkColorSetA(color, alpha * SkColorGetA(color));
+}
+
// copied from FrameBuilder::deferShadow
void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* caster) {
const RenderProperties& casterProperties = caster->getNodeProperties();
@@ -187,9 +191,11 @@
} else {
zParams = SkPoint3::Make(0, 0, casterProperties.getZ());
}
+ SkColor ambientColor = multiplyAlpha(casterProperties.getAmbientShadowColor(), ambientAlpha);
+ SkColor spotColor = multiplyAlpha(casterProperties.getSpotShadowColor(), spotAlpha);
SkShadowUtils::DrawShadow(
canvas, *casterPath, zParams, skiaLightPos, SkiaPipeline::getLightRadius(),
- ambientAlpha, spotAlpha, casterProperties.getShadowColor(),
+ ambientColor, spotColor,
casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
}
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index cf0b6a4..aa14699 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -98,8 +98,6 @@
isDirty = true;
}
if (animatedImage->isRunning()) {
- static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
- ->scheduleDeferredUpdate(animatedImage);
info.out.hasAnimations = true;
}
}
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 534782a..9db39d9 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -40,7 +40,6 @@
Vector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN};
SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) {
- mAnimatedImageDrawables.reserve(30);
mVectorDrawables.reserve(30);
}
@@ -327,15 +326,6 @@
ATRACE_NAME("flush commands");
surface->getCanvas()->flush();
-
- // TODO move to another method
- if (!mAnimatedImageDrawables.empty()) {
- ATRACE_NAME("Update AnimatedImageDrawables");
- for (auto animatedImage : mAnimatedImageDrawables) {
- animatedImage->scheduleUpdate(getTaskManager());
- }
- mAnimatedImageDrawables.clear();
- }
}
namespace {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index cc75e9c..3800194 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -55,12 +55,6 @@
std::vector<VectorDrawableRoot*>* getVectorDrawables() { return &mVectorDrawables; }
- void scheduleDeferredUpdate(AnimatedImageDrawable* imageDrawable) {
- mAnimatedImageDrawables.push_back(imageDrawable);
- }
-
- std::vector<AnimatedImageDrawable*>* getAnimatingImages() { return &mAnimatedImageDrawables; }
-
static void destroyLayer(RenderNode* node);
static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap);
@@ -144,11 +138,6 @@
*/
std::vector<VectorDrawableRoot*> mVectorDrawables;
- /**
- * populated by prepareTree with images with active animations
- */
- std::vector<AnimatedImageDrawable*> mAnimatedImageDrawables;
-
// Block of properties used only for debugging to record a SkPicture and save it in a file.
/**
* mCapturedFile is used to enforce we don't capture more than once for a given name (cause
diff --git a/libs/services/src/os/DropBoxManager.cpp b/libs/services/src/os/DropBoxManager.cpp
index f5685d9..c2907a6 100644
--- a/libs/services/src/os/DropBoxManager.cpp
+++ b/libs/services/src/os/DropBoxManager.cpp
@@ -208,6 +208,11 @@
Status
DropBoxManager::addFile(const String16& tag, int fd, int flags)
{
+ if (fd == -1) {
+ string message("invalid fd (-1) passed to to addFile");
+ ALOGW("DropboxManager: %s", message.c_str());
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, message.c_str());
+ }
Entry entry(tag, flags, fd);
return add(entry);
}
@@ -235,4 +240,3 @@
}
}} // namespace android::os
-
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 9db9d33..c33dce1 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -38,9 +38,12 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.location.ProviderProperties;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -1191,10 +1194,11 @@
@SystemApi
@RequiresPermission(WRITE_SECURE_SETTINGS)
public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
- try {
- mService.setLocationEnabledForUser(enabled, userHandle.getIdentifier());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ for (String provider : getAllProviders()) {
+ if (provider.equals(PASSIVE_PROVIDER)) {
+ continue;
+ }
+ setProviderEnabledForUser(provider, enabled, userHandle);
}
}
@@ -1208,11 +1212,19 @@
*/
@SystemApi
public boolean isLocationEnabledForUser(UserHandle userHandle) {
- try {
- return mService.isLocationEnabledForUser(userHandle.getIdentifier());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ final String allowedProviders = Settings.Secure.getStringForUser(
+ mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+ userHandle.getIdentifier());
+ final List<String> providerList = Arrays.asList(allowedProviders.split(","));
+ for(String provider : getAllProviders()) {
+ if (provider.equals(PASSIVE_PROVIDER)) {
+ continue;
+ }
+ if (providerList.contains(provider)) {
+ return true;
+ }
}
+ return false;
}
/**
@@ -1236,13 +1248,7 @@
* @throws IllegalArgumentException if provider is null
*/
public boolean isProviderEnabled(String provider) {
- checkProvider(provider);
-
- try {
- return mService.isProviderEnabled(provider);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return isProviderEnabledForUser(provider, Process.myUserHandle());
}
/**
@@ -1270,12 +1276,9 @@
@SystemApi
public boolean isProviderEnabledForUser(String provider, UserHandle userHandle) {
checkProvider(provider);
-
- try {
- return mService.isProviderEnabledForUser(provider, userHandle.getIdentifier());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ String allowedProviders = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userHandle.getIdentifier());
+ return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
}
/**
@@ -1294,13 +1297,16 @@
public boolean setProviderEnabledForUser(
String provider, boolean enabled, UserHandle userHandle) {
checkProvider(provider);
-
- try {
- return mService.setProviderEnabledForUser(
- provider, enabled, userHandle.getIdentifier());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ // to ensure thread safety, we write the provider name with a '+' or '-'
+ // and let the SettingsProvider handle it rather than reading and modifying
+ // the list of enabled providers.
+ if (enabled) {
+ provider = "+" + provider;
+ } else {
+ provider = "-" + provider;
}
+ return Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider, userHandle.getIdentifier());
}
/**
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 603926f..98e67c2 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -17,7 +17,9 @@
package com.android.internal.location.gnssmetrics;
import android.os.SystemClock;
+import android.os.connectivity.GpsBatteryStats;
+import android.text.format.DateUtils;
import android.util.Base64;
import android.util.Log;
import android.util.TimeUtils;
@@ -26,6 +28,7 @@
import com.android.internal.app.IBatteryStats;
import com.android.internal.location.nano.GnssLogsProto.GnssLog;
+import com.android.internal.location.nano.GnssLogsProto.PowerMetrics;
/**
* GnssMetrics: Is used for logging GNSS metrics
@@ -171,6 +174,7 @@
msg.standardDeviationTopFourAverageCn0DbHz
= topFourAverageCn0Statistics.getStandardDeviation();
}
+ msg.powerMetrics = mGnssPowerMetrics.buildProto();
String s = Base64.encodeToString(GnssLog.toByteArray(msg), Base64.DEFAULT);
reset();
return s;
@@ -218,6 +222,21 @@
topFourAverageCn0Statistics.getStandardDeviation()).append("\n");
}
s.append("GNSS_KPI_END").append("\n");
+ GpsBatteryStats stats = mGnssPowerMetrics.getGpsBatteryStats();
+ if (stats != null) {
+ s.append("Power Metrics").append('\n');
+ long[] t = stats.getTimeInGpsSignalQualityLevel();
+ if (t != null && t.length == NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+ s.append(" Amount of time (while on battery) Top 4 Avg CN0 > " +
+ Double.toString(GnssPowerMetrics.POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) +
+ " dB-Hz (min): ").append(t[1] / ((double) DateUtils.MINUTE_IN_MILLIS)).append("\n");
+ s.append(" Amount of time (while on battery) Top 4 Avg CN0 <= " +
+ Double.toString(GnssPowerMetrics.POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) +
+ " dB-Hz (min): ").append(t[0] / ((double) DateUtils.MINUTE_IN_MILLIS)).append("\n");
+ }
+ s.append(" Energy consumed while on battery (mAh): ").append(
+ stats.getEnergyConsumedMaMs() / ((double) DateUtils.HOUR_IN_MILLIS)).append("\n");
+ }
return s.toString();
}
@@ -294,7 +313,7 @@
private class GnssPowerMetrics {
/* Threshold for Top Four Average CN0 below which GNSS signal quality is declared poor */
- private static final double POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ = 20.0;
+ public static final double POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ = 20.0;
/* Minimum change in Top Four Average CN0 needed to trigger a report */
private static final double REPORTING_THRESHOLD_DB_HZ = 1.0;
@@ -313,6 +332,38 @@
}
/**
+ * Builds power metrics proto buf. This is included in the gnss proto buf.
+ * @return PowerMetrics
+ */
+ public PowerMetrics buildProto() {
+ PowerMetrics p = new PowerMetrics();
+ GpsBatteryStats stats = mGnssPowerMetrics.getGpsBatteryStats();
+ if (stats != null) {
+ p.loggingDurationMs = stats.getLoggingDurationMs();
+ p.energyConsumedMah = stats.getEnergyConsumedMaMs() / ((double) DateUtils.HOUR_IN_MILLIS);
+ long[] t = stats.getTimeInGpsSignalQualityLevel();
+ p.timeInSignalQualityLevelMs = new long[t.length];
+ for (int i = 0; i < t.length; i++) {
+ p.timeInSignalQualityLevelMs[i] = t[i];
+ }
+ }
+ return p;
+ }
+
+ /**
+ * Returns the GPS power stats
+ * @return GpsBatteryStats
+ */
+ public GpsBatteryStats getGpsBatteryStats() {
+ try {
+ return mBatteryStats.getGpsBatteryStats();
+ } catch (Exception e) {
+ Log.w(TAG, "Exception", e);
+ return null;
+ }
+ }
+
+ /**
* Reports signal quality to BatteryStats. Signal quality is based on Top four average CN0. If
* the number of SVs seen is less than 4, then signal quality is the average CN0.
* Changes are reported only if the average CN0 changes by more than REPORTING_THRESHOLD_DB_HZ.
@@ -347,4 +398,4 @@
return GnssMetrics.GPS_SIGNAL_QUALITY_POOR;
}
}
-}
\ No newline at end of file
+}
diff --git a/location/lib/Android.mk b/location/lib/Android.mk
index 62f5677..8424601 100644
--- a/location/lib/Android.mk
+++ b/location/lib/Android.mk
@@ -22,9 +22,7 @@
LOCAL_MODULE:= com.android.location.provider
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := \
- $(call all-subdir-java-files) \
- $(call all-aidl-files-under, java)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
include $(BUILD_JAVA_LIBRARY)
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 1a97b6b..3d879f5 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -22,6 +22,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
import java.util.TreeSet;
/**
@@ -142,7 +143,8 @@
TYPE_LINE_DIGITAL,
TYPE_FM,
TYPE_AUX_LINE,
- TYPE_IP }
+ TYPE_IP,
+ TYPE_BUS }
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceTypeOut {}
@@ -168,12 +170,26 @@
case TYPE_FM:
case TYPE_AUX_LINE:
case TYPE_IP:
+ case TYPE_BUS:
return true;
default:
return false;
}
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ AudioDeviceInfo that = (AudioDeviceInfo) o;
+ return Objects.equals(getPort(), that.getPort());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getPort());
+ }
+
private final AudioDevicePort mPort;
AudioDeviceInfo(AudioDevicePort port) {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a0a67b0..bf51d97 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -402,6 +402,18 @@
public static final int ADJUST_TOGGLE_MUTE = 101;
/** @hide */
+ @IntDef(flag = false, prefix = "ADJUST", value = {
+ ADJUST_RAISE,
+ ADJUST_LOWER,
+ ADJUST_SAME,
+ ADJUST_MUTE,
+ ADJUST_UNMUTE,
+ ADJUST_TOGGLE_MUTE }
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VolumeAdjustment {}
+
+ /** @hide */
public static final String adjustToString(int adj) {
switch (adj) {
case ADJUST_RAISE: return "ADJUST_RAISE";
@@ -2991,7 +3003,7 @@
final IAudioService service = getService();
try {
String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(),
- policy.hasFocusListener(), policy.isFocusPolicy());
+ policy.hasFocusListener(), policy.isFocusPolicy(), policy.isVolumeController());
if (regId == null) {
return ERROR;
} else {
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 6c65223..88d0a60 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -166,7 +166,8 @@
boolean isHdmiSystemAudioSupported();
String registerAudioPolicy(in AudioPolicyConfig policyConfig,
- in IAudioPolicyCallback pcb, boolean hasFocusListener, boolean isFocusPolicy);
+ in IAudioPolicyCallback pcb, boolean hasFocusListener, boolean isFocusPolicy,
+ boolean isVolumeController);
oneway void unregisterAudioPolicyAsync(in IAudioPolicyCallback pcb);
diff --git a/media/java/android/media/IMediaSession2.aidl b/media/java/android/media/IMediaSession2.aidl
deleted file mode 100644
index b10a40b..0000000
--- a/media/java/android/media/IMediaSession2.aidl
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.
- */
-
-package android.media;
-
-import android.media.IMediaSession2Callback;
-import android.os.Bundle;
-
-/**
- * Interface to MediaSession2. Framework MUST only call oneway APIs.
- *
- * @hide
- */
-// TODO(jaewan): Make this oneway interface.
-// Malicious app can fake session binder and holds commands from controller.
-interface IMediaSession2 {
- // TODO(jaewan): add onCommand() to send private command
- // TODO(jaewan): Due to the nature of oneway calls, APIs can be called in out of order
- // Add id for individual calls to address this.
-
- // TODO(jaewan): We may consider to add another binder just for the connection
- // not to expose other methods to the controller whose connection wasn't accepted.
- // But this would be enough for now because it's the same as existing
- // MediaBrowser and MediaBrowserService.
- oneway void connect(String callingPackage, IMediaSession2Callback callback);
- oneway void release(IMediaSession2Callback caller);
-
- //////////////////////////////////////////////////////////////////////////////////////////////
- // send command
- //////////////////////////////////////////////////////////////////////////////////////////////
- oneway void sendCommand(IMediaSession2Callback caller, in Bundle command, in Bundle args);
-
- Bundle getPlaybackState();
-
- //////////////////////////////////////////////////////////////////////////////////////////////
- // Get library service specific
- //////////////////////////////////////////////////////////////////////////////////////////////
- oneway void getBrowserRoot(IMediaSession2Callback callback, in Bundle rootHints);
-
- //////////////////////////////////////////////////////////////////////////////////////////////
- // Callbacks -- remove them
- //////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * @param callbackBinder binder to be used to notify changes.
- * @param callbackFlag one of {@link MediaController2#FLAG_CALLBACK_PLAYBACK} or
- * {@link MediaController2#FLAG_CALLBACK_SESSION_ACTIVENESS}
- * @param requestCode If >= 0, this code will be called back by the callback after the callback
- * is registered.
- */
- // TODO(jaewan): Due to the nature of the binder, calls can be called out of order.
- // Need a way to ensure calling of unregisterCallback unregisters later
- // registerCallback.
- oneway void registerCallback(IMediaSession2Callback callbackBinder,
- int callbackFlag, int requestCode);
- oneway void unregisterCallback(IMediaSession2Callback callbackBinder, int callbackFlag);
-}
diff --git a/media/java/android/media/IMediaSession2Callback.aidl b/media/java/android/media/IMediaSession2Callback.aidl
deleted file mode 100644
index eb02fa7..0000000
--- a/media/java/android/media/IMediaSession2Callback.aidl
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.
- */
-
-package android.media;
-
-import android.os.Bundle;
-import android.media.session.PlaybackState;
-import android.media.IMediaSession2;
-
-/**
- * Interface from MediaSession2 to MediaSession2Record.
- * <p>
- * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
- * and holds calls from session to make session owner(s) frozen.
- *
- * @hide
- */
-oneway interface IMediaSession2Callback {
- void onPlaybackStateChanged(in Bundle state);
-
- /**
- * Called only when the controller is created with service's token.
- *
- * @param sessionBinder {@code null} if the connect is rejected or is disconnected. a session
- * binder if the connect is accepted.
- * @param commands initially allowed commands.
- */
- // TODO(jaewan): Also need to pass flags for allowed actions for permission check.
- // For example, a media can allow setRating only for whitelisted apps
- // it's better for controller to know such information in advance.
- // Follow-up TODO: Add similar functions to the session.
- // TODO(jaewan): Is term 'accepted/rejected' correct? For permission, 'grant' is used.
- void onConnectionChanged(IMediaSession2 sessionBinder, in Bundle commandGroup);
-
- void onCustomLayoutChanged(in List<Bundle> commandButtonlist);
-
- //////////////////////////////////////////////////////////////////////////////////////////////
- // Browser sepcific
- //////////////////////////////////////////////////////////////////////////////////////////////
- void onGetRootResult(in Bundle rootHints, String rootMediaId, in Bundle rootExtra);
-}
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl b/media/java/android/media/ISessionTokensListener.aidl
similarity index 68%
copy from telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
copy to media/java/android/media/ISessionTokensListener.aidl
index f6005b6..c83a19e 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
+++ b/media/java/android/media/ISessionTokensListener.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 The Android Open Source Project
+ * 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.
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.media;
+
+import android.os.Bundle;
/**
- * See RcsFeature for more information.
- * {@hide}
+ * Listens for changes to the list of session tokens.
+ * @hide
*/
-interface IImsRcsFeature {
- //Empty Default Implementation
-}
\ No newline at end of file
+oneway interface ISessionTokensListener {
+ void onSessionTokensChanged(in List<Bundle> tokens);
+}
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
index 983ca75..dcd4dce 100644
--- a/media/java/android/media/MediaActionSound.java
+++ b/media/java/android/media/MediaActionSound.java
@@ -47,11 +47,16 @@
private SoundPool mSoundPool;
private SoundState[] mSounds;
+ private static final String[] SOUND_DIRS = {
+ "/product/media/audio/ui/",
+ "/system/media/audio/ui/",
+ };
+
private static final String[] SOUND_FILES = {
- "/system/media/audio/ui/camera_click.ogg",
- "/system/media/audio/ui/camera_focus.ogg",
- "/system/media/audio/ui/VideoRecord.ogg",
- "/system/media/audio/ui/VideoStop.ogg"
+ "camera_click.ogg",
+ "camera_focus.ogg",
+ "VideoRecord.ogg",
+ "VideoStop.ogg"
};
private static final String TAG = "MediaActionSound";
@@ -132,12 +137,16 @@
}
private int loadSound(SoundState sound) {
- int id = mSoundPool.load(SOUND_FILES[sound.name], 1);
- if (id > 0) {
- sound.state = STATE_LOADING;
- sound.id = id;
+ final String soundFileName = SOUND_FILES[sound.name];
+ for (String soundDir : SOUND_DIRS) {
+ int id = mSoundPool.load(soundDir + soundFileName, 1);
+ if (id > 0) {
+ sound.state = STATE_LOADING;
+ sound.id = id;
+ return id;
+ }
}
- return id;
+ return 0;
}
/**
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index 6064ec4..b32e539 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -30,6 +30,7 @@
import android.media.session.MediaSessionManager;
import android.media.update.ApiLoader;
import android.media.update.MediaController2Provider;
+import android.media.update.PlaybackInfoProvider;
import android.net.Uri;
import android.os.Bundle;
import android.os.ResultReceiver;
@@ -104,7 +105,7 @@
*
* @param info new playback info
*/
- public void onAudioInfoChanged(PlaybackInfo info) { }
+ public void onPlaybackInfoChanged(PlaybackInfo info) { }
/**
* Called when the allowed commands are changed by session.
@@ -126,18 +127,23 @@
/**
* Called when the playlist is changed.
*
- * @param list
- * @param param
+ * @param playlist A new playlist set by the session.
*/
- public void onPlaylistChanged(
- @NonNull List<MediaItem2> list, @NonNull PlaylistParams param) { }
+ public void onPlaylistChanged(@NonNull List<MediaItem2> playlist) { }
/**
- * Called when the playback state is changed.
+ * Called when the playback state is changed, or connection success.
*
- * @param state
+ * @param state latest playback state
*/
public void onPlaybackStateChanged(@NonNull PlaybackState2 state) { }
+
+ /**
+ * Called when the playlist parameters are changed.
+ *
+ * @param params The new play list parameters.
+ */
+ public void onPlaylistParamsChanged(@NonNull PlaylistParams params) { }
}
/**
@@ -155,21 +161,14 @@
*/
public static final int PLAYBACK_TYPE_LOCAL = 1;
- private final int mVolumeType;
- private final int mVolumeControl;
- private final int mMaxVolume;
- private final int mCurrentVolume;
- private final AudioAttributes mAudioAttrs;
+ private final PlaybackInfoProvider mProvider;
/**
* @hide
*/
- public PlaybackInfo(int type, AudioAttributes attrs, int control, int max, int current) {
- mVolumeType = type;
- mAudioAttrs = attrs;
- mVolumeControl = control;
- mMaxVolume = max;
- mCurrentVolume = current;
+ @SystemApi
+ public PlaybackInfo(PlaybackInfoProvider provider) {
+ mProvider = provider;
}
/**
@@ -182,7 +181,7 @@
* @return The type of playback this session is using.
*/
public int getPlaybackType() {
- return mVolumeType;
+ return mProvider.getPlaybackType_impl();
}
/**
@@ -194,7 +193,7 @@
* @return The attributes for this session.
*/
public AudioAttributes getAudioAttributes() {
- return mAudioAttrs;
+ return mProvider.getAudioAttributes_impl();
}
/**
@@ -205,11 +204,10 @@
* <li>{@link VolumeProvider#VOLUME_CONTROL_FIXED}</li>
* </ul>
*
- * @return The type of volume control that may be used with this
- * session.
+ * @return The type of volume control that may be used with this session.
*/
- public int getVolumeControl() {
- return mVolumeControl;
+ public int getControlType() {
+ return mProvider.getControlType_impl();
}
/**
@@ -218,7 +216,7 @@
* @return The maximum allowed volume where this session is playing.
*/
public int getMaxVolume() {
- return mMaxVolume;
+ return mProvider.getMaxVolume_impl();
}
/**
@@ -227,7 +225,7 @@
* @return The current volume where this session is playing.
*/
public int getCurrentVolume() {
- return mCurrentVolume;
+ return mProvider.getCurrentVolume_impl();
}
}
@@ -247,12 +245,13 @@
@NonNull @CallbackExecutor Executor executor, @NonNull ControllerCallback callback) {
super();
+ mProvider = createProvider(context, token, executor, callback);
// This also connects to the token.
// Explicit connect() isn't added on purpose because retrying connect() is impossible with
// session whose session binder is only valid while it's active.
// prevent a controller from reusable after the
// session is released and recreated.
- mProvider = createProvider(context, token, executor, callback);
+ mProvider.initialize();
}
MediaController2Provider createProvider(@NonNull Context context,
@@ -271,6 +270,9 @@
mProvider.close_impl();
}
+ /**
+ * @hide
+ */
@SystemApi
public MediaController2Provider getProvider() {
return mProvider;
@@ -359,6 +361,17 @@
}
/**
+ * Sets the {@link PlaylistParams} for the current play list. Repeat/shuffle mode and metadata
+ * for the list can be set by calling this method.
+ *
+ * @param params A {@link PlaylistParams} object to set.
+ * @throws IllegalArgumentException if given {@param param} is null.
+ */
+ public void setPlaylistParams(PlaylistParams params) {
+ mProvider.setPlaylistParams_impl(params);
+ }
+
+ /**
* @hide
*/
public void skipForward() {
@@ -527,11 +540,15 @@
}
/**
- * Get the latest {@link PlaybackState2} from the session.
+ * Get the lastly cached {@link PlaybackState2} from
+ * {@link ControllerCallback#onPlaybackStateChanged(PlaybackState2)}.
+ * <p>
+ * It may return {@code null} before the first callback or session has sent {@code null}
+ * playback state.
*
- * @return a playback state
+ * @return a playback state. Can be {@code null}
*/
- public PlaybackState2 getPlaybackState() {
+ public @Nullable PlaybackState2 getPlaybackState() {
return mProvider.getPlaybackState_impl();
}
@@ -576,9 +593,13 @@
return mProvider.getPlaylist_impl();
}
- public @Nullable
- PlaylistParams getPlaylistParam() {
- return mProvider.getPlaylistParam_impl();
+ /**
+ * Returns the {@link PlaylistParams} for the current play list.
+ * Can return {@code null} if the controller doesn't have enough permission, or if the session
+ * has not set the parameters.
+ */
+ public @Nullable PlaylistParams getPlaylistParams() {
+ return mProvider.getPlaylistParams_impl();
}
/**
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index a0edefa..90fcaab 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -942,43 +942,78 @@
throws DeniedByServerException;
/**
- * A means of enforcing limits on the number of concurrent streams per subscriber
- * across devices is provided via SecureStop. This is achieved by securely
- * monitoring the lifetime of sessions.
+ * Secure stops are a way to enforce limits on the number of concurrent
+ * streams per subscriber across devices. They provide secure monitoring of
+ * the lifetime of content decryption keys in MediaDrm sessions.
* <p>
- * Information from the server related to the current playback session is written
- * to persistent storage on the device when each MediaCrypto object is created.
+ * A secure stop is written to secure persistent memory when keys are loaded
+ * into a MediaDrm session. The secure stop state indicates that the keys
+ * are available for use. When playback completes and the keys are removed
+ * or the session is destroyed, the secure stop state is updated to indicate
+ * that keys are no longer usable.
* <p>
- * In the normal case, playback will be completed, the session destroyed and the
- * Secure Stops will be queried. The app queries secure stops and forwards the
- * secure stop message to the server which verifies the signature and notifies the
- * server side database that the session destruction has been confirmed. The persisted
- * record on the client is only removed after positive confirmation that the server
- * received the message using releaseSecureStops().
+ * After playback, the app can query the secure stop and send it in a
+ * message to the license server confirming that the keys are no longer
+ * active. The license server returns a secure stop release response
+ * message to the app which then deletes the secure stop from persistent
+ * memory using {@link #releaseSecureStops}.
+ * @return a list of all secure stops from secure persistent memory
*/
@NonNull
public native List<byte[]> getSecureStops();
/**
- * Access secure stop by secure stop ID.
+ * Return a list of all secure stop IDs currently in persistent memory.
*
- * @param ssid - The secure stop ID provided by the license server.
+ * @return a list of secure stop IDs
+ */
+ @NonNull
+ public native List<byte[]> getSecureStopIds();
+
+ /**
+ * Access a specific secure stop given its secure stop ID.
+ *
+ * @param ssid the ID of the secure stop to return
+ * @return the secure stop identified by ssid
*/
@NonNull
public native byte[] getSecureStop(@NonNull byte[] ssid);
/**
- * Process the SecureStop server response message ssRelease. After authenticating
- * the message, remove the SecureStops identified in the response.
+ * Process the secure stop server response message ssRelease. After
+ * authenticating the message, remove the secure stops identified in the
+ * response.
*
* @param ssRelease the server response indicating which secure stops to release
*/
public native void releaseSecureStops(@NonNull byte[] ssRelease);
/**
- * Remove all secure stops without requiring interaction with the server.
+ * Remove a specific secure stop without requiring a secure stop release message
+ * from the license server.
+ * @param ssid the ID of the secure stop to remove
*/
- public native void releaseAllSecureStops();
+ public native void removeSecureStop(@NonNull byte[] ssid);
+
+ /**
+ * Remove all secure stops without requiring a secure stop release message from
+ * the license server.
+ *
+ * This method was added in API 28. In API versions 18 through 27,
+ * {@link #releaseAllSecureStops} should be called instead. There is no need to
+ * do anything for API versions prior to 18.
+ */
+ public native void removeAllSecureStops();
+
+ /**
+ * Remove all secure stops without requiring a secure stop release message from
+ * the license server.
+ *
+ * @deprecated Remove all secure stops using {@link #removeAllSecureStops} instead.
+ */
+ public void releaseAllSecureStops() {
+ removeAllSecureStops();;
+ }
@Retention(RetentionPolicy.SOURCE)
@IntDef({HDCP_LEVEL_UNKNOWN, HDCP_NONE, HDCP_V1, HDCP_V2,
diff --git a/media/java/android/media/MediaItem2.java b/media/java/android/media/MediaItem2.java
index 6a96faa..eae4436 100644
--- a/media/java/android/media/MediaItem2.java
+++ b/media/java/android/media/MediaItem2.java
@@ -20,8 +20,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.content.Context;
+import android.media.update.ApiLoader;
+import android.media.update.MediaItem2Provider;
import android.os.Bundle;
-import android.text.TextUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -36,10 +38,6 @@
* @hide
*/
public class MediaItem2 {
- // TODO(jaewan): Keep DataSourceDesc.
- private final int mFlags;
- private MediaMetadata2 mMetadata;
-
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag=true, value = { FLAG_BROWSABLE, FLAG_PLAYABLE })
@@ -58,15 +56,29 @@
*/
public static final int FLAG_PLAYABLE = 1 << 1;
+ private final MediaItem2Provider mProvider;
+
/**
* Create a new media item.
*
+ * @param mediaId id of this item. It must be unique whithin this app
* @param metadata metadata with the media id.
* @param flags The flags for this item.
*/
- public MediaItem2(@NonNull MediaMetadata2 metadata, @Flags int flags) {
- mFlags = flags;
- setMetadata(metadata);
+ public MediaItem2(@NonNull Context context, @NonNull String mediaId,
+ @NonNull DataSourceDesc dsd, @Nullable MediaMetadata2 metadata,
+ @Flags int flags) {
+ mProvider = ApiLoader.getProvider(context).createMediaItem2(
+ context, this, mediaId, dsd, metadata, flags);
+ }
+
+ /**
+ * Create a new media item
+ * @hide
+ */
+ @SystemApi
+ public MediaItem2(MediaItem2Provider provider) {
+ mProvider = provider;
}
/**
@@ -76,22 +88,22 @@
*/
public Bundle toBundle() {
// TODO(jaewan): Fill here when we rebase.
- return new Bundle();
+ return mProvider.toBundle_impl();
+ }
+
+ public static MediaItem2 fromBundle(Context context, Bundle bundle) {
+ return ApiLoader.getProvider(context).fromBundle_MediaItem2(context, bundle);
}
public String toString() {
- final StringBuilder sb = new StringBuilder("MediaItem2{");
- sb.append("mFlags=").append(mFlags);
- sb.append(", mMetadata=").append(mMetadata);
- sb.append('}');
- return sb.toString();
+ return mProvider.toString_impl();
}
/**
* Gets the flags of the item.
*/
public @Flags int getFlags() {
- return mFlags;
+ return mProvider.getFlags_impl();
}
/**
@@ -99,7 +111,7 @@
* @see #FLAG_BROWSABLE
*/
public boolean isBrowsable() {
- return (mFlags & FLAG_BROWSABLE) != 0;
+ return mProvider.isBrowsable_impl();
}
/**
@@ -107,29 +119,24 @@
* @see #FLAG_PLAYABLE
*/
public boolean isPlayable() {
- return (mFlags & FLAG_PLAYABLE) != 0;
+ return mProvider.isPlayable_impl();
}
/**
- * Set a metadata. Metadata shouldn't be null and should have non-empty media id.
+ * Set a metadata. Metadata shouldn't be {@code null} and its id should be match
+ * with this instance's id.
*
- * @param metadata
+ * @param metadata metadata to update
*/
public void setMetadata(@NonNull MediaMetadata2 metadata) {
- if (metadata == null) {
- throw new IllegalArgumentException("metadata cannot be null");
- }
- if (TextUtils.isEmpty(metadata.getMediaId())) {
- throw new IllegalArgumentException("metadata must have a non-empty media id");
- }
- mMetadata = metadata;
+ mProvider.setMetadata_impl(metadata);
}
/**
* Returns the metadata of the media.
*/
public @NonNull MediaMetadata2 getMetadata() {
- return mMetadata;
+ return mProvider.getMetadata_impl();
}
/**
@@ -137,6 +144,17 @@
* @see MediaMetadata2#METADATA_KEY_MEDIA_ID
*/
public @Nullable String getMediaId() {
- return mMetadata.getMediaId();
+ return mProvider.getMediaId_impl();
+ }
+
+ /**
+ * Return the {@link DataSourceDesc}
+ * <p>
+ * Can be {@code null} if the MediaItem2 came from another process and anonymized
+ *
+ * @return data source descriptor
+ */
+ public @Nullable DataSourceDesc getDataSourceDesc() {
+ return mProvider.getDataSourceDesc_impl();
}
}
diff --git a/media/java/android/media/MediaLibraryService2.java b/media/java/android/media/MediaLibraryService2.java
index 5dadcb5..a901c68 100644
--- a/media/java/android/media/MediaLibraryService2.java
+++ b/media/java/android/media/MediaLibraryService2.java
@@ -19,6 +19,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.content.Context;
import android.media.MediaSession2.BuilderBase;
@@ -63,25 +64,16 @@
/**
* Session for the media library service.
*/
- public class MediaLibrarySession extends MediaSession2 {
+ public static class MediaLibrarySession extends MediaSession2 {
private final MediaLibrarySessionProvider mProvider;
- MediaLibrarySession(Context context, MediaPlayerBase player, String id,
- VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity,
- Executor callbackExecutor, SessionCallback callback) {
- super(context, player, id, volumeProvider, ratingType, sessionActivity,
- callbackExecutor, callback);
- mProvider = (MediaLibrarySessionProvider) getProvider();
- }
-
- @Override
- MediaSession2Provider createProvider(Context context, MediaPlayerBase player, String id,
- VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity,
- Executor callbackExecutor, SessionCallback callback) {
- return ApiLoader.getProvider(context)
- .createMediaLibraryService2MediaLibrarySession(context, this, player, id,
- volumeProvider, ratingType, sessionActivity,
- callbackExecutor, (MediaLibrarySessionCallback) callback);
+ /**
+ * @hide
+ */
+ @SystemApi
+ public MediaLibrarySession(MediaLibrarySessionProvider provider) {
+ super(provider);
+ mProvider = provider;
}
/**
@@ -109,6 +101,11 @@
}
public static class MediaLibrarySessionCallback extends MediaSession2.SessionCallback {
+
+ public MediaLibrarySessionCallback(Context context) {
+ super(context);
+ }
+
/**
* Called to get the root information for browsing by a particular client.
* <p>
@@ -202,31 +199,15 @@
/**
* Builder for {@link MediaLibrarySession}.
*/
- // TODO(jaewan): Move this to updatable.
- public class MediaLibrarySessionBuilder
- extends BuilderBase<MediaLibrarySessionBuilder, MediaLibrarySessionCallback> {
+ public class MediaLibrarySessionBuilder extends BuilderBase<MediaLibrarySession,
+ MediaLibrarySessionBuilder, MediaLibrarySessionCallback> {
public MediaLibrarySessionBuilder(
- @NonNull Context context, @NonNull MediaPlayerBase player,
+ @NonNull Context context, @NonNull MediaPlayerInterface player,
@NonNull @CallbackExecutor Executor callbackExecutor,
@NonNull MediaLibrarySessionCallback callback) {
- super(context, player);
- setSessionCallback(callbackExecutor, callback);
- }
-
- @Override
- public MediaLibrarySessionBuilder setSessionCallback(
- @NonNull @CallbackExecutor Executor callbackExecutor,
- @NonNull MediaLibrarySessionCallback callback) {
- if (callback == null) {
- throw new IllegalArgumentException("MediaLibrarySessionCallback cannot be null");
- }
- return super.setSessionCallback(callbackExecutor, callback);
- }
-
- @Override
- public MediaLibrarySession build() {
- return new MediaLibrarySession(mContext, mPlayer, mId, mVolumeProvider, mRatingType,
- mSessionActivity, mCallbackExecutor, mCallback);
+ super((instance) -> ApiLoader.getProvider(context).createMediaLibraryService2Builder(
+ context, (MediaLibrarySessionBuilder) instance, player, callbackExecutor,
+ callback));
}
}
diff --git a/media/java/android/media/MediaMetadata2.java b/media/java/android/media/MediaMetadata2.java
index fcdb4f7..54a9057 100644
--- a/media/java/android/media/MediaMetadata2.java
+++ b/media/java/android/media/MediaMetadata2.java
@@ -16,17 +16,16 @@
package android.media;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
+import android.annotation.SystemApi;
+import android.content.Context;
import android.graphics.Bitmap;
+import android.media.update.ApiLoader;
+import android.media.update.MediaMetadata2Provider;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.ArrayMap;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -37,9 +36,11 @@
*
* @hide
*/
-// TODO(jaewan): Move this to updatable
public final class MediaMetadata2 {
- private static final String TAG = "MediaMetadata2";
+ // New version of MediaMetadata that no longer implements Parcelable but added from/toBundle()
+ // for updatable.
+ // MediaDescription is deprecated because it was insufficient for controller to display media
+ // contents. Added getExtra() here to support all the features from the MediaDescription.
/**
* The title of the media.
@@ -365,76 +366,14 @@
@Retention(RetentionPolicy.SOURCE)
public @interface RatingKey {}
- static final int METADATA_TYPE_LONG = 0;
- static final int METADATA_TYPE_TEXT = 1;
- static final int METADATA_TYPE_BITMAP = 2;
- static final int METADATA_TYPE_RATING = 3;
- static final ArrayMap<String, Integer> METADATA_KEYS_TYPE;
-
- static {
- METADATA_KEYS_TYPE = new ArrayMap<String, Integer>();
- METADATA_KEYS_TYPE.put(METADATA_KEY_TITLE, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_ARTIST, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_DURATION, METADATA_TYPE_LONG);
- METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_AUTHOR, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_WRITER, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_COMPOSER, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_COMPILATION, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_DATE, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_LONG);
- METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_TRACK_NUMBER, METADATA_TYPE_LONG);
- METADATA_KEYS_TYPE.put(METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG);
- METADATA_KEYS_TYPE.put(METADATA_KEY_DISC_NUMBER, METADATA_TYPE_LONG);
- METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ARTIST, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP);
- METADATA_KEYS_TYPE.put(METADATA_KEY_ART_URI, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART, METADATA_TYPE_BITMAP);
- METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM_ART_URI, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_USER_RATING, METADATA_TYPE_RATING);
- METADATA_KEYS_TYPE.put(METADATA_KEY_RATING, METADATA_TYPE_RATING);
- METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_TITLE, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_SUBTITLE, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON, METADATA_TYPE_BITMAP);
- METADATA_KEYS_TYPE.put(METADATA_KEY_DISPLAY_ICON_URI, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_ID, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_BT_FOLDER_TYPE, METADATA_TYPE_LONG);
- METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_URI, METADATA_TYPE_TEXT);
- METADATA_KEYS_TYPE.put(METADATA_KEY_ADVERTISEMENT, METADATA_TYPE_LONG);
- METADATA_KEYS_TYPE.put(METADATA_KEY_DOWNLOAD_STATUS, METADATA_TYPE_LONG);
- }
-
- private static final @TextKey String[] PREFERRED_DESCRIPTION_ORDER = {
- METADATA_KEY_TITLE,
- METADATA_KEY_ARTIST,
- METADATA_KEY_ALBUM,
- METADATA_KEY_ALBUM_ARTIST,
- METADATA_KEY_WRITER,
- METADATA_KEY_AUTHOR,
- METADATA_KEY_COMPOSER
- };
-
- private static final @BitmapKey String[] PREFERRED_BITMAP_ORDER = {
- METADATA_KEY_DISPLAY_ICON,
- METADATA_KEY_ART,
- METADATA_KEY_ALBUM_ART
- };
-
- private static final @TextKey String[] PREFERRED_URI_ORDER = {
- METADATA_KEY_DISPLAY_ICON_URI,
- METADATA_KEY_ART_URI,
- METADATA_KEY_ALBUM_ART_URI
- };
-
- final Bundle mBundle;
+ private final MediaMetadata2Provider mProvider;
/**
* @hide
*/
- public MediaMetadata2(Bundle bundle) {
- mBundle = new Bundle(bundle);
+ @SystemApi
+ public MediaMetadata2(MediaMetadata2Provider provider) {
+ mProvider = provider;
}
/**
@@ -443,8 +382,8 @@
* @param key a String key
* @return true if the key exists in this metadata, false otherwise
*/
- public boolean containsKey(String key) {
- return mBundle.containsKey(key);
+ public boolean containsKey(@NonNull String key) {
+ return mProvider.containsKey_impl(key);
}
/**
@@ -455,8 +394,8 @@
* @param key The key the value is stored under
* @return a CharSequence value, or null
*/
- public CharSequence getText(@TextKey String key) {
- return mBundle.getCharSequence(key);
+ public @Nullable CharSequence getText(@TextKey String key) {
+ return mProvider.getText_impl(key);
}
/**
@@ -464,11 +403,11 @@
* the desired type exists for the given key or a null value is explicitly
* associated with the key.
*
- * @
* @return media id. Can be {@code null}
+ * @see #METADATA_KEY_MEDIA_ID
*/
public @Nullable String getMediaId() {
- return getString(METADATA_KEY_MEDIA_ID);
+ return mProvider.getMediaId_impl();
}
/**
@@ -479,12 +418,8 @@
* @param key The key the value is stored under
* @return a String value, or null
*/
- public String getString(@TextKey String key) {
- CharSequence text = mBundle.getCharSequence(key);
- if (text != null) {
- return text.toString();
- }
- return null;
+ public @Nullable String getString(@NonNull @TextKey String key) {
+ return mProvider.getString_impl(key);
}
/**
@@ -494,8 +429,8 @@
* @param key The key the value is stored under
* @return a long value
*/
- public long getLong(@LongKey String key) {
- return mBundle.getLong(key, 0);
+ public long getLong(@NonNull @LongKey String key) {
+ return mProvider.getLong_impl(key);
}
/**
@@ -503,18 +438,10 @@
* the given key.
*
* @param key The key the value is stored under
- * @return A {@link Rating2} or null
+ * @return A {@link Rating2} or {@code null}
*/
- public Rating2 getRating(@RatingKey String key) {
- // TODO(jaewan): Add backward compatibility
- Rating2 rating = null;
- try {
- rating = Rating2.fromBundle(mBundle.getBundle(key));
- } catch (Exception e) {
- // ignore, value was not a rating
- Log.w(TAG, "Failed to retrieve a key as Rating.", e);
- }
- return rating;
+ public @Nullable Rating2 getRating(@RatingKey String key) {
+ return mProvider.getRating_impl(key);
}
/**
@@ -525,14 +452,7 @@
* @return A {@link Bitmap} or null
*/
public Bitmap getBitmap(@BitmapKey String key) {
- Bitmap bmp = null;
- try {
- bmp = mBundle.getParcelable(key);
- } catch (Exception e) {
- // ignore, value was not a bitmap
- Log.w(TAG, "Failed to retrieve a key as Bitmap.", e);
- }
- return bmp;
+ return mProvider.getBitmap_impl(key);
}
/**
@@ -540,14 +460,8 @@
*
* @return A {@link Bundle} or {@code null}
*/
- public Bundle getExtra() {
- try {
- return mBundle.getBundle(METADATA_KEY_EXTRA);
- } catch (Exception e) {
- // ignore, value was not an bundle
- Log.w(TAG, "Failed to retrieve an extra");
- }
- return null;
+ public @Nullable Bundle getExtra() {
+ return mProvider.getExtra_impl();
}
/**
@@ -556,7 +470,7 @@
* @return The number of fields in the metadata.
*/
public int size() {
- return mBundle.size();
+ return mProvider.size_impl();
}
/**
@@ -564,8 +478,8 @@
*
* @return a Set of String keys
*/
- public Set<String> keySet() {
- return mBundle.keySet();
+ public @NonNull Set<String> keySet() {
+ return mProvider.keySet_impl();
}
/**
@@ -574,8 +488,21 @@
*
* @return The Bundle backing this metadata.
*/
- public Bundle getBundle() {
- return mBundle;
+ public @NonNull Bundle toBundle() {
+ return mProvider.toBundle_impl();
+ }
+
+ /**
+ * Creates the {@link MediaMetadata2} from the bundle that previously returned by
+ * {@link #toBundle()}.
+ *
+ * @param context context
+ * @param bundle bundle for the metadata
+ * @return a new MediaMetadata2
+ */
+ public static @NonNull MediaMetadata2 fromBundle(@NonNull Context context,
+ @Nullable Bundle bundle) {
+ return ApiLoader.getProvider(context).fromBundle_MediaMetadata2(context, bundle);
}
/**
@@ -583,14 +510,15 @@
* use the appropriate data type.
*/
public static final class Builder {
- private final Bundle mBundle;
+ private final MediaMetadata2Provider.BuilderProvider mProvider;
/**
* Create an empty Builder. Any field that should be included in the
* {@link MediaMetadata2} must be added.
*/
- public Builder() {
- mBundle = new Bundle();
+ public Builder(@NonNull Context context) {
+ mProvider = ApiLoader.getProvider(context).createMediaMetadata2Builder(
+ context, this);
}
/**
@@ -600,31 +528,17 @@
*
* @param source
*/
- public Builder(MediaMetadata2 source) {
- mBundle = new Bundle(source.mBundle);
+ public Builder(@NonNull Context context, @NonNull MediaMetadata2 source) {
+ mProvider = ApiLoader.getProvider(context).createMediaMetadata2Builder(
+ context, this, source);
}
/**
- * Create a Builder using a {@link MediaMetadata2} instance to set
- * initial values, but replace bitmaps with a scaled down copy if they
- * are larger than maxBitmapSize.
- *
- * @param source The original metadata to copy.
- * @param maxBitmapSize The maximum height/width for bitmaps contained
- * in the metadata.
* @hide
*/
- public Builder(MediaMetadata2 source, int maxBitmapSize) {
- this(source);
- for (String key : mBundle.keySet()) {
- Object value = mBundle.get(key);
- if (value instanceof Bitmap) {
- Bitmap bmp = (Bitmap) value;
- if (bmp.getHeight() > maxBitmapSize || bmp.getWidth() > maxBitmapSize) {
- putBitmap(key, scaleBitmap(bmp, maxBitmapSize));
- }
- }
- }
+ @SystemApi
+ public Builder(@NonNull MediaMetadata2Provider.BuilderProvider provider) {
+ mProvider = provider;
}
/**
@@ -653,15 +567,8 @@
* @param value The CharSequence value to store
* @return The Builder to allow chaining
*/
- public Builder putText(@TextKey String key, CharSequence value) {
- if (METADATA_KEYS_TYPE.containsKey(key)) {
- if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
- throw new IllegalArgumentException("The " + key
- + " key cannot be used to put a CharSequence");
- }
- }
- mBundle.putCharSequence(key, value);
- return this;
+ public @NonNull Builder putText(@TextKey String key, @Nullable CharSequence value) {
+ return mProvider.putText_impl(key, value);
}
/**
@@ -690,15 +597,8 @@
* @param value The String value to store
* @return The Builder to allow chaining
*/
- public Builder putString(@TextKey String key, String value) {
- if (METADATA_KEYS_TYPE.containsKey(key)) {
- if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
- throw new IllegalArgumentException("The " + key
- + " key cannot be used to put a String");
- }
- }
- mBundle.putCharSequence(key, value);
- return this;
+ public @NonNull Builder putString(@TextKey String key, @Nullable String value) {
+ return mProvider.putString_impl(key, value);
}
/**
@@ -720,15 +620,8 @@
* @param value The String value to store
* @return The Builder to allow chaining
*/
- public Builder putLong(@LongKey String key, long value) {
- if (METADATA_KEYS_TYPE.containsKey(key)) {
- if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) {
- throw new IllegalArgumentException("The " + key
- + " key cannot be used to put a long");
- }
- }
- mBundle.putLong(key, value);
- return this;
+ public @NonNull Builder putLong(@NonNull @LongKey String key, long value) {
+ return mProvider.putLong_impl(key, value);
}
/**
@@ -744,16 +637,8 @@
* @param value The String value to store
* @return The Builder to allow chaining
*/
- public Builder putRating(@RatingKey String key, Rating2 value) {
- if (METADATA_KEYS_TYPE.containsKey(key)) {
- if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) {
- throw new IllegalArgumentException("The " + key
- + " key cannot be used to put a Rating");
- }
- }
- mBundle.putBundle(key, value.toBundle());
-
- return this;
+ public @NonNull Builder putRating(@NonNull @RatingKey String key, @Nullable Rating2 value) {
+ return mProvider.putRating_impl(key, value);
}
/**
@@ -774,23 +659,15 @@
* @param value The Bitmap to store
* @return The Builder to allow chaining
*/
- public Builder putBitmap(@BitmapKey String key, Bitmap value) {
- if (METADATA_KEYS_TYPE.containsKey(key)) {
- if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
- throw new IllegalArgumentException("The " + key
- + " key cannot be used to put a Bitmap");
- }
- }
- mBundle.putParcelable(key, value);
- return this;
+ public @NonNull Builder putBitmap(@NonNull @BitmapKey String key, @Nullable Bitmap value) {
+ return mProvider.putBitmap_impl(key, value);
}
/**
* Set an extra {@link Bundle} into the metadata.
*/
- public Builder setExtra(Bundle bundle) {
- mBundle.putBundle(METADATA_KEY_EXTRA, bundle);
- return this;
+ public @NonNull Builder setExtra(@Nullable Bundle bundle) {
+ return mProvider.setExtra_impl(bundle);
}
/**
@@ -798,18 +675,8 @@
*
* @return The new MediaMetadata2 instance
*/
- public MediaMetadata2 build() {
- return new MediaMetadata2(mBundle);
- }
-
- private Bitmap scaleBitmap(Bitmap bmp, int maxSize) {
- float maxSizeF = maxSize;
- float widthScale = maxSizeF / bmp.getWidth();
- float heightScale = maxSizeF / bmp.getHeight();
- float scale = Math.min(widthScale, heightScale);
- int height = (int) (bmp.getHeight() * scale);
- int width = (int) (bmp.getWidth() * scale);
- return Bitmap.createScaledBitmap(bmp, width, height, true);
+ public @NonNull MediaMetadata2 build() {
+ return mProvider.build_impl();
}
}
}
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index d36df84..d84eedf 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -96,22 +96,13 @@
* {@link #close()} is called, it is in the <em>End</em> state. Between these
* two states is the life cycle of the MediaPlayer2 object.
* <ul>
- * <li>There is a subtle but important difference between a newly constructed
- * MediaPlayer2 object and the MediaPlayer2 object after {@link #reset()}
- * is called. It is a programming error to invoke methods such
+ * <li> It is a programming error to invoke methods such
* as {@link #getCurrentPosition()},
* {@link #getDuration()}, {@link #getVideoHeight()},
* {@link #getVideoWidth()}, {@link #setAudioAttributes(AudioAttributes)},
* {@link #setVolume(float, float)}, {@link #pause()}, {@link #play()},
* {@link #seekTo(long, int)} or
- * {@link #prepareAsync()} in the <em>Idle</em> state for both cases. If any of these
- * methods is called right after a MediaPlayer2 object is constructed,
- * the user supplied callback method OnErrorListener.onError() won't be
- * called by the internal player engine and the object state remains
- * unchanged; but if these methods are called right after {@link #reset()},
- * the user supplied callback method OnErrorListener.onError() will be
- * invoked by the internal player engine and the object will be
- * transfered to the <em>Error</em> state. </li>
+ * {@link #prepareAsync()} in the <em>Idle</em> state.
* <li>It is also recommended that once
* a MediaPlayer2 object is no longer being used, call {@link #close()} immediately
* so that resources used by the internal player engine associated with the
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 86a285c..222c66e 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -1960,6 +1960,13 @@
mTimeProvider = null;
}
+ synchronized (mEventCbLock) {
+ mEventCallbackRecords.clear();
+ }
+ synchronized (mDrmEventCbLock) {
+ mDrmEventCallbackRecords.clear();
+ }
+
stayAwake(false);
_reset();
// make sure none of the listeners get called anymore
@@ -3049,8 +3056,7 @@
stayAwake(false);
updateSurfaceScreenOn();
synchronized (mEventCbLock) {
- mEventCb = null;
- mEventExec = null;
+ mEventCallbackRecords.clear();
}
if (mTimeProvider != null) {
mTimeProvider.close();
@@ -3061,8 +3067,7 @@
// Modular DRM clean up
mOnDrmConfigHelper = null;
synchronized (mDrmEventCbLock) {
- mDrmEventCb = null;
- mDrmEventExec = null;
+ mDrmEventCallbackRecords.clear();
}
resetDrmState();
@@ -3118,18 +3123,8 @@
Log.w(TAG, "mediaplayer2 went away with unhandled events");
return;
}
- final Executor eventExec;
- final EventCallback eventCb;
- synchronized (mEventCbLock) {
- eventExec = mEventExec;
- eventCb = mEventCb;
- }
- final Executor drmEventExec;
- final DrmEventCallback drmEventCb;
- synchronized (mDrmEventCbLock) {
- drmEventExec = mDrmEventExec;
- drmEventCb = mDrmEventCb;
- }
+ final int what = msg.arg1;
+ final int extra = msg.arg2;
switch(msg.what) {
case MEDIA_PREPARED:
try {
@@ -3143,33 +3138,36 @@
sendMessage(msg2);
}
- if (eventCb != null && eventExec != null) {
- eventExec.execute(() -> eventCb.onInfo(
- mMediaPlayer, 0, MEDIA_INFO_PREPARED, 0));
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onInfo(
+ mMediaPlayer, 0, MEDIA_INFO_PREPARED, 0));
+ }
}
return;
case MEDIA_DRM_INFO:
- Log.v(TAG, "MEDIA_DRM_INFO " + mDrmEventCb);
-
if (msg.obj == null) {
Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
} else if (msg.obj instanceof Parcel) {
- if (drmEventExec != null && drmEventCb != null) {
- // The parcel was parsed already in postEventFromNative
- final DrmInfoImpl drmInfo;
+ // The parcel was parsed already in postEventFromNative
+ final DrmInfoImpl drmInfo;
- synchronized (mDrmLock) {
- if (mDrmInfoImpl != null) {
- drmInfo = mDrmInfoImpl.makeCopy();
- } else {
- drmInfo = null;
- }
+ synchronized (mDrmLock) {
+ if (mDrmInfoImpl != null) {
+ drmInfo = mDrmInfoImpl.makeCopy();
+ } else {
+ drmInfo = null;
}
+ }
- // notifying the client outside the lock
- if (drmInfo != null) {
- drmEventExec.execute(() -> drmEventCb.onDrmInfo(mMediaPlayer, drmInfo));
+ // notifying the client outside the lock
+ if (drmInfo != null) {
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onDrmInfo(
+ mMediaPlayer, drmInfo));
+ }
}
}
} else {
@@ -3178,9 +3176,11 @@
return;
case MEDIA_PLAYBACK_COMPLETE:
- if (eventCb != null && eventExec != null) {
- eventExec.execute(() -> eventCb.onInfo(
- mMediaPlayer, 0, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onInfo(
+ mMediaPlayer, 0, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
+ }
}
stayAwake(false);
return;
@@ -3205,16 +3205,21 @@
break;
case MEDIA_BUFFERING_UPDATE:
- if (eventCb != null && eventExec != null) {
- final int percent = msg.arg1;
- eventExec.execute(() -> eventCb.onBufferingUpdate(mMediaPlayer, 0, percent));
+ final int percent = msg.arg1;
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onBufferingUpdate(
+ mMediaPlayer, 0, percent));
+ }
}
return;
case MEDIA_SEEK_COMPLETE:
- if (eventCb != null && eventExec != null) {
- eventExec.execute(() -> eventCb.onInfo(
- mMediaPlayer, 0, MEDIA_INFO_COMPLETE_CALL_SEEK, 0));
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onInfo(
+ mMediaPlayer, 0, MEDIA_INFO_COMPLETE_CALL_SEEK, 0));
+ }
}
// fall through
@@ -3228,61 +3233,68 @@
return;
case MEDIA_SET_VIDEO_SIZE:
- if (eventCb != null && eventExec != null) {
- final int width = msg.arg1;
- final int height = msg.arg2;
- eventExec.execute(() -> eventCb.onVideoSizeChanged(
- mMediaPlayer, 0, width, height));
+ final int width = msg.arg1;
+ final int height = msg.arg2;
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onVideoSizeChanged(
+ mMediaPlayer, 0, width, height));
+ }
}
return;
case MEDIA_ERROR:
Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
- if (eventCb != null && eventExec != null) {
- final int what = msg.arg1;
- final int extra = msg.arg2;
- eventExec.execute(() -> eventCb.onError(mMediaPlayer, 0, what, extra));
- eventExec.execute(() -> eventCb.onInfo(
- mMediaPlayer, 0, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onError(
+ mMediaPlayer, 0, what, extra));
+ cb.first.execute(() -> cb.second.onInfo(
+ mMediaPlayer, 0, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
+ }
}
stayAwake(false);
return;
case MEDIA_INFO:
switch (msg.arg1) {
- case MEDIA_INFO_VIDEO_TRACK_LAGGING:
- Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
- break;
- case MEDIA_INFO_METADATA_UPDATE:
- try {
- scanInternalSubtitleTracks();
- } catch (RuntimeException e) {
- Message msg2 = obtainMessage(
- MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
- sendMessage(msg2);
- }
- // fall through
+ case MEDIA_INFO_VIDEO_TRACK_LAGGING:
+ Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
+ break;
- case MEDIA_INFO_EXTERNAL_METADATA_UPDATE:
- msg.arg1 = MEDIA_INFO_METADATA_UPDATE;
- // update default track selection
- if (mSubtitleController != null) {
- mSubtitleController.selectDefaultTrack();
- }
- break;
- case MEDIA_INFO_BUFFERING_START:
- case MEDIA_INFO_BUFFERING_END:
- TimeProvider timeProvider = mTimeProvider;
- if (timeProvider != null) {
- timeProvider.onBuffering(msg.arg1 == MEDIA_INFO_BUFFERING_START);
- }
- break;
+ case MEDIA_INFO_METADATA_UPDATE:
+ try {
+ scanInternalSubtitleTracks();
+ } catch (RuntimeException e) {
+ Message msg2 = obtainMessage(
+ MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED,
+ null);
+ sendMessage(msg2);
+ }
+ // fall through
+
+ case MEDIA_INFO_EXTERNAL_METADATA_UPDATE:
+ msg.arg1 = MEDIA_INFO_METADATA_UPDATE;
+ // update default track selection
+ if (mSubtitleController != null) {
+ mSubtitleController.selectDefaultTrack();
+ }
+ break;
+
+ case MEDIA_INFO_BUFFERING_START:
+ case MEDIA_INFO_BUFFERING_END:
+ TimeProvider timeProvider = mTimeProvider;
+ if (timeProvider != null) {
+ timeProvider.onBuffering(msg.arg1 == MEDIA_INFO_BUFFERING_START);
+ }
+ break;
}
- if (eventCb != null && eventExec != null) {
- final int what = msg.arg1;
- final int extra = msg.arg2;
- eventExec.execute(() -> eventCb.onInfo(mMediaPlayer, 0, what, extra));
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onInfo(
+ mMediaPlayer, 0, what, extra));
+ }
}
// No real default action so far.
return;
@@ -3295,17 +3307,18 @@
return;
case MEDIA_TIMED_TEXT:
- if (eventCb == null || eventExec == null) {
- return;
- }
- if (msg.obj == null) {
- eventExec.execute(() -> eventCb.onTimedText(mMediaPlayer, 0, null));
+ final TimedText text;
+ if (msg.obj instanceof Parcel) {
+ Parcel parcel = (Parcel)msg.obj;
+ text = new TimedText(parcel);
+ parcel.recycle();
} else {
- if (msg.obj instanceof Parcel) {
- Parcel parcel = (Parcel)msg.obj;
- TimedText text = new TimedText(parcel);
- parcel.recycle();
- eventExec.execute(() -> eventCb.onTimedText(mMediaPlayer, 0, text));
+ text = null;
+ }
+
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onTimedText(mMediaPlayer, 0, text));
}
}
return;
@@ -3324,15 +3337,20 @@
return;
case MEDIA_META_DATA:
- if (eventCb == null || eventExec == null) {
- return;
- }
+ final TimedMetaData data;
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
- TimedMetaData data = TimedMetaData.createTimedMetaDataFromParcel(parcel);
+ data = TimedMetaData.createTimedMetaDataFromParcel(parcel);
parcel.recycle();
- eventExec.execute(() -> eventCb.onTimedMetaDataAvailable(
- mMediaPlayer, 0, data));
+ } else {
+ data = null;
+ }
+
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onTimedMetaDataAvailable(
+ mMediaPlayer, 0, data));
+ }
}
return;
@@ -3420,9 +3438,9 @@
}
}
- private Executor mEventExec;
- private EventCallback mEventCb;
private final Object mEventCbLock = new Object();
+ private ArrayList<Pair<Executor, EventCallback> > mEventCallbackRecords
+ = new ArrayList<Pair<Executor, EventCallback> >();
/**
* Register a callback to be invoked when the media source is ready
@@ -3441,9 +3459,7 @@
throw new IllegalArgumentException("Illegal null Executor for the EventCallback");
}
synchronized (mEventCbLock) {
- // TODO: support multiple callbacks.
- mEventExec = executor;
- mEventCb = eventCallback;
+ mEventCallbackRecords.add(new Pair(executor, eventCallback));
}
}
@@ -3455,9 +3471,10 @@
@Override
public void unregisterEventCallback(EventCallback callback) {
synchronized (mEventCbLock) {
- if (callback == mEventCb) {
- mEventExec = null;
- mEventCb = null;
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ if (cb.second == callback) {
+ mEventCallbackRecords.remove(cb);
+ }
}
}
}
@@ -3497,9 +3514,9 @@
private OnDrmConfigHelper mOnDrmConfigHelper;
- private Executor mDrmEventExec;
- private DrmEventCallback mDrmEventCb;
private final Object mDrmEventCbLock = new Object();
+ private ArrayList<Pair<Executor, DrmEventCallback> > mDrmEventCallbackRecords
+ = new ArrayList<Pair<Executor, DrmEventCallback> >();
/**
* Register a callback to be invoked when the media source is ready
@@ -3518,9 +3535,7 @@
throw new IllegalArgumentException("Illegal null Executor for the EventCallback");
}
synchronized (mDrmEventCbLock) {
- // TODO: support multiple callbacks.
- mDrmEventExec = executor;
- mDrmEventCb = eventCallback;
+ mDrmEventCallbackRecords.add(new Pair(executor, eventCallback));
}
}
@@ -3532,9 +3547,11 @@
@Override
public void unregisterDrmEventCallback(DrmEventCallback callback) {
synchronized (mDrmEventCbLock) {
- if (callback == mDrmEventCb) {
- mDrmEventExec = null;
- mDrmEventCb = null;
+ for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
+ if (cb.second == callback) {
+ mDrmEventCallbackRecords.remove(cb);
+ break;
+ }
}
}
}
@@ -3733,15 +3750,11 @@
// if finished successfully without provisioning, call the callback outside the lock
if (allDoneWithoutProvisioning) {
- final Executor drmEventExec;
- final DrmEventCallback drmEventCb;
synchronized (mDrmEventCbLock) {
- drmEventExec = mDrmEventExec;
- drmEventCb = mDrmEventCb;
- }
- if (drmEventExec != null && drmEventCb != null) {
- drmEventExec.execute(() -> drmEventCb.onDrmPrepared(
- this, PREPARE_DRM_STATUS_SUCCESS));
+ for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onDrmPrepared(
+ this, PREPARE_DRM_STATUS_SUCCESS));
+ }
}
}
@@ -4324,14 +4337,12 @@
boolean succeeded = false;
- final Executor drmEventExec;
- final DrmEventCallback drmEventCb;
+ boolean hasCallback = false;
synchronized (mDrmEventCbLock) {
- drmEventExec = mDrmEventExec;
- drmEventCb = mDrmEventCb;
+ hasCallback = !mDrmEventCallbackRecords.isEmpty();
}
// non-blocking mode needs the lock
- if (drmEventExec != null && drmEventCb != null) {
+ if (hasCallback) {
synchronized (drmLock) {
// continuing with prepareDrm
@@ -4349,7 +4360,11 @@
} // synchronized
// calling the callback outside the lock
- drmEventExec.execute(() -> drmEventCb.onDrmPrepared(mediaPlayer, status));
+ synchronized (mDrmEventCbLock) {
+ for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onDrmPrepared(mediaPlayer, status));
+ }
+ }
} else { // blocking mode already has the lock
// continuing with prepareDrm
@@ -4397,13 +4412,11 @@
int result;
// non-blocking: this is not the final result
- final Executor drmEventExec;
- final DrmEventCallback drmEventCb;
+ boolean hasCallback = false;
synchronized (mDrmEventCbLock) {
- drmEventExec = mDrmEventExec;
- drmEventCb = mDrmEventCb;
+ hasCallback = !mDrmEventCallbackRecords.isEmpty();
}
- if (drmEventCb != null && drmEventExec != null) {
+ if (hasCallback) {
result = PREPARE_DRM_STATUS_SUCCESS;
} else {
// if blocking mode, wait till provisioning is done
diff --git a/media/java/android/media/MediaPlayerBase.java b/media/java/android/media/MediaPlayerBase.java
deleted file mode 100644
index 0efec901..0000000
--- a/media/java/android/media/MediaPlayerBase.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.
- */
-
-package android.media;
-
-import android.media.MediaSession2.PlaylistParams;
-
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * Base interfaces for all media players that want media session.
- * @hide
- */
-public abstract class MediaPlayerBase {
- /**
- * Listens change in {@link PlaybackState2}.
- */
- public interface PlaybackListener {
- /**
- * Called when {@link PlaybackState2} for this player is changed.
- */
- void onPlaybackChanged(PlaybackState2 state);
- }
-
- public abstract void play();
- public abstract void prepare();
- public abstract void pause();
- public abstract void stop();
- public abstract void skipToPrevious();
- public abstract void skipToNext();
- public abstract void seekTo(long pos);
- public abstract void fastFoward();
- public abstract void rewind();
-
- public abstract PlaybackState2 getPlaybackState();
- public abstract AudioAttributes getAudioAttributes();
-
- public abstract void setPlaylist(List<MediaItem2> item, PlaylistParams param);
- public abstract void setCurrentPlaylistItem(int index);
-
- /**
- * Add a {@link PlaybackListener} to be invoked when the playback state is changed.
- *
- * @param executor the Handler that will receive the listener
- * @param listener the listener that will be run
- */
- public abstract void addPlaybackListener(Executor executor, PlaybackListener listener);
-
- /**
- * Remove previously added {@link PlaybackListener}.
- *
- * @param listener the listener to be removed
- */
- public abstract void removePlaybackListener(PlaybackListener listener);
-}
diff --git a/media/java/android/media/MediaPlayerInterface.java b/media/java/android/media/MediaPlayerInterface.java
new file mode 100644
index 0000000..78e2391
--- /dev/null
+++ b/media/java/android/media/MediaPlayerInterface.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.MediaSession2.PlaylistParams;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Base interfaces for all media players that want media session.
+ * @hide
+ */
+public interface MediaPlayerInterface {
+ /**
+ * Listens change in {@link PlaybackState2}.
+ */
+ interface PlaybackListener {
+ /**
+ * Called when {@link PlaybackState2} for this player is changed.
+ */
+ void onPlaybackChanged(PlaybackState2 state);
+ }
+
+ // Transport controls that session will send command directly to this player.
+ void play();
+ void prepare();
+ void pause();
+ void stop();
+ void skipToPrevious();
+ void skipToNext();
+ void seekTo(long pos);
+ void fastForward();
+ void rewind();
+
+ PlaybackState2 getPlaybackState();
+
+ /**
+ * Sets the {@link AudioAttributes} to be used during the playback of the media.
+ *
+ * @param attributes non-null <code>AudioAttributes</code>.
+ */
+ void setAudioAttributes(@NonNull AudioAttributes attributes);
+
+ /**
+ * Returns AudioAttributes that media player has.
+ */
+ @Nullable
+ AudioAttributes getAudioAttributes();
+
+ void addPlaylistItem(int index, MediaItem2 item);
+ void removePlaylistItem(MediaItem2 item);
+
+ void setPlaylist(List<MediaItem2> playlist);
+ List<MediaItem2> getPlaylist();
+
+ void setCurrentPlaylistItem(int index);
+ void setPlaylistParams(PlaylistParams params);
+ PlaylistParams getPlaylistParams();
+
+ /**
+ * Add a {@link PlaybackListener} to be invoked when the playback state is changed.
+ *
+ * @param executor the Handler that will receive the listener
+ * @param listener the listener that will be run
+ */
+ void addPlaybackListener(Executor executor, PlaybackListener listener);
+
+ /**
+ * Remove previously added {@link PlaybackListener}.
+ *
+ * @param listener the listener to be removed
+ */
+ void removePlaybackListener(PlaybackListener listener);
+}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index cb4e46f..c309038 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -158,6 +158,7 @@
public static final String SCANNED_BUILD_PREFS_NAME = "MediaScanBuild";
public static final String LAST_INTERNAL_SCAN_FINGERPRINT = "lastScanFingerprint";
private static final String SYSTEM_SOUNDS_DIR = "/system/media/audio";
+ private static final String PRODUCT_SOUNDS_DIR = "/product/media/audio";
private static String sLastInternalScanFingerprint;
private static final String[] ID3_GENRES = {
@@ -1153,7 +1154,10 @@
private static boolean isSystemSoundWithMetadata(String path) {
if (path.startsWith(SYSTEM_SOUNDS_DIR + ALARMS_DIR)
|| path.startsWith(SYSTEM_SOUNDS_DIR + RINGTONES_DIR)
- || path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR)) {
+ || path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR)
+ || path.startsWith(PRODUCT_SOUNDS_DIR + ALARMS_DIR)
+ || path.startsWith(PRODUCT_SOUNDS_DIR + RINGTONES_DIR)
+ || path.startsWith(PRODUCT_SOUNDS_DIR + NOTIFICATIONS_DIR)) {
return true;
}
return false;
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index 7dffd40..acf9615 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -24,24 +24,26 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.media.MediaPlayerBase.PlaybackListener;
+import android.media.MediaPlayerInterface.PlaybackListener;
import android.media.session.MediaSession;
import android.media.session.MediaSession.Callback;
import android.media.session.PlaybackState;
import android.media.update.ApiLoader;
import android.media.update.MediaSession2Provider;
+import android.media.update.MediaSession2Provider.BuilderBaseProvider;
+import android.media.update.MediaSession2Provider.CommandGroupProvider;
+import android.media.update.MediaSession2Provider.CommandProvider;
import android.media.update.MediaSession2Provider.ControllerInfoProvider;
+import android.media.update.ProviderCreator;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
-import android.os.Parcelable;
+import android.os.IInterface;
import android.os.ResultReceiver;
import android.text.TextUtils;
-import android.util.ArraySet;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
@@ -67,7 +69,8 @@
* session.
* <p>
* When a session receive transport control commands, the session sends the commands directly to
- * the the underlying media player set by {@link Builder} or {@link #setPlayer(MediaPlayerBase)}.
+ * the the underlying media player set by {@link Builder} or
+ * {@link #setPlayer(MediaPlayerInterface)}.
* <p>
* When an app is finished performing playback it must call {@link #close()} to clean up the session
* and notify any controllers.
@@ -80,31 +83,178 @@
public class MediaSession2 implements AutoCloseable {
private final MediaSession2Provider mProvider;
- // Note: Do not define IntDef because subclass can add more command code on top of these.
+ // TODO(jaewan): Should we define IntDef? Currently we don't have to allow subclass to add more.
// TODO(jaewan): Shouldn't we pull out?
+ // TODO(jaewan): Should we also protect getters not related with metadata?
+ // Getters are getRatingType(), getPlaybackState(), getSessionActivity(),
+ // getPlaylistParams())
+ // Next ID: 23
+ /**
+ * Command code for the custom command which can be defined by string action in the
+ * {@link Command}.
+ */
public static final int COMMAND_CODE_CUSTOM = 0;
- public static final int COMMAND_CODE_PLAYBACK_START = 1;
+
+ /**
+ * Command code for {@link MediaController2#play()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
+ public static final int COMMAND_CODE_PLAYBACK_PLAY = 1;
+
+ /**
+ * Command code for {@link MediaController2#pause()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYBACK_PAUSE = 2;
+
+ /**
+ * Command code for {@link MediaController2#stop()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYBACK_STOP = 3;
+
+ /**
+ * Command code for {@link MediaController2#skipToNext()} ()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM = 4;
+
+ /**
+ * Command code for {@link MediaController2#skipToPrevious()} ()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM = 5;
+
+ /**
+ * Command code for {@link MediaController2#prepare()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYBACK_PREPARE = 6;
+
+ /**
+ * Command code for {@link MediaController2#fastForward()} ()}.
+ * <p>
+ * This is transport control command. Command would be sent directly to the player if the
+ * session doesn't reject the request through the
+ * {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYBACK_FAST_FORWARD = 7;
+
+ /**
+ * Command code for {@link MediaController2#rewind()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYBACK_REWIND = 8;
+
+ /**
+ * Command code for {@link MediaController2#seekTo(long)} ()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYBACK_SEEK_TO = 9;
+ /**
+ * Command code for {@link MediaController2#setCurrentPlaylistItem(int)} ()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM = 10;
- public static final int COMMAND_CODE_PLAYLIST_GET = 11;
+ /**
+ * Command code for {@link MediaController2#setPlaylistParams(PlaylistParams)} ()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
+ public static final int COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS = 11;
+
+ /**
+ * Command code for {@link MediaController2#addPlaylistItem(int, MediaItem2)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYLIST_ADD = 12;
+
+ /**
+ * Command code for {@link MediaController2#addPlaylistItem(int, MediaItem2)}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
public static final int COMMAND_CODE_PLAYLIST_REMOVE = 13;
- public static final int COMMAND_CODE_PLAY_FROM_MEDIA_ID = 14;
- public static final int COMMAND_CODE_PLAY_FROM_URI = 15;
- public static final int COMMAND_CODE_PLAY_FROM_SEARCH = 16;
+ /**
+ * Command code for {@link MediaController2#getPlaylist()}.
+ * <p>
+ * Command would be sent directly to the player if the session doesn't reject the request
+ * through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
+ public static final int COMMAND_CODE_PLAYLIST_GET = 14;
- public static final int COMMAND_CODE_PREPARE_FROM_MEDIA_ID = 17;
- public static final int COMMAND_CODE_PREPARE_FROM_URI = 18;
- public static final int COMMAND_CODE_PREPARE_FROM_SEARCH = 19;
+ /**
+ * Command code for both {@link MediaController2#setVolumeTo(int, int)} and
+ * {@link MediaController2#adjustVolume(int, int)}.
+ * <p>
+ * Command would adjust the volume or sent to the volume provider directly if the session
+ * doesn't reject the request through the
+ * {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
+ */
+ public static final int COMMAND_CODE_SET_VOLUME = 15;
+
+ /**
+ * Command code for {@link MediaController2#playFromMediaId(String, Bundle)}.
+ */
+ public static final int COMMAND_CODE_PLAY_FROM_MEDIA_ID = 16;
+
+ /**
+ * Command code for {@link MediaController2#playFromUri(String, Bundle)}.
+ */
+ public static final int COMMAND_CODE_PLAY_FROM_URI = 17;
+
+ /**
+ * Command code for {@link MediaController2#playFromSearch(String, Bundle)}.
+ */
+ public static final int COMMAND_CODE_PLAY_FROM_SEARCH = 18;
+
+ /**
+ * Command code for {@link MediaController2#prepareFromMediaId(String, Bundle)}.
+ */
+ public static final int COMMAND_CODE_PREPARE_FROM_MEDIA_ID = 19;
+
+ /**
+ * Command code for {@link MediaController2#prepareFromUri(Uri, Bundle)}.
+ */
+ public static final int COMMAND_CODE_PREPARE_FROM_URI = 20;
+
+ /**
+ * Command code for {@link MediaController2#prepareFromSearch(String, Bundle)}.
+ */
+ public static final int COMMAND_CODE_PREPARE_FROM_SEARCH = 21;
+
+ /**
+ * Command code for {@link MediaBrowser2} specific functions that allows navigation and search
+ * from the {@link MediaLibraryService2}. This would be ignored if a {@link MediaSession2},
+ * not {@link android.media.MediaLibraryService2.MediaLibrarySession}, specify this.
+ *
+ * @see MediaBrowser2
+ */
+ public static final int COMMAND_CODE_BROWSER = 22;
/**
* Define a command that a {@link MediaController2} can send to a {@link MediaSession2}.
@@ -115,43 +265,31 @@
*/
// TODO(jaewan): Move this into the updatable.
public static final class Command {
- private static final String KEY_COMMAND_CODE
- = "android.media.media_session2.command.command_code";
- private static final String KEY_COMMAND_CUSTOM_COMMAND
- = "android.media.media_session2.command.custom_command";
- private static final String KEY_COMMAND_EXTRA
- = "android.media.media_session2.command.extra";
+ private final CommandProvider mProvider;
- private final int mCommandCode;
- // Nonnull if it's custom command
- private final String mCustomCommand;
- private final Bundle mExtra;
-
- public Command(int commandCode) {
- mCommandCode = commandCode;
- mCustomCommand = null;
- mExtra = null;
+ public Command(@NonNull Context context, int commandCode) {
+ mProvider = ApiLoader.getProvider(context)
+ .createMediaSession2Command(this, commandCode, null, null);
}
- public Command(@NonNull String action, @Nullable Bundle extra) {
+ public Command(@NonNull Context context, @NonNull String action, @Nullable Bundle extra) {
if (action == null) {
throw new IllegalArgumentException("action shouldn't be null");
}
- mCommandCode = COMMAND_CODE_CUSTOM;
- mCustomCommand = action;
- mExtra = extra;
+ mProvider = ApiLoader.getProvider(context)
+ .createMediaSession2Command(this, COMMAND_CODE_CUSTOM, action, extra);
}
public int getCommandCode() {
- return mCommandCode;
+ return mProvider.getCommandCode_impl();
}
public @Nullable String getCustomCommand() {
- return mCustomCommand;
+ return mProvider.getCustomCommand_impl();
}
public @Nullable Bundle getExtra() {
- return mExtra;
+ return mProvider.getExtra_impl();
}
/**
@@ -159,28 +297,7 @@
* @hide
*/
public Bundle toBundle() {
- Bundle bundle = new Bundle();
- bundle.putInt(KEY_COMMAND_CODE, mCommandCode);
- bundle.putString(KEY_COMMAND_CUSTOM_COMMAND, mCustomCommand);
- bundle.putBundle(KEY_COMMAND_EXTRA, mExtra);
- return bundle;
- }
-
- /**
- * @return a new Command instance from the Bundle
- * @hide
- */
- public static Command fromBundle(Bundle command) {
- int code = command.getInt(KEY_COMMAND_CODE);
- if (code != COMMAND_CODE_CUSTOM) {
- return new Command(code);
- } else {
- String customCommand = command.getString(KEY_COMMAND_CUSTOM_COMMAND);
- if (customCommand == null) {
- return null;
- }
- return new Command(customCommand, command.getBundle(KEY_COMMAND_EXTRA));
- }
+ return mProvider.toBundle_impl();
}
@Override
@@ -188,67 +305,65 @@
if (!(obj instanceof Command)) {
return false;
}
- Command other = (Command) obj;
- // TODO(jaewan): Should we also compare contents in bundle?
- // It may not be possible if the bundle contains private class.
- return mCommandCode == other.mCommandCode
- && TextUtils.equals(mCustomCommand, other.mCustomCommand);
+ return mProvider.equals_impl(((Command) obj).mProvider);
}
@Override
public int hashCode() {
- final int prime = 31;
- return ((mCustomCommand != null) ? mCustomCommand.hashCode() : 0) * prime + mCommandCode;
+ return mProvider.hashCode_impl();
+ }
+
+ /**
+ * @return a new Command instance from the Bundle
+ * @hide
+ */
+ public static Command fromBundle(@NonNull Context context, Bundle command) {
+ return ApiLoader.getProvider(context).fromBundle_MediaSession2Command(context, command);
}
}
/**
* Represent set of {@link Command}.
*/
- // TODO(jaewan): Move this to updatable
public static class CommandGroup {
- private static final String KEY_COMMANDS =
- "android.media.mediasession2.commandgroup.commands";
- private ArraySet<Command> mCommands = new ArraySet<>();
+ private final CommandGroupProvider mProvider;
- public CommandGroup() {
+ public CommandGroup(Context context) {
+ mProvider = ApiLoader.getProvider(context)
+ .createMediaSession2CommandGroup(context, this, null);
}
- public CommandGroup(CommandGroup others) {
- mCommands.addAll(others.mCommands);
+ public CommandGroup(Context context, CommandGroup others) {
+ mProvider = ApiLoader.getProvider(context)
+ .createMediaSession2CommandGroup(context, this, others);
}
public void addCommand(Command command) {
- mCommands.add(command);
+ mProvider.addCommand_impl(command);
}
public void addAllPredefinedCommands() {
- // TODO(jaewan): Is there any better way than this?
- mCommands.add(new Command(COMMAND_CODE_PLAYBACK_START));
- mCommands.add(new Command(COMMAND_CODE_PLAYBACK_PAUSE));
- mCommands.add(new Command(COMMAND_CODE_PLAYBACK_STOP));
- mCommands.add(new Command(COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM));
- mCommands.add(new Command(COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM));
+ mProvider.addAllPredefinedCommands_impl();
}
public void removeCommand(Command command) {
- mCommands.remove(command);
+ mProvider.removeCommand_impl(command);
}
public boolean hasCommand(Command command) {
- return mCommands.contains(command);
+ return mProvider.hasCommand_impl(command);
}
public boolean hasCommand(int code) {
- if (code == COMMAND_CODE_CUSTOM) {
- throw new IllegalArgumentException("Use hasCommand(Command) for custom command");
- }
- for (int i = 0; i < mCommands.size(); i++) {
- if (mCommands.valueAt(i).getCommandCode() == code) {
- return true;
- }
- }
- return false;
+ return mProvider.hasCommand_impl(code);
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi
+ public CommandGroupProvider getProvider() {
+ return mProvider;
}
/**
@@ -256,40 +371,16 @@
* @hide
*/
public Bundle toBundle() {
- ArrayList<Bundle> list = new ArrayList<>();
- for (int i = 0; i < mCommands.size(); i++) {
- list.add(mCommands.valueAt(i).toBundle());
- }
- Bundle bundle = new Bundle();
- bundle.putParcelableArrayList(KEY_COMMANDS, list);
- return bundle;
+ return mProvider.toBundle_impl();
}
/**
* @return new instance of CommandGroup from the bundle
* @hide
*/
- public static @Nullable CommandGroup fromBundle(Bundle commands) {
- if (commands == null) {
- return null;
- }
- List<Parcelable> list = commands.getParcelableArrayList(KEY_COMMANDS);
- if (list == null) {
- return null;
- }
- CommandGroup commandGroup = new CommandGroup();
- for (int i = 0; i < list.size(); i++) {
- Parcelable parcelable = list.get(i);
- if (!(parcelable instanceof Bundle)) {
- continue;
- }
- Bundle commandBundle = (Bundle) parcelable;
- Command command = Command.fromBundle(commandBundle);
- if (command != null) {
- commandGroup.addCommand(command);
- }
- }
- return commandGroup;
+ public static @Nullable CommandGroup fromBundle(Context context, Bundle commands) {
+ return ApiLoader.getProvider(context)
+ .fromBundle_MediaSession2CommandGroup(context, commands);
}
}
@@ -301,6 +392,12 @@
*/
// TODO(jaewan): Can we move this inside of the updatable for default implementation.
public static class SessionCallback {
+ private final Context mContext;
+
+ public SessionCallback(Context context) {
+ mContext = context;
+ }
+
/**
* Called when a controller is created for this session. Return allowed commands for
* controller. By default it allows all connection requests and commands.
@@ -313,7 +410,7 @@
*/
// TODO(jaewan): Change return type. Once we do, null is for reject.
public @Nullable CommandGroup onConnect(@NonNull ControllerInfo controller) {
- CommandGroup commands = new CommandGroup();
+ CommandGroup commands = new CommandGroup(mContext);
commands.addAllPredefinedCommands();
return commands;
}
@@ -326,22 +423,36 @@
public void onDisconnected(@NonNull ControllerInfo controller) { }
/**
- * Called when a controller sent a command to the session, and the command will be sent to
- * the player directly unless you reject the request by {@code false}.
+ * Called when a controller sent a command that will be sent directly to the player. Return
+ * {@code false} here to reject the request and stop sending command to the player.
*
* @param controller controller information.
* @param command a command. This method will be called for every single command.
* @return {@code true} if you want to accept incoming command. {@code false} otherwise.
+ * @see #COMMAND_CODE_PLAYBACK_PLAY
+ * @see #COMMAND_CODE_PLAYBACK_PAUSE
+ * @see #COMMAND_CODE_PLAYBACK_STOP
+ * @see #COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM
+ * @see #COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM
+ * @see #COMMAND_CODE_PLAYBACK_PREPARE
+ * @see #COMMAND_CODE_PLAYBACK_FAST_FORWARD
+ * @see #COMMAND_CODE_PLAYBACK_REWIND
+ * @see #COMMAND_CODE_PLAYBACK_SEEK_TO
+ * @see #COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM
+ * @see #COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS
+ * @see #COMMAND_CODE_PLAYLIST_ADD
+ * @see #COMMAND_CODE_PLAYLIST_REMOVE
+ * @see #COMMAND_CODE_PLAYLIST_GET
+ * @see #COMMAND_CODE_SET_VOLUME
*/
- // TODO(jaewan): Add more documentations (or make it clear) which commands can be filtered
- // with this.
public boolean onCommandRequest(@NonNull ControllerInfo controller,
@NonNull Command command) {
return true;
}
/**
- * Called when a controller set rating on the currently playing contents.
+ * Called when a controller set rating on the currently playing contents by
+ * {@link MediaController2#setRating(Rating2)}.
*
* @param controller controller information
* @param rating new rating from the controller
@@ -349,7 +460,8 @@
public void onSetRating(@NonNull ControllerInfo controller, @NonNull Rating2 rating) { }
/**
- * Called when a controller sent a custom command.
+ * Called when a controller sent a custom command through
+ * {@link MediaController2#sendCustomCommand(Command, Bundle, ResultReceiver)}.
*
* @param controller controller information
* @param customCommand custom command.
@@ -361,7 +473,48 @@
@Nullable ResultReceiver cb) { }
/**
- * Override to handle requests to prepare for playing a specific mediaId.
+ * Called when a controller requested to play a specific mediaId through
+ * {@link MediaController2#playFromMediaId(String, Bundle)}.
+ *
+ * @param controller controller information
+ * @param mediaId media id
+ * @param extras optional extra bundle
+ * @see #COMMAND_CODE_PLAY_FROM_MEDIA_ID
+ */
+ public void onPlayFromMediaId(@NonNull ControllerInfo controller,
+ @NonNull String mediaId, @Nullable Bundle extras) { }
+
+ /**
+ * Called when a controller requested to begin playback from a search query through
+ * {@link MediaController2#playFromSearch(String, Bundle)}
+ * <p>
+ * An empty query indicates that the app may play any music. The implementation should
+ * attempt to make a smart choice about what to play.
+ *
+ * @param controller controller information
+ * @param query query string. Can be empty to indicate any suggested media
+ * @param extras optional extra bundle
+ * @see #COMMAND_CODE_PLAY_FROM_SEARCH
+ */
+ public void onPlayFromSearch(@NonNull ControllerInfo controller,
+ @NonNull String query, @Nullable Bundle extras) { }
+
+ /**
+ * Called when a controller requested to play a specific media item represented by a URI
+ * through {@link MediaController2#playFromUri(String, Bundle)}
+ *
+ * @param controller controller information
+ * @param uri uri
+ * @param extras optional extra bundle
+ * @see #COMMAND_CODE_PLAY_FROM_URI
+ */
+ public void onPlayFromUri(@NonNull ControllerInfo controller,
+ @NonNull String uri, @Nullable Bundle extras) { }
+
+ /**
+ * Called when a controller requested to prepare for playing a specific mediaId through
+ * {@link MediaController2#prepareFromMediaId(String, Bundle)}.
+ * <p>
* During the preparation, a session should not hold audio focus in order to allow other
* sessions play seamlessly. The state of playback should be updated to
* {@link PlaybackState#STATE_PAUSED} after the preparation is done.
@@ -371,28 +524,41 @@
* <p>
* Override {@link #onPlayFromMediaId} to handle requests for starting
* playback without preparation.
+ *
+ * @param controller controller information
+ * @param mediaId media id to prepare
+ * @param extras optional extra bundle
+ * @see #COMMAND_CODE_PREPARE_FROM_MEDIA_ID
*/
- public void onPlayFromMediaId(@NonNull ControllerInfo controller,
+ public void onPrepareFromMediaId(@NonNull ControllerInfo controller,
@NonNull String mediaId, @Nullable Bundle extras) { }
/**
- * Override to handle requests to prepare playback from a search query. An empty query
- * indicates that the app may prepare any music. The implementation should attempt to make a
- * smart choice about what to play. During the preparation, a session should not hold audio
- * focus in order to allow other sessions play seamlessly. The state of playback should be
- * updated to {@link PlaybackState#STATE_PAUSED} after the preparation is done.
+ * Called when a controller requested to prepare playback from a search query through
+ * {@link MediaController2#prepareFromSearch(String, Bundle)}.
* <p>
- * The playback of the prepared content should start in the later calls of
- * {@link MediaSession2#play()}.
+ * An empty query indicates that the app may prepare any music. The implementation should
+ * attempt to make a smart choice about what to play.
+ * <p>
+ * The state of playback should be updated to {@link PlaybackState#STATE_PAUSED} after the
+ * preparation is done. The playback of the prepared content should start in the later
+ * calls of {@link MediaSession2#play()}.
* <p>
* Override {@link #onPlayFromSearch} to handle requests for starting playback without
* preparation.
+ *
+ * @param controller controller information
+ * @param query query string. Can be empty to indicate any suggested media
+ * @param extras optional extra bundle
+ * @see #COMMAND_CODE_PREPARE_FROM_SEARCH
*/
- public void onPlayFromSearch(@NonNull ControllerInfo controller,
+ public void onPrepareFromSearch(@NonNull ControllerInfo controller,
@NonNull String query, @Nullable Bundle extras) { }
/**
- * Override to handle requests to prepare a specific media item represented by a URI.
+ * Called when a controller requested to prepare a specific media item represented by a URI
+ * through {@link MediaController2#prepareFromUri(Uri, Bundle)}.
+ * <p></p>
* During the preparation, a session should not hold audio focus in order to allow
* other sessions play seamlessly. The state of playback should be updated to
* {@link PlaybackState#STATE_PAUSED} after the preparation is done.
@@ -402,51 +568,14 @@
* <p>
* Override {@link #onPlayFromUri} to handle requests for starting playback without
* preparation.
- */
- public void onPlayFromUri(@NonNull ControllerInfo controller,
- @NonNull String uri, @Nullable Bundle extras) { }
-
- /**
- * Override to handle requests to play a specific mediaId.
- */
- public void onPrepareFromMediaId(@NonNull ControllerInfo controller,
- @NonNull String mediaId, @Nullable Bundle extras) { }
-
- /**
- * Override to handle requests to begin playback from a search query. An
- * empty query indicates that the app may play any music. The
- * implementation should attempt to make a smart choice about what to
- * play.
- */
- public void onPrepareFromSearch(@NonNull ControllerInfo controller,
- @NonNull String query, @Nullable Bundle extras) { }
-
- /**
- * Override to handle requests to play a specific media item represented by a URI.
+ *
+ * @param controller controller information
+ * @param uri uri
+ * @param extras optional extra bundle
+ * @see #COMMAND_CODE_PREPARE_FROM_URI
*/
public void onPrepareFromUri(@NonNull ControllerInfo controller,
@NonNull Uri uri, @Nullable Bundle extras) { }
-
- /**
- * Called when a controller wants to add a {@link MediaItem2} at the specified position
- * in the play queue.
- * <p>
- * The item from the media controller wouldn't have valid data source descriptor because
- * it would have been anonymized when it's sent to the remote process.
- *
- * @param item The media item to be inserted.
- * @param index The index at which the item is to be inserted.
- */
- public void onAddPlaylistItem(@NonNull ControllerInfo controller,
- @NonNull MediaItem2 item, int index) { }
-
- /**
- * Called when a controller wants to remove the {@link MediaItem2}
- *
- * @param item
- */
- // Can we do this automatically?
- public void onRemovePlaylistItem(@NonNull MediaItem2 item) { }
};
/**
@@ -455,36 +584,11 @@
* @hide
*/
static abstract class BuilderBase
- <T extends MediaSession2.BuilderBase<T, C>, C extends SessionCallback> {
- final Context mContext;
- final MediaPlayerBase mPlayer;
- String mId;
- Executor mCallbackExecutor;
- C mCallback;
- VolumeProvider mVolumeProvider;
- int mRatingType;
- PendingIntent mSessionActivity;
+ <T extends MediaSession2, U extends BuilderBase<T, U, C>, C extends SessionCallback> {
+ private final BuilderBaseProvider<T, C> mProvider;
- /**
- * Constructor.
- *
- * @param context a context
- * @param player a player to handle incoming command from any controller.
- * @throws IllegalArgumentException if any parameter is null, or the player is a
- * {@link MediaSession2} or {@link MediaController2}.
- */
- // TODO(jaewan): Also need executor
- public BuilderBase(@NonNull Context context, @NonNull MediaPlayerBase player) {
- if (context == null) {
- throw new IllegalArgumentException("context shouldn't be null");
- }
- if (player == null) {
- throw new IllegalArgumentException("player shouldn't be null");
- }
- mContext = context;
- mPlayer = player;
- // Ensure non-null
- mId = "";
+ BuilderBase(ProviderCreator<BuilderBase<T, U, C>, BuilderBaseProvider<T, C>> creator) {
+ mProvider = creator.createProvider(this);
}
/**
@@ -496,9 +600,9 @@
*
* @param volumeProvider The provider that will handle volume changes. Can be {@code null}
*/
- public T setVolumeProvider(@Nullable VolumeProvider volumeProvider) {
- mVolumeProvider = volumeProvider;
- return (T) this;
+ public U setVolumeProvider(@Nullable VolumeProvider volumeProvider) {
+ mProvider.setVolumeProvider_impl(volumeProvider);
+ return (U) this;
}
/**
@@ -514,9 +618,9 @@
* <li>{@link Rating2#RATING_THUMB_UP_DOWN}</li>
* </ul>
*/
- public T setRatingType(@Rating2.Style int type) {
- mRatingType = type;
- return (T) this;
+ public U setRatingType(@Rating2.Style int type) {
+ mProvider.setRatingType_impl(type);
+ return (U) this;
}
/**
@@ -526,9 +630,9 @@
*
* @param pi The intent to launch to show UI for this session.
*/
- public T setSessionActivity(@Nullable PendingIntent pi) {
- mSessionActivity = pi;
- return (T) this;
+ public U setSessionActivity(@Nullable PendingIntent pi) {
+ mProvider.setSessionActivity_impl(pi);
+ return (U) this;
}
/**
@@ -541,12 +645,9 @@
* @throws IllegalArgumentException if id is {@code null}
* @return
*/
- public T setId(@NonNull String id) {
- if (id == null) {
- throw new IllegalArgumentException("id shouldn't be null");
- }
- mId = id;
- return (T) this;
+ public U setId(@NonNull String id) {
+ mProvider.setId_impl(id);
+ return (U) this;
}
/**
@@ -556,17 +657,10 @@
* @param callback session callback.
* @return
*/
- public T setSessionCallback(@NonNull @CallbackExecutor Executor executor,
+ public U setSessionCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull C callback) {
- if (executor == null) {
- throw new IllegalArgumentException("executor shouldn't be null");
- }
- if (callback == null) {
- throw new IllegalArgumentException("callback shouldn't be null");
- }
- mCallbackExecutor = executor;
- mCallback = callback;
- return (T) this;
+ mProvider.setSessionCallback_impl(executor, callback);
+ return (U) this;
}
/**
@@ -576,7 +670,9 @@
* @throws IllegalStateException if the session with the same id is already exists for the
* package.
*/
- public abstract MediaSession2 build();
+ public T build() {
+ return mProvider.build_impl();
+ }
}
/**
@@ -585,28 +681,18 @@
* Any incoming event from the {@link MediaController2} will be handled on the thread
* that created session with the {@link Builder#build()}.
*/
- // TODO(jaewan): Move this to updatable
// TODO(jaewan): Add setRatingType()
// TODO(jaewan): Add setSessionActivity()
- public static final class Builder extends BuilderBase<Builder, SessionCallback> {
- public Builder(Context context, @NonNull MediaPlayerBase player) {
- super(context, player);
- }
-
- @Override
- public MediaSession2 build() {
- if (mCallback == null) {
- mCallback = new SessionCallback();
- }
- return new MediaSession2(mContext, mPlayer, mId, mVolumeProvider, mRatingType,
- mSessionActivity, mCallbackExecutor, mCallback);
+ public static final class Builder extends BuilderBase<MediaSession2, Builder, SessionCallback> {
+ public Builder(Context context, @NonNull MediaPlayerInterface player) {
+ super((instance) -> ApiLoader.getProvider(context).createMediaSession2Builder(
+ context, (Builder) instance, player));
}
}
/**
* Information of a controller.
*/
- // TODO(jaewan): Move implementation to the updatable.
public static final class ControllerInfo {
private final ControllerInfoProvider mProvider;
@@ -616,9 +702,9 @@
// TODO(jaewan): SystemApi
// TODO(jaewan): Also accept componentName to check notificaiton listener.
public ControllerInfo(Context context, int uid, int pid, String packageName,
- IMediaSession2Callback callback) {
+ IInterface callback) {
mProvider = ApiLoader.getProvider(context)
- .createMediaSession2ControllerInfoProvider(
+ .createMediaSession2ControllerInfo(
context, this, uid, pid, packageName, callback);
}
@@ -647,6 +733,9 @@
return mProvider.isTrusted_impl();
}
+ /**
+ * @hide
+ */
@SystemApi
public ControllerInfoProvider getProvider() {
return mProvider;
@@ -773,9 +862,9 @@
* @hide
*/
// TODO(jaewan): @SystemApi
- public static @Nullable CommandButton fromBundle(Bundle bundle) {
+ public static @Nullable CommandButton fromBundle(Context context, Bundle bundle) {
Builder builder = new Builder();
- builder.setCommand(Command.fromBundle(bundle.getBundle(KEY_COMMAND)));
+ builder.setCommand(Command.fromBundle(context, bundle.getBundle(KEY_COMMAND)));
builder.setIconResId(bundle.getInt(KEY_ICON_RES_ID, 0));
builder.setDisplayName(bundle.getString(KEY_DISPLAY_NAME));
builder.setExtra(bundle.getBundle(KEY_EXTRA));
@@ -845,8 +934,7 @@
/**
* Parameter for the playlist.
*/
- // TODO(jaewan): add fromBundle()/toBundle()
- public static class PlaylistParams {
+ public final static class PlaylistParams {
/**
* @hide
*/
@@ -901,28 +989,71 @@
*/
public static final int SHUFFLE_MODE_GROUP = 2;
- private @RepeatMode int mRepeatMode;
- private @ShuffleMode int mShuffleMode;
- private MediaMetadata2 mPlaylistMetadata;
+ private final MediaSession2Provider.PlaylistParamsProvider mProvider;
- public PlaylistParams(@RepeatMode int repeatMode, @ShuffleMode int shuffleMode,
- @Nullable MediaMetadata2 playlistMetadata) {
- mRepeatMode = repeatMode;
- mShuffleMode = shuffleMode;
- mPlaylistMetadata = playlistMetadata;
+ /**
+ * Instantiate {@link PlaylistParams}
+ *
+ * @param context context
+ * @param repeatMode repeat mode
+ * @param shuffleMode shuffle mode
+ * @param playlistMetadata metadata for the list
+ */
+ public PlaylistParams(@NonNull Context context, @RepeatMode int repeatMode,
+ @ShuffleMode int shuffleMode, @Nullable MediaMetadata2 playlistMetadata) {
+ mProvider = ApiLoader.getProvider(context).createMediaSession2PlaylistParams(
+ context, this, repeatMode, shuffleMode, playlistMetadata);
}
+ /**
+ * Create a new bundle for this object.
+ *
+ * @return
+ */
+ public @NonNull Bundle toBundle() {
+ return mProvider.toBundle_impl();
+ }
+
+ /**
+ * Create a new playlist params from the bundle that was previously returned by
+ * {@link #toBundle}.
+ *
+ * @param context context
+ * @return a new playlist params. Can be {@code null} for error.
+ */
+ public static @Nullable PlaylistParams fromBundle(
+ @NonNull Context context, @Nullable Bundle bundle) {
+ return ApiLoader.getProvider(context).fromBundle_PlaylistParams(context, bundle);
+ }
+
+ /**
+ * Get repeat mode
+ *
+ * @return repeat mode
+ * @see #REPEAT_MODE_NONE, #REPEAT_MODE_ONE, #REPEAT_MODE_ALL, #REPEAT_MODE_GROUP
+ */
public @RepeatMode int getRepeatMode() {
- return mRepeatMode;
+ return mProvider.getRepeatMode_impl();
}
+ /**
+ * Get shuffle mode
+ *
+ * @return shuffle mode
+ * @see #SHUFFLE_MODE_NONE, #SHUFFLE_MODE_ALL, #SHUFFLE_MODE_GROUP
+ */
public @ShuffleMode int getShuffleMode() {
- return mShuffleMode;
+ return mProvider.getShuffleMode_impl();
}
- public MediaMetadata2 getPlaylistMetadata() {
- return mPlaylistMetadata;
+ /**
+ * Get metadata for the playlist
+ *
+ * @return metadata. Can be {@code null}
+ */
+ public @Nullable MediaMetadata2 getPlaylistMetadata() {
+ return mProvider.getPlaylistMetadata_impl();
}
}
@@ -940,32 +1071,23 @@
* framework had to add heuristics to figure out if an app is
* @hide
*/
-
- MediaSession2(Context context, MediaPlayerBase player, String id, VolumeProvider volumeProvider,
- int ratingType, PendingIntent sessionActivity, Executor callbackExecutor,
- SessionCallback callback) {
+ @SystemApi
+ public MediaSession2(MediaSession2Provider provider) {
super();
- mProvider = createProvider(context, player, id, volumeProvider, ratingType, sessionActivity,
- callbackExecutor, callback
- );
+ mProvider = provider;
}
- MediaSession2Provider createProvider(Context context, MediaPlayerBase player, String id,
- VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity,
- Executor callbackExecutor, SessionCallback callback) {
- return ApiLoader.getProvider(context)
- .createMediaSession2(context, this, player, id, volumeProvider, ratingType,
- sessionActivity, callbackExecutor, callback);
- }
-
+ /**
+ * @hide
+ */
@SystemApi
public MediaSession2Provider getProvider() {
return mProvider;
}
/**
- * Set the underlying {@link MediaPlayerBase} for this session to dispatch incoming event to.
- * Events from the {@link MediaController2} will be sent directly to the underlying
+ * Set the underlying {@link MediaPlayerInterface} for this session to dispatch incoming event
+ * to. Events from the {@link MediaController2} will be sent directly to the underlying
* player on the {@link Handler} where the session is created on.
* <p>
* If the new player is successfully set, {@link PlaybackListener}
@@ -974,22 +1096,23 @@
* You can also specify a volume provider. If so, playback in the player is considered as
* remote playback.
*
- * @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
+ * @param player a {@link MediaPlayerInterface} that handles actual media playback in your app.
* @throws IllegalArgumentException if the player is {@code null}.
*/
- public void setPlayer(@NonNull MediaPlayerBase player) {
+ public void setPlayer(@NonNull MediaPlayerInterface player) {
mProvider.setPlayer_impl(player);
}
/**
- * Set the underlying {@link MediaPlayerBase} with the volume provider for remote playback.
+ * Set the underlying {@link MediaPlayerInterface} with the volume provider for remote playback.
*
- * @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
+ * @param player a {@link MediaPlayerInterface} that handles actual media playback in your app.
* @param volumeProvider a volume provider
- * @see #setPlayer(MediaPlayerBase)
+ * @see #setPlayer(MediaPlayerInterface)
* @see Builder#setVolumeProvider(VolumeProvider)
*/
- public void setPlayer(@NonNull MediaPlayerBase player, @NonNull VolumeProvider volumeProvider) {
+ public void setPlayer(@NonNull MediaPlayerInterface player,
+ @NonNull VolumeProvider volumeProvider) {
mProvider.setPlayer_impl(player, volumeProvider);
}
@@ -1001,7 +1124,8 @@
/**
* @return player
*/
- public @Nullable MediaPlayerBase getPlayer() {
+ public @Nullable
+ MediaPlayerInterface getPlayer() {
return mProvider.getPlayer_impl();
}
@@ -1018,15 +1142,6 @@
}
/**
- * Sets the {@link AudioAttributes} to be used during the playback of the video.
- *
- * @param attributes non-null <code>AudioAttributes</code>.
- */
- public void setAudioAttributes(@NonNull AudioAttributes attributes) {
- mProvider.setAudioAttributes_impl(attributes);
- }
-
- /**
* Sets which type of audio focus will be requested during the playback, or configures playback
* to not request audio focus. Valid values for focus requests are
* {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
@@ -1205,7 +1320,73 @@
// To match with KEYCODE_MEDIA_SKIP_BACKWARD
}
- public void setPlaylist(@NonNull List<MediaItem2> playlist, @NonNull PlaylistParams param) {
- mProvider.setPlaylist_impl(playlist, param);
+ /**
+ * Sets a list of {@link MediaItem2} as the current play list.
+ *
+ * @param playlist A list of {@link MediaItem2} objects to set as a play list.
+ * @throws IllegalArgumentException if given {@param playlist} is null.
+ */
+ public void setPlaylist(@NonNull List<MediaItem2> playlist) {
+ mProvider.setPlaylist_impl(playlist);
+ }
+
+ /**
+ * Returns the playlist which is lastly set.
+ */
+ public List<MediaItem2> getPlaylist() {
+ return mProvider.getPlaylist_impl();
+ }
+
+ /**
+ * Sets the {@link PlaylistParams} for the current play list. Repeat/shuffle mode and metadata
+ * for the list can be set by calling this method.
+ *
+ * @param params A {@link PlaylistParams} object to set.
+ * @throws IllegalArgumentException if given {@param param} is null.
+ */
+ public void setPlaylistParams(PlaylistParams params) {
+ mProvider.setPlaylistParams_impl(params);
+ }
+
+ /**
+ * Returns the {@link PlaylistParams} for the current play list.
+ * Returns {@code null} if not set.
+ */
+ public PlaylistParams getPlaylistParams() {
+ return mProvider.getPlaylistParams_impl();
+ }
+
+ /*
+ * Add a {@link PlaybackListener} to listen changes in the underlying
+ * {@link MediaPlayerInterface}. Listener will be called immediately to tell the current value.
+ * <p>
+ * Added listeners will be also called when the underlying player is changed.
+ *
+ * @param executor the call listener
+ * @param listener the listener that will be run
+ * @throws IllegalArgumentException when either the listener or handler is {@code null}.
+ */
+ public void addPlaybackListener(@NonNull @CallbackExecutor Executor executor,
+ @NonNull PlaybackListener listener) {
+ mProvider.addPlaybackListener_impl(executor, listener);
+ }
+
+ /**
+ * Remove previously added {@link PlaybackListener}.
+ *
+ * @param listener the listener to be removed
+ * @throws IllegalArgumentException if the listener is {@code null}.
+ */
+ public void removePlaybackListener(@NonNull PlaybackListener listener) {
+ mProvider.removePlaybackListener_impl(listener);
+ }
+
+ /**
+ * Return the {@link PlaybackState2} from the player.
+ *
+ * @return playback state
+ */
+ public PlaybackState2 getPlaybackState() {
+ return mProvider.getPlaybackState_impl();
}
}
diff --git a/media/java/android/media/PlaybackState2.java b/media/java/android/media/PlaybackState2.java
index 04f211d..627974a 100644
--- a/media/java/android/media/PlaybackState2.java
+++ b/media/java/android/media/PlaybackState2.java
@@ -17,28 +17,68 @@
package android.media;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.update.ApiLoader;
+import android.media.update.PlaybackState2Provider;
import android.os.Bundle;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
- * Playback state for a {@link MediaPlayerBase}, to be shared between {@link MediaSession2} and
+ * Playback state for a {@link MediaPlayerInterface}, to be shared between {@link MediaSession2} and
* {@link MediaController2}. This includes a playback state {@link #STATE_PLAYING},
* the current playback position and extra.
* @hide
*/
public final class PlaybackState2 {
- private static final String TAG = "PlaybackState2";
-
- private static final String KEY_STATE = "android.media.playbackstate2.state";
-
+ // Similar to the PlaybackState2 with following changes
+ // - Not implement Parcelable and added from/toBundle()
+ // - Removed playback state that doesn't match with the MediaPlayer2
+ // Full list should be finalized when the MediaPlayer2 has getter for the playback state.
+ // Here's table for the MP2 state and PlaybackState2.State.
+ // +----------------------------------------+----------------------------------------+
+ // | MediaPlayer2 state | Matching PlaybackState2.State |
+ // | (Names are from MP2' Javadoc) | |
+ // +----------------------------------------+----------------------------------------+
+ // | Idle: Just finished creating MP2 | STATE_NONE |
+ // | or reset() is called | |
+ // +----------------------------------------+----------------------------------------+
+ // | Initialized: setDataSource/Playlist | N/A (Session/Controller don't |
+ // | | differentiate with Prepared) |
+ // +----------------------------------------+----------------------------------------+
+ // | Prepared: Prepared after initialized | STATE_PAUSED |
+ // +----------------------------------------+----------------------------------------+
+ // | Started: Started playback | STATE_PLAYING |
+ // +----------------------------------------+----------------------------------------+
+ // | Paused: Paused playback | STATE_PAUSED |
+ // +----------------------------------------+----------------------------------------+
+ // | PlaybackCompleted: Playback is done | STATE_PAUSED |
+ // +----------------------------------------+----------------------------------------+
+ // | Stopped: MP2.stop() is called. | STATE_STOPPED |
+ // | prepare() is needed to play again | |
+ // | (Seemingly the same as initialized | |
+ // | because cannot set data source | |
+ // | after this) | |
+ // +----------------------------------------+----------------------------------------+
+ // | Error: an API is called in a state | STATE_ERROR |
+ // | that the API isn't supported | |
+ // +----------------------------------------+----------------------------------------+
+ // | End: MP2.close() is called to release | N/A (MediaSession will be gone) |
+ // | MP2. Cannot be reused anymore | |
+ // +----------------------------------------+----------------------------------------+
+ // | Started, but | STATE_BUFFERING |
+ // | EventCallback.onBufferingUpdate() | |
+ // +----------------------------------------+----------------------------------------+
+ // - Removed actions and custom actions.
+ // - Repeat mode / shuffle mode is now in the PlaylistParams
// TODO(jaewan): Replace states from MediaPlayer2
/**
* @hide
*/
- @IntDef({STATE_NONE, STATE_STOPPED, STATE_PREPARED, STATE_PAUSED, STATE_PLAYING,
- STATE_FINISH, STATE_BUFFERING, STATE_ERROR})
+ @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_BUFFERING, STATE_ERROR})
@Retention(RetentionPolicy.SOURCE)
public @interface State {}
@@ -54,73 +94,46 @@
public final static int STATE_STOPPED = 1;
/**
- * State indicating this item is currently prepared
- */
- public final static int STATE_PREPARED = 2;
-
- /**
* State indicating this item is currently paused.
*/
- public final static int STATE_PAUSED = 3;
+ public final static int STATE_PAUSED = 2;
/**
* State indicating this item is currently playing.
*/
- public final static int STATE_PLAYING = 4;
-
- /**
- * State indicating the playback reaches the end of the item.
- */
- public final static int STATE_FINISH = 5;
+ public final static int STATE_PLAYING = 3;
/**
* State indicating this item is currently buffering and will begin playing
* when enough data has buffered.
*/
- public final static int STATE_BUFFERING = 6;
+ public final static int STATE_BUFFERING = 4;
/**
* State indicating this item is currently in an error state. The error
* message should also be set when entering this state.
*/
- public final static int STATE_ERROR = 7;
+ public final static int STATE_ERROR = 5;
/**
* Use this value for the position to indicate the position is not known.
*/
public final static long PLAYBACK_POSITION_UNKNOWN = -1;
- private final int mState;
- private final long mPosition;
- private final long mBufferedPosition;
- private final float mSpeed;
- private final CharSequence mErrorMessage;
- private final long mUpdateTime;
- private final long mActiveItemId;
+ private final PlaybackState2Provider mProvider;
- public PlaybackState2(int state, long position, long updateTime, float speed,
- long bufferedPosition, long activeItemId, CharSequence error) {
- mState = state;
- mPosition = position;
- mSpeed = speed;
- mUpdateTime = updateTime;
- mBufferedPosition = bufferedPosition;
- mActiveItemId = activeItemId;
- mErrorMessage = error;
+ // TODO(jaewan): Better error handling?
+ // E.g. media item at #2 has issue, but continue playing #3
+ // login error. fire intent xxx to login
+ public PlaybackState2(@NonNull Context context, int state, long position, long updateTime,
+ float speed, long bufferedPosition, long activeItemId, CharSequence error) {
+ mProvider = ApiLoader.getProvider(context).createPlaybackState2(context, this, state,
+ position, updateTime, speed, bufferedPosition, activeItemId, error);
}
@Override
public String toString() {
- StringBuilder bob = new StringBuilder("PlaybackState {");
- bob.append("state=").append(mState);
- bob.append(", position=").append(mPosition);
- bob.append(", buffered position=").append(mBufferedPosition);
- bob.append(", speed=").append(mSpeed);
- bob.append(", updated=").append(mUpdateTime);
- bob.append(", active item id=").append(mActiveItemId);
- bob.append(", error=").append(mErrorMessage);
- bob.append("}");
- return bob.toString();
+ return mProvider.toString_impl();
}
/**
@@ -128,22 +141,24 @@
* <ul>
* <li> {@link PlaybackState2#STATE_NONE}</li>
* <li> {@link PlaybackState2#STATE_STOPPED}</li>
- * <li> {@link PlaybackState2#STATE_PLAYING}</li>
+ * <li> {@link PlaybackState2#STATE_PREPARED}</li>
* <li> {@link PlaybackState2#STATE_PAUSED}</li>
+ * <li> {@link PlaybackState2#STATE_PLAYING}</li>
+ * <li> {@link PlaybackState2#STATE_FINISH}</li>
* <li> {@link PlaybackState2#STATE_BUFFERING}</li>
* <li> {@link PlaybackState2#STATE_ERROR}</li>
* </ul>
*/
@State
public int getState() {
- return mState;
+ return mProvider.getState_impl();
}
/**
* Get the current playback position in ms.
*/
public long getPosition() {
- return mPosition;
+ return mProvider.getPosition_impl();
}
/**
@@ -152,7 +167,7 @@
* content.
*/
public long getBufferedPosition() {
- return mBufferedPosition;
+ return mProvider.getBufferedPosition_impl();
}
/**
@@ -163,7 +178,7 @@
* @return The current speed of playback.
*/
public float getPlaybackSpeed() {
- return mSpeed;
+ return mProvider.getPlaybackSpeed_impl();
}
/**
@@ -171,7 +186,7 @@
* {@link PlaybackState2#STATE_ERROR}.
*/
public CharSequence getErrorMessage() {
- return mErrorMessage;
+ return mProvider.getErrorMessage_impl();
}
/**
@@ -181,7 +196,7 @@
* @return The last time the position was updated.
*/
public long getLastPositionUpdateTime() {
- return mUpdateTime;
+ return mProvider.getLastPositionUpdateTime_impl();
}
/**
@@ -190,26 +205,26 @@
* @return The id of the currently active item in the queue
*/
public long getCurrentPlaylistItemIndex() {
- return mActiveItemId;
+ return mProvider.getCurrentPlaylistItemIndex_impl();
}
/**
- * @return Bundle object for this to share between processes.
+ * Returns this object as a bundle to share between processes.
*/
- public Bundle toBundle() {
- // TODO(jaewan): Include other variables.
- Bundle bundle = new Bundle();
- bundle.putInt(KEY_STATE, mState);
- return bundle;
+ public @NonNull Bundle toBundle() {
+ return mProvider.toBundle_impl();
}
/**
- * @param bundle input
- * @return
+ * Creates an instance from a bundle which is previously created by {@link #toBundle()}.
+ *
+ * @param context context
+ * @param bundle A bundle created by {@link #toBundle()}.
+ * @return A new {@link PlaybackState2} instance. Returns {@code null} if the given
+ * {@param bundle} is null, or if the {@param bundle} has no playback state parameters.
*/
- public static PlaybackState2 fromBundle(Bundle bundle) {
- // TODO(jaewan): Include other variables.
- final int state = bundle.getInt(KEY_STATE);
- return new PlaybackState2(state, 0, 0, 0, 0, 0, null);
+ public @Nullable static PlaybackState2 fromBundle(@NonNull Context context,
+ @Nullable Bundle bundle) {
+ return ApiLoader.getProvider(context).fromBundle_PlaybackState2(context, bundle);
}
}
\ No newline at end of file
diff --git a/media/java/android/media/Rating2.java b/media/java/android/media/Rating2.java
index 93aea6f..4f77ecd 100644
--- a/media/java/android/media/Rating2.java
+++ b/media/java/android/media/Rating2.java
@@ -16,7 +16,13 @@
package android.media;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.media.update.ApiLoader;
+import android.media.update.Rating2Provider;
import android.os.Bundle;
import android.util.Log;
@@ -33,10 +39,8 @@
* @hide
*/
public final class Rating2 {
- private static final String TAG = "Rating2";
-
- private static final String KEY_STYLE = "android.media.rating2.style";
- private static final String KEY_VALUE = "android.media.rating2.value";
+ // Mostly same as the android.media.Rating, but it's no longer implements Parcelable for
+ // updatable support.
/**
* @hide
@@ -91,31 +95,48 @@
*/
public final static int RATING_PERCENTAGE = 6;
- private final static float RATING_NOT_RATED = -1.0f;
+ private final Rating2Provider mProvider;
- private final int mRatingStyle;
-
- private final float mRatingValue;
-
- private Rating2(@Style int ratingStyle, float rating) {
- mRatingStyle = ratingStyle;
- mRatingValue = rating;
+ /**
+ * @hide
+ */
+ @SystemApi
+ public Rating2(@NonNull Rating2Provider provider) {
+ mProvider = provider;
}
@Override
public String toString() {
- return "Rating2:style=" + mRatingStyle + " rating="
- + (mRatingValue < 0.0f ? "unrated" : String.valueOf(mRatingValue));
+ return mProvider.toString_impl();
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi
+ public Rating2Provider getProvider() {
+ return mProvider;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return mProvider.equals_impl(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return mProvider.hashCode_impl();
}
/**
* Create an instance from bundle object, previoulsy created by {@link #toBundle()}
*
+ * @param context context
* @param bundle bundle
- * @return new Rating2 instance
+ * @return new Rating2 instance or {@code null} for error
*/
- public static Rating2 fromBundle(Bundle bundle) {
- return new Rating2(bundle.getInt(KEY_STYLE), bundle.getFloat(KEY_VALUE));
+ public static Rating2 fromBundle(@NonNull Context context, @Nullable Bundle bundle) {
+ return ApiLoader.getProvider(context).fromBundle_Rating2(context, bundle);
}
/**
@@ -123,55 +144,45 @@
* @return bundle of this object
*/
public Bundle toBundle() {
- Bundle bundle = new Bundle();
- bundle.putInt(KEY_STYLE, mRatingStyle);
- bundle.putFloat(KEY_VALUE, mRatingValue);
- return bundle;
+ return mProvider.toBundle_impl();
}
/**
* Return a Rating2 instance with no rating.
* Create and return a new Rating2 instance with no rating known for the given
* rating style.
+ * @param context context
* @param ratingStyle one of {@link #RATING_HEART}, {@link #RATING_THUMB_UP_DOWN},
* {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, {@link #RATING_5_STARS},
* or {@link #RATING_PERCENTAGE}.
* @return null if an invalid rating style is passed, a new Rating2 instance otherwise.
*/
- public static Rating2 newUnratedRating(@Style int ratingStyle) {
- switch(ratingStyle) {
- case RATING_HEART:
- case RATING_THUMB_UP_DOWN:
- case RATING_3_STARS:
- case RATING_4_STARS:
- case RATING_5_STARS:
- case RATING_PERCENTAGE:
- return new Rating2(ratingStyle, RATING_NOT_RATED);
- default:
- return null;
- }
+ public static @Nullable Rating2 newUnratedRating(@NonNull Context context, @Style int ratingStyle) {
+ return ApiLoader.getProvider(context).newUnratedRating_Rating2(context, ratingStyle);
}
/**
* Return a Rating2 instance with a heart-based rating.
* Create and return a new Rating2 instance with a rating style of {@link #RATING_HEART},
* and a heart-based rating.
+ * @param context context
* @param hasHeart true for a "heart selected" rating, false for "heart unselected".
* @return a new Rating2 instance.
*/
- public static Rating2 newHeartRating(boolean hasHeart) {
- return new Rating2(RATING_HEART, hasHeart ? 1.0f : 0.0f);
+ public static @Nullable Rating2 newHeartRating(@NonNull Context context, boolean hasHeart) {
+ return ApiLoader.getProvider(context).newHeartRating_Rating2(context, hasHeart);
}
/**
* Return a Rating2 instance with a thumb-based rating.
* Create and return a new Rating2 instance with a {@link #RATING_THUMB_UP_DOWN}
* rating style, and a "thumb up" or "thumb down" rating.
+ * @param context context
* @param thumbIsUp true for a "thumb up" rating, false for "thumb down".
* @return a new Rating2 instance.
*/
- public static Rating2 newThumbRating(boolean thumbIsUp) {
- return new Rating2(RATING_THUMB_UP_DOWN, thumbIsUp ? 1.0f : 0.0f);
+ public static @Nullable Rating2 newThumbRating(@NonNull Context context, boolean thumbIsUp) {
+ return ApiLoader.getProvider(context).newThumbRating_Rating2(context, thumbIsUp);
}
/**
@@ -179,6 +190,7 @@
* Create and return a new Rating2 instance with one of the star-base rating styles
* and the given integer or fractional number of stars. Non integer values can for instance
* be used to represent an average rating value, which might not be an integer number of stars.
+ * @param context context
* @param starRatingStyle one of {@link #RATING_3_STARS}, {@link #RATING_4_STARS},
* {@link #RATING_5_STARS}.
* @param starRating a number ranging from 0.0f to 3.0f, 4.0f or 5.0f according to
@@ -186,51 +198,30 @@
* @return null if the rating style is invalid, or the rating is out of range,
* a new Rating2 instance otherwise.
*/
- public static Rating2 newStarRating(@StarStyle int starRatingStyle, float starRating) {
- float maxRating = -1.0f;
- switch(starRatingStyle) {
- case RATING_3_STARS:
- maxRating = 3.0f;
- break;
- case RATING_4_STARS:
- maxRating = 4.0f;
- break;
- case RATING_5_STARS:
- maxRating = 5.0f;
- break;
- default:
- Log.e(TAG, "Invalid rating style (" + starRatingStyle + ") for a star rating");
- return null;
- }
- if ((starRating < 0.0f) || (starRating > maxRating)) {
- Log.e(TAG, "Trying to set out of range star-based rating");
- return null;
- }
- return new Rating2(starRatingStyle, starRating);
+ public static @Nullable Rating2 newStarRating(@NonNull Context context,
+ @StarStyle int starRatingStyle, float starRating) {
+ return ApiLoader.getProvider(context).newStarRating_Rating2(
+ context, starRatingStyle, starRating);
}
/**
* Return a Rating2 instance with a percentage-based rating.
* Create and return a new Rating2 instance with a {@link #RATING_PERCENTAGE}
* rating style, and a rating of the given percentage.
+ * @param context context
* @param percent the value of the rating
* @return null if the rating is out of range, a new Rating2 instance otherwise.
*/
- public static Rating2 newPercentageRating(float percent) {
- if ((percent < 0.0f) || (percent > 100.0f)) {
- Log.e(TAG, "Invalid percentage-based rating value");
- return null;
- } else {
- return new Rating2(RATING_PERCENTAGE, percent);
- }
+ public static @Nullable Rating2 newPercentageRating(@NonNull Context context, float percent) {
+ return ApiLoader.getProvider(context).newPercentageRating_Rating2(context, percent);
}
/**
* Return whether there is a rating value available.
- * @return true if the instance was not created with {@link #newUnratedRating(int)}.
+ * @return true if the instance was not created with {@link #newUnratedRating(Context, int)}.
*/
public boolean isRated() {
- return mRatingValue >= 0.0f;
+ return mProvider.isRated_impl();
}
/**
@@ -241,7 +232,7 @@
*/
@Style
public int getRatingStyle() {
- return mRatingStyle;
+ return mProvider.getRatingStyle_impl();
}
/**
@@ -250,11 +241,7 @@
* if the rating style is not {@link #RATING_HEART} or if it is unrated.
*/
public boolean hasHeart() {
- if (mRatingStyle != RATING_HEART) {
- return false;
- } else {
- return (mRatingValue == 1.0f);
- }
+ return mProvider.hasHeart_impl();
}
/**
@@ -263,11 +250,7 @@
* if the rating style is not {@link #RATING_THUMB_UP_DOWN} or if it is unrated.
*/
public boolean isThumbUp() {
- if (mRatingStyle != RATING_THUMB_UP_DOWN) {
- return false;
- } else {
- return (mRatingValue == 1.0f);
- }
+ return mProvider.isThumbUp_impl();
}
/**
@@ -276,16 +259,7 @@
* not star-based, or if it is unrated.
*/
public float getStarRating() {
- switch (mRatingStyle) {
- case RATING_3_STARS:
- case RATING_4_STARS:
- case RATING_5_STARS:
- if (isRated()) {
- return mRatingValue;
- }
- default:
- return -1.0f;
- }
+ return mProvider.getStarRating_impl();
}
/**
@@ -294,10 +268,6 @@
* not percentage-based, or if it is unrated.
*/
public float getPercentRating() {
- if ((mRatingStyle != RATING_PERCENTAGE) || !isRated()) {
- return -1.0f;
- } else {
- return mRatingValue;
- }
+ return mProvider.getPercentRating_impl();
}
}
diff --git a/media/java/android/media/SessionPlayer2.java b/media/java/android/media/SessionPlayer2.java
new file mode 100644
index 0000000..60acf16
--- /dev/null
+++ b/media/java/android/media/SessionPlayer2.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.media.MediaSession2.PlaylistParams;
+import android.media.update.ApiLoader;
+import android.media.update.SessionPlayer2Provider;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Implementation of the {@link MediaPlayerInterface} which is backed by the {@link MediaPlayer2}
+ * @hide
+ */
+public class SessionPlayer2 implements MediaPlayerInterface {
+ private final SessionPlayer2Provider mProvider;
+
+ public SessionPlayer2(Context context) {
+ mProvider = ApiLoader.getProvider(context).createSessionPlayer2(context, this);
+ }
+
+ @Override
+ public void play() {
+ mProvider.play_impl();
+ }
+
+ @Override
+ public void prepare() {
+ mProvider.prepare_impl();
+ }
+
+ @Override
+ public void pause() {
+ mProvider.pause_impl();
+ }
+
+ @Override
+ public void stop() {
+ mProvider.stop_impl();
+ }
+
+ @Override
+ public void skipToPrevious() {
+ mProvider.skipToPrevious_impl();
+ }
+
+ @Override
+ public void skipToNext() {
+ mProvider.skipToNext_impl();
+ }
+
+ @Override
+ public void seekTo(long pos) {
+ mProvider.seekTo_impl(pos);
+ }
+
+ @Override
+ public void fastForward() {
+ mProvider.fastForward_impl();
+ }
+
+ @Override
+ public void rewind() {
+ mProvider.rewind_impl();
+ }
+
+ @Override
+ public PlaybackState2 getPlaybackState() {
+ return mProvider.getPlaybackState_impl();
+ }
+
+ @Override
+ public void setAudioAttributes(AudioAttributes attributes) {
+ mProvider.setAudioAttributes_impl(attributes);
+ }
+
+ @Override
+ public AudioAttributes getAudioAttributes() {
+ return mProvider.getAudioAttributes_impl();
+ }
+
+ @Override
+ public void setPlaylist(List<MediaItem2> playlist) {
+ mProvider.setPlaylist_impl(playlist);
+ }
+
+ @Override
+ public List<MediaItem2> getPlaylist() {
+ return mProvider.getPlaylist_impl();
+ }
+
+ @Override
+ public void setCurrentPlaylistItem(int index) {
+ mProvider.setCurrentPlaylistItem_impl(index);
+ }
+
+ @Override
+ public void setPlaylistParams(PlaylistParams params) {
+ mProvider.setPlaylistParams_impl(params);
+ }
+
+ @Override
+ public void addPlaylistItem(int index, MediaItem2 item) {
+ mProvider.addPlaylistItem_impl(index, item);
+ }
+
+ @Override
+ public void removePlaylistItem(MediaItem2 item) {
+ mProvider.removePlaylistItem_impl(item);
+ }
+
+ @Override
+ public PlaylistParams getPlaylistParams() {
+ return mProvider.getPlaylistParams_impl();
+ }
+
+ @Override
+ public void addPlaybackListener(Executor executor, PlaybackListener listener) {
+ mProvider.addPlaybackListener_impl(executor, listener);
+ }
+
+ @Override
+ public void removePlaybackListener(PlaybackListener listener) {
+ mProvider.removePlaybackListener_impl(listener);
+ }
+
+ public MediaPlayer2 getPlayer() {
+ return mProvider.getPlayer_impl();
+ }
+
+ @SystemApi
+ public SessionPlayer2Provider getProvider() {
+ return mProvider;
+ }
+}
diff --git a/media/java/android/media/SessionToken2.java b/media/java/android/media/SessionToken2.java
index 0abb852..2c2090c 100644
--- a/media/java/android/media/SessionToken2.java
+++ b/media/java/android/media/SessionToken2.java
@@ -18,11 +18,12 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.Context;
import android.media.session.MediaSessionManager;
+import android.media.update.ApiLoader;
+import android.media.update.SessionToken2Provider;
import android.os.Bundle;
-import android.os.IBinder;
-import android.text.TextUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -37,7 +38,6 @@
* It can be also obtained by {@link MediaSessionManager}.
* @hide
*/
-// TODO(jaewan): Move Token to updatable!
public final class SessionToken2 {
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {TYPE_SESSION, TYPE_SESSION_SERVICE, TYPE_LIBRARY_SERVICE})
@@ -48,91 +48,88 @@
public static final int TYPE_SESSION_SERVICE = 1;
public static final int TYPE_LIBRARY_SERVICE = 2;
- private static final String KEY_TYPE = "android.media.token.type";
- private static final String KEY_PACKAGE_NAME = "android.media.token.package_name";
- private static final String KEY_SERVICE_NAME = "android.media.token.service_name";
- private static final String KEY_ID = "android.media.token.id";
- private static final String KEY_SESSION_BINDER = "android.media.token.session_binder";
+ private final SessionToken2Provider mProvider;
- private final @TokenType int mType;
- private final String mPackageName;
- private final String mServiceName;
- private final String mId;
- private final IMediaSession2 mSessionBinder;
+ // From the return value of android.os.Process.getUidForName(String) when error
+ private static final int UID_UNKNOWN = -1;
+
+ /**
+ * Constructor for the token. You can only create token for session service or library service
+ * to use by {@link MediaController2} or {@link MediaBrowser2}.
+ *
+ * @param context context
+ * @param packageName package name
+ * @param serviceName name of service. Can be {@code null} if it's not an service.
+ */
+ public SessionToken2(@NonNull Context context, @NonNull String packageName,
+ @NonNull String serviceName) {
+ this(context, packageName, serviceName, UID_UNKNOWN);
+ }
+
+ /**
+ * Constructor for the token. You can only create token for session service or library service
+ * to use by {@link MediaController2} or {@link MediaBrowser2}.
+ *
+ * @param context context
+ * @param packageName package name
+ * @param serviceName name of service. Can be {@code null} if it's not an service.
+ * @param uid uid of the app.
+ * @hide
+ */
+ public SessionToken2(@NonNull Context context, @NonNull String packageName,
+ @NonNull String serviceName, int uid) {
+ mProvider = ApiLoader.getProvider(context).createSessionToken2(
+ context, this, packageName, serviceName, uid);
+ }
/**
* Constructor for the token.
- *
- * @hide
- * @param type type
- * @param packageName package name
- * @param id id
- * @param serviceName name of service. Can be {@code null} if it's not an service.
- * @param sessionBinder binder for this session. Can be {@code null} if it's service.
* @hide
*/
- // TODO(jaewan): UID is also needed.
- // TODO(jaewan): Unhide
- public SessionToken2(@TokenType int type, @NonNull String packageName, @NonNull String id,
- @Nullable String serviceName, @Nullable IMediaSession2 sessionBinder) {
- // TODO(jaewan): Add sanity check.
- mType = type;
- mPackageName = packageName;
- mId = id;
- mServiceName = serviceName;
- mSessionBinder = sessionBinder;
+ @SystemApi
+ public SessionToken2(@NonNull SessionToken2Provider provider) {
+ mProvider = provider;
}
+ @Override
public int hashCode() {
- final int prime = 31;
- return mType
- + prime * (mPackageName.hashCode()
- + prime * (mId.hashCode()
- + prime * ((mServiceName != null ? mServiceName.hashCode() : 0)
- + prime * (mSessionBinder != null ? mSessionBinder.asBinder().hashCode() : 0))));
+ return mProvider.hashCode_impl();
}
@Override
public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- SessionToken2 other = (SessionToken2) obj;
- if (!mPackageName.equals(other.getPackageName())
- || !mServiceName.equals(other.getServiceName())
- || !mId.equals(other.getId())
- || mType != other.getType()) {
- return false;
- }
- if (mSessionBinder == other.getSessionBinder()) {
- return true;
- } else if (mSessionBinder == null || other.getSessionBinder() == null) {
- return false;
- }
- return mSessionBinder.asBinder().equals(other.getSessionBinder().asBinder());
+ return mProvider.equals_impl(obj);
}
@Override
public String toString() {
- return "SessionToken {pkg=" + mPackageName + " id=" + mId + " type=" + mType
- + " service=" + mServiceName + " binder=" + mSessionBinder + "}";
+ return mProvider.toString_impl();
+ }
+
+ @SystemApi
+ public SessionToken2Provider getProvider() {
+ return mProvider;
+ }
+
+ /**
+ * @return uid of the session
+ */
+ public int getUid() {
+ return mProvider.getUid_impl();
}
/**
* @return package name
*/
public String getPackageName() {
- return mPackageName;
+ return mProvider.getPackageName_impl();
}
/**
* @return id
*/
public String getId() {
- return mId;
+ return mProvider.getId_imp();
}
/**
@@ -141,82 +138,23 @@
* @see #TYPE_SESSION_SERVICE
*/
public @TokenType int getType() {
- return mType;
- }
-
- /**
- * @return session binder.
- * @hide
- */
- public @Nullable IMediaSession2 getSessionBinder() {
- return mSessionBinder;
- }
-
- /**
- * @return service name if it's session service.
- * @hide
- */
- public @Nullable String getServiceName() {
- return mServiceName;
+ return mProvider.getType_impl();
}
/**
* Create a token from the bundle, exported by {@link #toBundle()}.
- *
* @param bundle
* @return
*/
- public static SessionToken2 fromBundle(@NonNull Bundle bundle) {
- if (bundle == null) {
- return null;
- }
- final @TokenType int type = bundle.getInt(KEY_TYPE, -1);
- final String packageName = bundle.getString(KEY_PACKAGE_NAME);
- final String serviceName = bundle.getString(KEY_SERVICE_NAME);
- final String id = bundle.getString(KEY_ID);
- final IBinder sessionBinder = bundle.getBinder(KEY_SESSION_BINDER);
-
- // Sanity check.
- switch (type) {
- case TYPE_SESSION:
- if (!(sessionBinder instanceof IMediaSession2)) {
- throw new IllegalArgumentException("Session needs sessionBinder");
- }
- break;
- case TYPE_SESSION_SERVICE:
- if (TextUtils.isEmpty(serviceName)) {
- throw new IllegalArgumentException("Session service needs service name");
- }
- if (sessionBinder != null && !(sessionBinder instanceof IMediaSession2)) {
- throw new IllegalArgumentException("Invalid session binder");
- }
- break;
- default:
- throw new IllegalArgumentException("Invalid type");
- }
- if (TextUtils.isEmpty(packageName) || id == null) {
- throw new IllegalArgumentException("Package name nor ID cannot be null.");
- }
- // TODO(jaewan): Revisit here when we add connection callback to the session for individual
- // controller's permission check. With it, sessionBinder should be available
- // if and only if for session, not session service.
- return new SessionToken2(type, packageName, id, serviceName,
- sessionBinder != null ? IMediaSession2.Stub.asInterface(sessionBinder) : null);
+ public static SessionToken2 fromBundle(@NonNull Context context, @NonNull Bundle bundle) {
+ return ApiLoader.getProvider(context).SessionToken2_fromBundle(context, bundle);
}
/**
* Create a {@link Bundle} from this token to share it across processes.
- *
* @return Bundle
*/
public Bundle toBundle() {
- Bundle bundle = new Bundle();
- bundle.putString(KEY_PACKAGE_NAME, mPackageName);
- bundle.putString(KEY_SERVICE_NAME, mServiceName);
- bundle.putString(KEY_ID, mId);
- bundle.putInt(KEY_TYPE, mType);
- bundle.putBinder(KEY_SESSION_BINDER,
- mSessionBinder != null ? mSessionBinder.asBinder() : null);
- return bundle;
+ return mProvider.toBundle_impl();
}
}
diff --git a/media/java/android/media/VolumeProvider2.java b/media/java/android/media/VolumeProvider2.java
new file mode 100644
index 0000000..00746e2
--- /dev/null
+++ b/media/java/android/media/VolumeProvider2.java
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.media.update.ApiLoader;
+import android.media.update.VolumeProvider2Provider;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Handles requests to adjust or set the volume on a session. This is also used
+ * to push volume updates back to the session. The provider must call
+ * {@link #setCurrentVolume(int)} each time the volume being provided changes.
+ * <p>
+ * You can set a volume provider on a session by calling
+ * {@link MediaSession2#setPlayer(MediaPlayerInterface, VolumeProvider)}.
+ *
+ * @hide
+ */
+public abstract class VolumeProvider2 {
+
+ /**
+ * @hide
+ */
+ @IntDef({VOLUME_CONTROL_FIXED, VOLUME_CONTROL_RELATIVE, VOLUME_CONTROL_ABSOLUTE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ControlType {}
+
+ /**
+ * The volume is fixed and can not be modified. Requests to change volume
+ * should be ignored.
+ */
+ public static final int VOLUME_CONTROL_FIXED = 0;
+
+ /**
+ * The volume control uses relative adjustment via
+ * {@link #onAdjustVolume(int)}. Attempts to set the volume to a specific
+ * value should be ignored.
+ */
+ public static final int VOLUME_CONTROL_RELATIVE = 1;
+
+ /**
+ * The volume control uses an absolute value. It may be adjusted using
+ * {@link #onAdjustVolume(int)} or set directly using
+ * {@link #onSetVolumeTo(int)}.
+ */
+ public static final int VOLUME_CONTROL_ABSOLUTE = 2;
+
+ private final VolumeProvider2Provider mProvider;
+
+ /**
+ * Create a new volume provider for handling volume events. You must specify
+ * the type of volume control, the maximum volume that can be used, and the
+ * current volume on the output.
+ *
+ * @param controlType The method for controlling volume that is used by this provider.
+ * @param maxVolume The maximum allowed volume.
+ * @param currentVolume The current volume on the output.
+ */
+ public VolumeProvider2(@NonNull Context context, @ControlType int controlType,
+ int maxVolume, int currentVolume) {
+ mProvider = ApiLoader.getProvider(context).createVolumeProvider2(
+ context, this, controlType, maxVolume, currentVolume);
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi
+ public VolumeProvider2Provider getProvider() {
+ return mProvider;
+ }
+
+ /**
+ * Get the volume control type that this volume provider uses.
+ *
+ * @return The volume control type for this volume provider
+ */
+ @ControlType
+ public final int getControlType() {
+ return mProvider.getControlType_impl();
+ }
+
+ /**
+ * Get the maximum volume this provider allows.
+ *
+ * @return The max allowed volume.
+ */
+ public final int getMaxVolume() {
+ return mProvider.getMaxVolume_impl();
+ }
+
+ /**
+ * Gets the current volume. This will be the last value set by
+ * {@link #setCurrentVolume(int)}.
+ *
+ * @return The current volume.
+ */
+ public final int getCurrentVolume() {
+ return mProvider.getCurrentVolume_impl();
+ }
+
+ /**
+ * Notify the system that the current volume has been changed. This must be
+ * called every time the volume changes to ensure it is displayed properly.
+ *
+ * @param currentVolume The current volume on the output.
+ */
+ public final void setCurrentVolume(int currentVolume) {
+ mProvider.setCurrentVolume_impl(currentVolume);
+ }
+
+ /**
+ * Override to handle requests to set the volume of the current output.
+ * After the volume has been modified {@link #setCurrentVolume} must be
+ * called to notify the system.
+ *
+ * @param volume The volume to set the output to.
+ */
+ public void onSetVolumeTo(int volume) { }
+
+ /**
+ * Override to handle requests to adjust the volume of the current output.
+ * Direction will be one of {@link AudioManager#ADJUST_LOWER},
+ * {@link AudioManager#ADJUST_RAISE}, {@link AudioManager#ADJUST_SAME}.
+ * After the volume has been modified {@link #setCurrentVolume} must be
+ * called to notify the system.
+ *
+ * @param direction The direction to change the volume in.
+ */
+ public void onAdjustVolume(int direction) { }
+}
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 7e88c27..4de731a 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -89,6 +89,8 @@
private AudioPolicyFocusListener mFocusListener;
+ private final AudioPolicyVolumeCallback mVolCb;
+
private Context mContext;
private AudioPolicyConfig mConfig;
@@ -99,12 +101,15 @@
public boolean hasFocusListener() { return mFocusListener != null; }
/** @hide */
public boolean isFocusPolicy() { return mIsFocusPolicy; }
+ /** @hide */
+ public boolean isVolumeController() { return mVolCb != null; }
/**
* The parameter is guaranteed non-null through the Builder
*/
private AudioPolicy(AudioPolicyConfig config, Context context, Looper looper,
- AudioPolicyFocusListener fl, AudioPolicyStatusListener sl, boolean isFocusPolicy) {
+ AudioPolicyFocusListener fl, AudioPolicyStatusListener sl, boolean isFocusPolicy,
+ AudioPolicyVolumeCallback vc) {
mConfig = config;
mStatus = POLICY_STATUS_UNREGISTERED;
mContext = context;
@@ -120,6 +125,7 @@
mFocusListener = fl;
mStatusListener = sl;
mIsFocusPolicy = isFocusPolicy;
+ mVolCb = vc;
}
/**
@@ -134,6 +140,7 @@
private AudioPolicyFocusListener mFocusListener;
private AudioPolicyStatusListener mStatusListener;
private boolean mIsFocusPolicy = false;
+ private AudioPolicyVolumeCallback mVolCb;
/**
* Constructs a new Builder with no audio mixes.
@@ -208,6 +215,22 @@
mStatusListener = l;
}
+ @SystemApi
+ /**
+ * Sets the callback to receive all volume key-related events.
+ * The callback will only be called if the device is configured to handle volume events
+ * in the PhoneWindowManager (see config_handleVolumeKeysInWindowManager)
+ * @param vc
+ * @return the same Builder instance.
+ */
+ public Builder setAudioPolicyVolumeCallback(@NonNull AudioPolicyVolumeCallback vc) {
+ if (vc == null) {
+ throw new IllegalArgumentException("Invalid null volume callback");
+ }
+ mVolCb = vc;
+ return this;
+ }
+
/**
* Combines all of the attributes that have been set on this {@code Builder} and returns a
* new {@link AudioPolicy} object.
@@ -229,7 +252,7 @@
+ "an AudioPolicyFocusListener");
}
return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext, mLooper,
- mFocusListener, mStatusListener, mIsFocusPolicy);
+ mFocusListener, mStatusListener, mIsFocusPolicy, mVolCb);
}
}
@@ -455,6 +478,23 @@
public void onAudioFocusAbandon(AudioFocusInfo afi) {}
}
+ @SystemApi
+ /**
+ * Callback class to receive volume change-related events.
+ * See {@link #Builder.setAudioPolicyVolumeCallback(AudioPolicyCallback)} to configure the
+ * {@link AudioPolicy} to receive those events.
+ *
+ */
+ public static abstract class AudioPolicyVolumeCallback {
+ /** @hide */
+ public AudioPolicyVolumeCallback() {}
+ /**
+ * Called when volume key-related changes are triggered, on the key down event.
+ * @param adjustment the type of volume adjustment for the key.
+ */
+ public void onVolumeAdjustment(@AudioManager.VolumeAdjustment int adjustment) {}
+ }
+
private void onPolicyStatusChange() {
AudioPolicyStatusListener l;
synchronized (mLock) {
@@ -517,6 +557,13 @@
}
}
}
+
+ public void notifyVolumeAdjust(int adjustment) {
+ sendMsg(MSG_VOL_ADJUST, null /* ignored */, adjustment);
+ if (DEBUG) {
+ Log.v(TAG, "notifyVolumeAdjust: " + adjustment);
+ }
+ }
};
//==================================================
@@ -528,6 +575,7 @@
private final static int MSG_MIX_STATE_UPDATE = 3;
private final static int MSG_FOCUS_REQUEST = 4;
private final static int MSG_FOCUS_ABANDON = 5;
+ private final static int MSG_VOL_ADJUST = 6;
private class EventHandler extends Handler {
public EventHandler(AudioPolicy ap, Looper looper) {
@@ -571,6 +619,13 @@
Log.e(TAG, "Invalid null focus listener for focus abandon event");
}
break;
+ case MSG_VOL_ADJUST:
+ if (mVolCb != null) {
+ mVolCb.onVolumeAdjustment(msg.arg1);
+ } else { // should never be null, but don't crash
+ Log.e(TAG, "Invalid null volume event");
+ }
+ break;
default:
Log.e(TAG, "Unknown event " + msg.what);
}
diff --git a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
index 86abbb4..107e7cd 100644
--- a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
+++ b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
@@ -31,4 +31,7 @@
// callback for mix activity status update
void notifyMixStateUpdate(in String regId, int state);
+
+ // callback for volume events
+ void notifyVolumeAdjust(int adjustment);
}
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index b8463dd..2d365d0 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -17,7 +17,7 @@
import android.content.ComponentName;
import android.media.IRemoteVolumeController;
-import android.media.IMediaSession2;
+import android.media.ISessionTokensListener;
import android.media.session.IActiveSessionsListener;
import android.media.session.ICallback;
import android.media.session.IOnMediaKeyListener;
@@ -52,6 +52,11 @@
void setOnMediaKeyListener(in IOnMediaKeyListener listener);
// MediaSession2
- Bundle createSessionToken(String callingPackage, String id, IMediaSession2 binder);
+ boolean onSessionCreated(in Bundle sessionToken);
+ void onSessionDestroyed(in Bundle sessionToken);
List<Bundle> getSessionTokens(boolean activeSessionOnly, boolean sessionServiceOnly);
+
+ void addSessionTokensListener(in ISessionTokensListener listener, int userId,
+ String packageName);
+ void removeSessionTokensListener(in ISessionTokensListener listener);
}
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 81b4603..454113c 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -16,6 +16,7 @@
package android.media.session;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -24,8 +25,8 @@
import android.content.ComponentName;
import android.content.Context;
import android.media.AudioManager;
-import android.media.IMediaSession2;
import android.media.IRemoteVolumeController;
+import android.media.ISessionTokensListener;
import android.media.MediaSession2;
import android.media.MediaSessionService2;
import android.media.SessionToken2;
@@ -44,6 +45,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* Provides support for interacting with {@link MediaSession media sessions}
@@ -71,6 +73,8 @@
private final ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper> mListeners
= new ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper>();
+ private final ArrayMap<OnSessionTokensChangedListener, SessionTokensChangedWrapper>
+ mSessionTokensListener = new ArrayMap<>();
private final Object mLock = new Object();
private final ISessionManager mService;
@@ -337,37 +341,54 @@
/**
* Called when a {@link MediaSession2} is created.
- *
* @hide
*/
// TODO(jaewan): System API
- public SessionToken2 createSessionToken(@NonNull String callingPackage, @NonNull String id,
- @NonNull IMediaSession2 binder) {
+ public boolean onSessionCreated(@NonNull SessionToken2 token) {
+ if (token == null) {
+ return false;
+ }
try {
- Bundle bundle = mService.createSessionToken(callingPackage, id, binder);
- return SessionToken2.fromBundle(bundle);
+ return mService.onSessionCreated(token.toBundle());
} catch (RemoteException e) {
Log.wtf(TAG, "Cannot communicate with the service.", e);
}
- return null;
+ return false;
+ }
+
+ /** Called when a {@link MediaSession2} is destroyed.
+ * @hide
+ */
+ // TODO(jaewan): System API
+ public void onSessionDestroyed(@NonNull SessionToken2 token) {
+ if (token == null) {
+ return;
+ }
+ try {
+ mService.onSessionDestroyed(token.toBundle());
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Cannot communicate with the service.", e);
+ }
}
/**
* Get {@link List} of {@link SessionToken2} whose sessions are active now. This list represents
* active sessions regardless of whether they're {@link MediaSession2} or
* {@link MediaSessionService2}.
+ * <p>
+ * This requires the android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by the
+ * calling app. You may also retrieve this list if your app is an enabled notification listener
+ * using the {@link NotificationListenerService} APIs.
*
- * @return list of Tokens
+ * @return list of tokens
* @hide
*/
// TODO(jaewan): Unhide
- // TODO(jaewan): Protect this with permission.
- // TODO(jaewna): Add listener for change in lists.
public List<SessionToken2> getActiveSessionTokens() {
try {
List<Bundle> bundles = mService.getSessionTokens(
/* activeSessionOnly */ true, /* sessionServiceOnly */ false);
- return toTokenList(bundles);
+ return toTokenList(mContext, bundles);
} catch (RemoteException e) {
Log.wtf(TAG, "Cannot communicate with the service.", e);
return Collections.emptyList();
@@ -377,17 +398,20 @@
/**
* Get {@link List} of {@link SessionToken2} for {@link MediaSessionService2} regardless of their
* activeness. This list represents media apps that support background playback.
+ * <p>
+ * This requires the android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by the
+ * calling app. You may also retrieve this list if your app is an enabled notification listener
+ * using the {@link NotificationListenerService} APIs.
*
- * @return list of Tokens
+ * @return list of tokens
* @hide
*/
// TODO(jaewan): Unhide
- // TODO(jaewna): Add listener for change in lists.
public List<SessionToken2> getSessionServiceTokens() {
try {
List<Bundle> bundles = mService.getSessionTokens(
/* activeSessionOnly */ false, /* sessionServiceOnly */ true);
- return toTokenList(bundles);
+ return toTokenList(mContext, bundles);
} catch (RemoteException e) {
Log.wtf(TAG, "Cannot communicate with the service.", e);
return Collections.emptyList();
@@ -397,31 +421,113 @@
/**
* Get all {@link SessionToken2}s. This is the combined list of {@link #getActiveSessionTokens()}
* and {@link #getSessionServiceTokens}.
+ * <p>
+ * This requires the android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by the
+ * calling app. You may also retrieve this list if your app is an enabled notification listener
+ * using the {@link NotificationListenerService} APIs.
*
- * @return list of Tokens
+ * @return list of tokens
* @see #getActiveSessionTokens
* @see #getSessionServiceTokens
* @hide
*/
// TODO(jaewan): Unhide
- // TODO(jaewan): Protect this with permission.
- // TODO(jaewna): Add listener for change in lists.
public List<SessionToken2> getAllSessionTokens() {
try {
List<Bundle> bundles = mService.getSessionTokens(
/* activeSessionOnly */ false, /* sessionServiceOnly */ false);
- return toTokenList(bundles);
+ return toTokenList(mContext, bundles);
} catch (RemoteException e) {
Log.wtf(TAG, "Cannot communicate with the service.", e);
return Collections.emptyList();
}
}
- private static List<SessionToken2> toTokenList(List<Bundle> bundles) {
+ /**
+ * Add a listener to be notified when the {@link #getAllSessionTokens()} changes.
+ * <p>
+ * This requires the android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by the
+ * calling app. You may also retrieve this list if your app is an enabled notification listener
+ * using the {@link NotificationListenerService} APIs.
+ *
+ * @param executor executor to run this command
+ * @param listener The listener to add.
+ * @hide
+ */
+ // TODO(jaewan): Unhide
+ public void addOnSessionTokensChangedListener(@NonNull @CallbackExecutor Executor executor,
+ @NonNull OnSessionTokensChangedListener listener) {
+ addOnSessionTokensChangedListener(UserHandle.myUserId(), executor, listener);
+ }
+
+ /**
+ * Add a listener to be notified when the {@link #getAllSessionTokens()} changes.
+ * <p>
+ * This requires the android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by the
+ * calling app. You may also retrieve this list if your app is an enabled notification listener
+ * using the {@link NotificationListenerService} APIs.
+ *
+ * @param userId The userId to listen for changes on.
+ * @param executor executor to run this command
+ * @param listener The listener to add.
+ * @hide
+ */
+ public void addOnSessionTokensChangedListener(int userId,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnSessionTokensChangedListener listener) {
+ if (executor == null) {
+ throw new IllegalArgumentException("executor may not be null");
+ }
+ if (listener == null) {
+ throw new IllegalArgumentException("listener may not be null");
+ }
+ synchronized (mLock) {
+ if (mSessionTokensListener.get(listener) != null) {
+ Log.w(TAG, "Attempted to add session listener twice, ignoring.");
+ return;
+ }
+ SessionTokensChangedWrapper wrapper = new SessionTokensChangedWrapper(
+ mContext, executor, listener);
+ try {
+ mService.addSessionTokensListener(wrapper.mStub, userId, mContext.getPackageName());
+ mSessionTokensListener.put(listener, wrapper);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in addSessionTokensListener.", e);
+ }
+ }
+ }
+
+ /**
+ * Stop receiving session token updates on the specified listener.
+ *
+ * @param listener The listener to remove.
+ * @hide
+ */
+ // TODO(jaewan): Unhide
+ public void removeOnSessionTokensChangedListener(
+ @NonNull OnSessionTokensChangedListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener may not be null");
+ }
+ synchronized (mLock) {
+ SessionTokensChangedWrapper wrapper = mSessionTokensListener.remove(listener);
+ if (wrapper != null) {
+ try {
+ mService.removeSessionTokensListener(wrapper.mStub);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in removeSessionTokensListener.", e);
+ } finally {
+ wrapper.release();
+ }
+ }
+ }
+ }
+
+ private static List<SessionToken2> toTokenList(Context context, List<Bundle> bundles) {
List<SessionToken2> tokens = new ArrayList<>();
if (bundles != null) {
for (int i = 0; i < bundles.size(); i++) {
- SessionToken2 token = SessionToken2.fromBundle(bundles.get(i));
+ SessionToken2 token = SessionToken2.fromBundle(context, bundles.get(i));
if (token != null) {
tokens.add(token);
}
@@ -552,6 +658,16 @@
}
/**
+ * Listens for changes to the {@link #getAllSessionTokens()}. This can be added
+ * using {@link #addOnActiveSessionsChangedListener}.
+ * @hide
+ */
+ // TODO(jaewan): Unhide
+ public interface OnSessionTokensChangedListener {
+ void onSessionTokensChanged(@NonNull List<SessionToken2> tokens);
+ }
+
+ /**
* Listens the volume key long-presses.
* @hide
*/
@@ -677,6 +793,35 @@
}
}
+ private static final class SessionTokensChangedWrapper {
+ private Context mContext;
+ private Executor mExecutor;
+ private OnSessionTokensChangedListener mListener;
+
+ public SessionTokensChangedWrapper(Context context, Executor executor,
+ OnSessionTokensChangedListener listener) {
+ mContext = context;
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ private final ISessionTokensListener.Stub mStub = new ISessionTokensListener.Stub() {
+ @Override
+ public void onSessionTokensChanged(final List<Bundle> bundles) {
+ mExecutor.execute(() -> {
+ List<SessionToken2> tokens = toTokenList(mContext, bundles);
+ mListener.onSessionTokensChanged(tokens);
+ });
+ }
+ };
+
+ private void release() {
+ mListener = null;
+ mContext = null;
+ mExecutor = null;
+ }
+ }
+
private static final class OnVolumeKeyLongPressListenerImpl
extends IOnVolumeKeyLongPressListener.Stub {
private OnVolumeKeyLongPressListener mListener;
diff --git a/media/java/android/media/update/FrameLayoutHelper.java b/media/java/android/media/update/FrameLayoutHelper.java
new file mode 100644
index 0000000..983dc70
--- /dev/null
+++ b/media/java/android/media/update/FrameLayoutHelper.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+package android.media.update;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+/**
+ * Helper class for connecting the public API to an updatable implementation.
+ *
+ * @see ViewProvider
+ *
+ * @hide
+ */
+public abstract class FrameLayoutHelper<T extends ViewProvider> extends FrameLayout {
+ /** @hide */
+ final public T mProvider;
+
+ /** @hide */
+ public FrameLayoutHelper(ProviderCreator<T> creator,
+ Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ mProvider = creator.createProvider(this, new SuperProvider());
+ }
+
+ /** @hide */
+ // TODO @SystemApi
+ public T getProvider() {
+ return mProvider;
+ }
+
+ @Override
+ public CharSequence getAccessibilityClassName() {
+ return mProvider.getAccessibilityClassName_impl();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ return mProvider.onTouchEvent_impl(ev);
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent ev) {
+ return mProvider.onTrackballEvent_impl(ev);
+ }
+
+ @Override
+ public void onFinishInflate() {
+ mProvider.onFinishInflate_impl();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ mProvider.setEnabled_impl(enabled);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ mProvider.onAttachedToWindow_impl();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mProvider.onDetachedFromWindow_impl();
+ }
+
+ /** @hide */
+ public class SuperProvider implements ViewProvider {
+ @Override
+ public CharSequence getAccessibilityClassName_impl() {
+ return FrameLayoutHelper.super.getAccessibilityClassName();
+ }
+
+ @Override
+ public boolean onTouchEvent_impl(MotionEvent ev) {
+ return FrameLayoutHelper.super.onTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onTrackballEvent_impl(MotionEvent ev) {
+ return FrameLayoutHelper.super.onTrackballEvent(ev);
+ }
+
+ @Override
+ public void onFinishInflate_impl() {
+ FrameLayoutHelper.super.onFinishInflate();
+ }
+
+ @Override
+ public void setEnabled_impl(boolean enabled) {
+ FrameLayoutHelper.super.setEnabled(enabled);
+ }
+
+ @Override
+ public void onAttachedToWindow_impl() {
+ FrameLayoutHelper.super.onAttachedToWindow();
+ }
+
+ @Override
+ public void onDetachedFromWindow_impl() {
+ FrameLayoutHelper.super.onDetachedFromWindow();
+ }
+ }
+
+ /** @hide */
+ @FunctionalInterface
+ public interface ProviderCreator<U extends ViewProvider> {
+ U createProvider(FrameLayoutHelper<U> instance, ViewProvider superProvider);
+ }
+}
diff --git a/media/java/android/media/update/MediaControlView2Provider.java b/media/java/android/media/update/MediaControlView2Provider.java
index 6b38c92..95fe363 100644
--- a/media/java/android/media/update/MediaControlView2Provider.java
+++ b/media/java/android/media/update/MediaControlView2Provider.java
@@ -36,12 +36,10 @@
// TODO @SystemApi
public interface MediaControlView2Provider extends ViewProvider {
void setController_impl(MediaController controller);
- void show_impl();
- void show_impl(int timeout);
boolean isShowing_impl();
- void hide_impl();
- void showSubtitle_impl();
- void hideSubtitle_impl();
- void setPrevNextListeners_impl(View.OnClickListener next, View.OnClickListener prev);
- void setButtonVisibility_impl(int button, boolean visible);
+ void setButtonVisibility_impl(int button, int visibility);
+ void requestPlayButtonFocus_impl();
+ void onVisibilityAggregated_impl(boolean isVisible);
+ void setTimeout_impl(long timeout);
+ long getTimeout_impl();
}
diff --git a/media/java/android/media/update/MediaController2Provider.java b/media/java/android/media/update/MediaController2Provider.java
index 8dfb892..05790c1 100644
--- a/media/java/android/media/update/MediaController2Provider.java
+++ b/media/java/android/media/update/MediaController2Provider.java
@@ -35,6 +35,8 @@
* @hide
*/
public interface MediaController2Provider extends TransportControlProvider {
+ void initialize();
+
void close_impl();
SessionToken2 getSessionToken_impl();
boolean isConnected_impl();
@@ -60,6 +62,7 @@
void removePlaylistItem_impl(MediaItem2 index);
void addPlaylistItem_impl(int index, MediaItem2 item);
- PlaylistParams getPlaylistParam_impl();
+ PlaylistParams getPlaylistParams_impl();
+ void setPlaylistParams_impl(PlaylistParams params);
PlaybackState2 getPlaybackState_impl();
}
diff --git a/media/java/android/media/update/MediaItem2Provider.java b/media/java/android/media/update/MediaItem2Provider.java
new file mode 100644
index 0000000..2970f0e
--- /dev/null
+++ b/media/java/android/media/update/MediaItem2Provider.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package android.media.update;
+
+import android.media.DataSourceDesc;
+import android.media.MediaMetadata2;
+import android.os.Bundle;
+
+/**
+ * @hide
+ */
+// TODO(jaewan): SystemApi
+public interface MediaItem2Provider {
+ Bundle toBundle_impl();
+ String toString_impl();
+ int getFlags_impl();
+ boolean isBrowsable_impl();
+ boolean isPlayable_impl();
+ void setMetadata_impl(MediaMetadata2 metadata);
+ MediaMetadata2 getMetadata_impl();
+ String getMediaId_impl();
+ DataSourceDesc getDataSourceDesc_impl();
+}
diff --git a/media/java/android/media/update/MediaLibraryService2Provider.java b/media/java/android/media/update/MediaLibraryService2Provider.java
index a568839..87f509a 100644
--- a/media/java/android/media/update/MediaLibraryService2Provider.java
+++ b/media/java/android/media/update/MediaLibraryService2Provider.java
@@ -17,12 +17,15 @@
package android.media.update;
import android.annotation.SystemApi;
+import android.media.MediaLibraryService2.MediaLibrarySession;
+import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
import android.media.MediaSession2.ControllerInfo;
import android.os.Bundle;
/**
* @hide
*/
+// TODO: @SystemApi
public interface MediaLibraryService2Provider extends MediaSessionService2Provider {
// Nothing new for now
diff --git a/media/java/android/media/update/MediaMetadata2Provider.java b/media/java/android/media/update/MediaMetadata2Provider.java
new file mode 100644
index 0000000..55ac43d
--- /dev/null
+++ b/media/java/android/media/update/MediaMetadata2Provider.java
@@ -0,0 +1,37 @@
+package android.media.update;
+
+import android.graphics.Bitmap;
+import android.media.MediaMetadata2;
+import android.media.MediaMetadata2.Builder;
+import android.media.Rating2;
+import android.os.Bundle;
+
+import java.util.Set;
+
+/**
+ * @hide
+ */
+// TODO(jaewan): SystemApi
+public interface MediaMetadata2Provider {
+ boolean containsKey_impl(String key);
+ CharSequence getText_impl(String key);
+ String getMediaId_impl();
+ String getString_impl(String key);
+ long getLong_impl(String key);
+ Rating2 getRating_impl(String key);
+ Bundle toBundle_impl();
+ Set<String> keySet_impl();
+ int size_impl();
+ Bitmap getBitmap_impl(String key);
+ Bundle getExtra_impl();
+
+ interface BuilderProvider {
+ Builder putText_impl(String key, CharSequence value);
+ Builder putString_impl(String key, String value);
+ Builder putLong_impl(String key, long value);
+ Builder putRating_impl(String key, Rating2 value);
+ Builder putBitmap_impl(String key, Bitmap value);
+ Builder setExtra_impl(Bundle bundle);
+ MediaMetadata2 build_impl();
+ }
+}
diff --git a/media/java/android/media/update/MediaSession2Provider.java b/media/java/android/media/update/MediaSession2Provider.java
index d32b741..da4d0c7 100644
--- a/media/java/android/media/update/MediaSession2Provider.java
+++ b/media/java/android/media/update/MediaSession2Provider.java
@@ -16,34 +16,38 @@
package android.media.update;
-import android.annotation.SystemApi;
-import android.media.AudioAttributes;
+import android.app.PendingIntent;
import android.media.MediaItem2;
-import android.media.MediaPlayerBase;
+import android.media.MediaMetadata2;
+import android.media.MediaPlayerInterface;
+import android.media.MediaPlayerInterface.PlaybackListener;
+import android.media.MediaSession2;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandButton;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.PlaylistParams;
+import android.media.MediaSession2.SessionCallback;
import android.media.SessionToken2;
import android.media.VolumeProvider;
import android.os.Bundle;
import android.os.ResultReceiver;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* @hide
*/
+// TODO: @SystemApi
public interface MediaSession2Provider extends TransportControlProvider {
void close_impl();
- void setPlayer_impl(MediaPlayerBase player);
- void setPlayer_impl(MediaPlayerBase player, VolumeProvider volumeProvider);
- MediaPlayerBase getPlayer_impl();
+ void setPlayer_impl(MediaPlayerInterface player);
+ void setPlayer_impl(MediaPlayerInterface player, VolumeProvider volumeProvider);
+ MediaPlayerInterface getPlayer_impl();
SessionToken2 getToken_impl();
List<ControllerInfo> getConnectedControllers_impl();
void setCustomLayout_impl(ControllerInfo controller, List<CommandButton> layout);
- void setAudioAttributes_impl(AudioAttributes attributes);
void setAudioFocusRequest_impl(int focusGain);
void setAllowedCommands_impl(ControllerInfo controller, CommandGroup commands);
@@ -51,7 +55,32 @@
void sendCustomCommand_impl(ControllerInfo controller, Command command, Bundle args,
ResultReceiver receiver);
void sendCustomCommand_impl(Command command, Bundle args);
- void setPlaylist_impl(List<MediaItem2> playlist, PlaylistParams param);
+ void setPlaylist_impl(List<MediaItem2> playlist);
+ List<MediaItem2> getPlaylist_impl();
+ void setPlaylistParams_impl(PlaylistParams params);
+ PlaylistParams getPlaylistParams_impl();
+
+ void addPlaybackListener_impl(Executor executor, PlaybackListener listener);
+ void removePlaybackListener_impl(PlaybackListener listener);
+
+ interface CommandProvider {
+ int getCommandCode_impl();
+ String getCustomCommand_impl();
+ Bundle getExtra_impl();
+ Bundle toBundle_impl();
+
+ boolean equals_impl(Object ob);
+ int hashCode_impl();
+ }
+
+ interface CommandGroupProvider {
+ void addCommand_impl(Command command);
+ void addAllPredefinedCommands_impl();
+ void removeCommand_impl(Command command);
+ boolean hasCommand_impl(Command command);
+ boolean hasCommand_impl(int code);
+ Bundle toBundle_impl();
+ }
interface ControllerInfoProvider {
String getPackageName_impl();
@@ -60,4 +89,20 @@
int hashCode_impl();
boolean equals_impl(ControllerInfoProvider obj);
}
+
+ interface PlaylistParamsProvider {
+ int getRepeatMode_impl();
+ int getShuffleMode_impl();
+ MediaMetadata2 getPlaylistMetadata_impl();
+ Bundle toBundle_impl();
+ }
+
+ interface BuilderBaseProvider<T extends MediaSession2, C extends SessionCallback> {
+ void setVolumeProvider_impl(VolumeProvider volumeProvider);
+ void setRatingType_impl(int type);
+ void setSessionActivity_impl(PendingIntent pi);
+ void setId_impl(String id);
+ void setSessionCallback_impl(Executor executor, C callback);
+ T build_impl();
+ }
}
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl b/media/java/android/media/update/PlaybackInfoProvider.java
similarity index 60%
copy from telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl
copy to media/java/android/media/update/PlaybackInfoProvider.java
index 01cca2db..36eb58a 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl
+++ b/media/java/android/media/update/PlaybackInfoProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 The Android Open Source Project
+ * 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.
@@ -14,14 +14,18 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.media.update;
-import android.telephony.ims.internal.stub.ImsFeatureConfiguration;
+import android.media.AudioAttributes;
/**
- * See ImsService#Listener for more information.
- * {@hide}
+ * @hide
*/
-oneway interface IImsServiceControllerListener {
- void onUpdateSupportedImsFeatures(in ImsFeatureConfiguration c);
+// TODO(jaewan): @SystemApi
+public interface PlaybackInfoProvider {
+ int getPlaybackType_impl();
+ AudioAttributes getAudioAttributes_impl();
+ int getControlType_impl();
+ int getMaxVolume_impl();
+ int getCurrentVolume_impl();
}
diff --git a/media/java/android/media/update/PlaybackState2Provider.java b/media/java/android/media/update/PlaybackState2Provider.java
new file mode 100644
index 0000000..2875e98
--- /dev/null
+++ b/media/java/android/media/update/PlaybackState2Provider.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+package android.media.update;
+
+import android.os.Bundle;
+
+/**
+ * @hide
+ */
+// TODO(jaewan): @SystemApi
+public interface PlaybackState2Provider {
+ String toString_impl();
+
+ int getState_impl();
+
+ long getPosition_impl();
+
+ long getBufferedPosition_impl();
+
+ float getPlaybackSpeed_impl();
+
+ CharSequence getErrorMessage_impl();
+
+ long getLastPositionUpdateTime_impl();
+
+ long getCurrentPlaylistItemIndex_impl();
+
+ Bundle toBundle_impl();
+}
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl b/media/java/android/media/update/ProviderCreator.java
similarity index 74%
copy from telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
copy to media/java/android/media/update/ProviderCreator.java
index d648a35..f5f3e47 100644
--- a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
+++ b/media/java/android/media/update/ProviderCreator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 The Android Open Source Project
+ * 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.
@@ -14,6 +14,10 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.media.update;
-parcelable ImsStreamMediaProfile;
+/** @hide */
+@FunctionalInterface
+public interface ProviderCreator<T, U> {
+ U createProvider(T instance);
+}
diff --git a/media/java/android/media/update/Rating2Provider.java b/media/java/android/media/update/Rating2Provider.java
new file mode 100644
index 0000000..8966196
--- /dev/null
+++ b/media/java/android/media/update/Rating2Provider.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package android.media.update;
+
+import android.annotation.SystemApi;
+import android.os.Bundle;
+
+/**
+ * @hide
+ */
+// TODO(jaewan): @SystemApi
+public interface Rating2Provider {
+ String toString_impl();
+ boolean equals_impl(Object obj);
+ int hashCode_impl();
+ Bundle toBundle_impl();
+ boolean isRated_impl();
+ int getRatingStyle_impl();
+ boolean hasHeart_impl();
+ boolean isThumbUp_impl();
+ float getStarRating_impl();
+ float getPercentRating_impl();
+}
\ No newline at end of file
diff --git a/media/java/android/media/update/SessionPlayer2Provider.java b/media/java/android/media/update/SessionPlayer2Provider.java
new file mode 100644
index 0000000..e068c21
--- /dev/null
+++ b/media/java/android/media/update/SessionPlayer2Provider.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+package android.media.update;
+
+import android.media.AudioAttributes;
+import android.media.MediaItem2;
+import android.media.MediaPlayer2;
+import android.media.MediaPlayerInterface.PlaybackListener;
+import android.media.MediaSession2.PlaylistParams;
+import android.media.PlaybackState2;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ */
+public interface SessionPlayer2Provider {
+ void play_impl();
+ void prepare_impl();
+ void pause_impl();
+ void stop_impl();
+ void skipToPrevious_impl();
+ void skipToNext_impl();
+ void seekTo_impl(long pos);
+ void fastForward_impl();
+ void rewind_impl();
+ PlaybackState2 getPlaybackState_impl();
+ void setAudioAttributes_impl(AudioAttributes attributes);
+ AudioAttributes getAudioAttributes_impl();
+ void addPlaylistItem_impl(int index, MediaItem2 item);
+ void removePlaylistItem_impl(MediaItem2 item);
+ void setPlaylist_impl(List<MediaItem2> playlist);
+ List<MediaItem2> getPlaylist_impl();
+ void setCurrentPlaylistItem_impl(int index);
+ void setPlaylistParams_impl(PlaylistParams params);
+ PlaylistParams getPlaylistParams_impl();
+ void addPlaybackListener_impl(Executor executor, PlaybackListener listener);
+ void removePlaybackListener_impl(PlaybackListener listener);
+ MediaPlayer2 getPlayer_impl();
+}
diff --git a/media/java/android/media/update/SessionToken2Provider.java b/media/java/android/media/update/SessionToken2Provider.java
new file mode 100644
index 0000000..95d6ce0
--- /dev/null
+++ b/media/java/android/media/update/SessionToken2Provider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package android.media.update;
+
+import android.os.Bundle;
+
+/**
+ * @hide
+ */
+public interface SessionToken2Provider {
+ String getPackageName_impl();
+ String getId_imp();
+ int getType_impl();
+ int getUid_impl();
+ Bundle toBundle_impl();
+
+ int hashCode_impl();
+ boolean equals_impl(Object obj);
+ String toString_impl();
+}
diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java
index 3cd1a99..922b452 100644
--- a/media/java/android/media/update/StaticProvider.java
+++ b/media/java/android/media/update/StaticProvider.java
@@ -17,24 +17,34 @@
package android.media.update;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.app.PendingIntent;
import android.content.Context;
+import android.media.DataSourceDesc;
import android.media.MediaBrowser2;
import android.media.MediaBrowser2.BrowserCallback;
import android.media.MediaController2;
import android.media.MediaController2.ControllerCallback;
+import android.media.MediaItem2;
import android.media.MediaLibraryService2;
import android.media.MediaLibraryService2.MediaLibrarySession;
+import android.media.MediaLibraryService2.MediaLibrarySessionBuilder;
import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
-import android.media.MediaPlayerBase;
+import android.media.MediaMetadata2;
+import android.media.MediaPlayerInterface;
import android.media.MediaSession2;
+import android.media.MediaSession2.PlaylistParams;
import android.media.MediaSession2.SessionCallback;
import android.media.MediaSessionService2;
+import android.media.PlaybackState2;
+import android.media.Rating2;
+import android.media.SessionPlayer2;
import android.media.SessionToken2;
-import android.media.VolumeProvider;
-import android.media.update.MediaLibraryService2Provider.MediaLibrarySessionProvider;
+import android.media.VolumeProvider2;
+import android.media.update.MediaSession2Provider.BuilderBaseProvider;
+import android.media.update.MediaSession2Provider.CommandGroupProvider;
+import android.media.update.MediaSession2Provider.CommandProvider;
import android.media.update.MediaSession2Provider.ControllerInfoProvider;
+import android.media.update.MediaSession2Provider.PlaylistParamsProvider;
+import android.os.Bundle;
import android.os.IInterface;
import android.util.AttributeSet;
import android.widget.MediaControlView2;
@@ -56,20 +66,64 @@
VideoView2 instance, ViewProvider superProvider,
@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes);
- MediaSession2Provider createMediaSession2(Context context, MediaSession2 instance,
- MediaPlayerBase player, String id, VolumeProvider volumeProvider, int ratingType,
- PendingIntent sessionActivity, Executor executor, SessionCallback callback);
- ControllerInfoProvider createMediaSession2ControllerInfoProvider(Context context,
+ CommandProvider createMediaSession2Command(MediaSession2.Command instance,
+ int commandCode, String action, Bundle extra);
+ MediaSession2.Command fromBundle_MediaSession2Command(Context context, Bundle bundle);
+ CommandGroupProvider createMediaSession2CommandGroup(Context context,
+ MediaSession2.CommandGroup instance, MediaSession2.CommandGroup others);
+ MediaSession2.CommandGroup fromBundle_MediaSession2CommandGroup(Context context, Bundle bundle);
+ ControllerInfoProvider createMediaSession2ControllerInfo(Context context,
MediaSession2.ControllerInfo instance, int uid, int pid,
String packageName, IInterface callback);
+ PlaylistParamsProvider createMediaSession2PlaylistParams(Context context,
+ PlaylistParams playlistParams, int repeatMode, int shuffleMode,
+ MediaMetadata2 playlistMetadata);
+ PlaylistParams fromBundle_PlaylistParams(Context context, Bundle bundle);
+ BuilderBaseProvider<MediaSession2, SessionCallback> createMediaSession2Builder(
+ Context context, MediaSession2.Builder instance, MediaPlayerInterface player);
+
MediaController2Provider createMediaController2(Context context, MediaController2 instance,
SessionToken2 token, Executor executor, ControllerCallback callback);
+
MediaBrowser2Provider createMediaBrowser2(Context context, MediaBrowser2 instance,
SessionToken2 token, Executor executor, BrowserCallback callback);
+
MediaSessionService2Provider createMediaSessionService2(MediaSessionService2 instance);
+
MediaSessionService2Provider createMediaLibraryService2(MediaLibraryService2 instance);
- MediaLibrarySessionProvider createMediaLibraryService2MediaLibrarySession(Context context,
- MediaLibrarySession instance, MediaPlayerBase player, String id,
- VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity,
- Executor executor, MediaLibrarySessionCallback callback);
+ BuilderBaseProvider<MediaLibrarySession, MediaLibrarySessionCallback>
+ createMediaLibraryService2Builder(
+ Context context, MediaLibrarySessionBuilder instance, MediaPlayerInterface player,
+ Executor callbackExecutor, MediaLibrarySessionCallback callback);
+
+ SessionToken2Provider createSessionToken2(Context context, SessionToken2 instance,
+ String packageName, String serviceName, int uid);
+ SessionToken2 SessionToken2_fromBundle(Context context, Bundle bundle);
+
+ SessionPlayer2Provider createSessionPlayer2(Context context, SessionPlayer2 instance);
+
+ MediaItem2Provider createMediaItem2(Context context, MediaItem2 mediaItem2,
+ String mediaId, DataSourceDesc dsd, MediaMetadata2 metadata, int flags);
+ MediaItem2 fromBundle_MediaItem2(Context context, Bundle bundle);
+
+ VolumeProvider2Provider createVolumeProvider2(Context context, VolumeProvider2 instance,
+ int controlType, int maxVolume, int currentVolume);
+
+ MediaMetadata2 fromBundle_MediaMetadata2(Context context, Bundle bundle);
+ MediaMetadata2Provider.BuilderProvider createMediaMetadata2Builder(
+ Context context, MediaMetadata2.Builder builder);
+ MediaMetadata2Provider.BuilderProvider createMediaMetadata2Builder(
+ Context context, MediaMetadata2.Builder builder, MediaMetadata2 source);
+
+ Rating2 newUnratedRating_Rating2(Context context, int ratingStyle);
+ Rating2 fromBundle_Rating2(Context context, Bundle bundle);
+ Rating2 newHeartRating_Rating2(Context context, boolean hasHeart);
+ Rating2 newThumbRating_Rating2(Context context, boolean thumbIsUp);
+ Rating2 newStarRating_Rating2(Context context, int starRatingStyle, float starRating);
+ Rating2 newPercentageRating_Rating2(Context context, float percent);
+
+ PlaybackState2Provider createPlaybackState2(Context context, PlaybackState2 instance, int state,
+ long position, long updateTime, float speed, long bufferedPosition, long activeItemId,
+ CharSequence error);
+ PlaybackState2 fromBundle_PlaybackState2(Context context, Bundle bundle);
}
diff --git a/media/java/android/media/update/TransportControlProvider.java b/media/java/android/media/update/TransportControlProvider.java
index 0c87063e..44f82b29 100644
--- a/media/java/android/media/update/TransportControlProvider.java
+++ b/media/java/android/media/update/TransportControlProvider.java
@@ -16,6 +16,8 @@
package android.media.update;
+import android.media.PlaybackState2;
+
/**
* @hide
*/
@@ -31,4 +33,6 @@
void rewind_impl();
void seekTo_impl(long pos);
void setCurrentPlaylistItem_impl(int index);
+
+ PlaybackState2 getPlaybackState_impl();
}
diff --git a/media/java/android/media/update/VideoView2Provider.java b/media/java/android/media/update/VideoView2Provider.java
index 5c05ce4..10f03d2 100644
--- a/media/java/android/media/update/VideoView2Provider.java
+++ b/media/java/android/media/update/VideoView2Provider.java
@@ -17,14 +17,17 @@
package android.media.update;
import android.media.AudioAttributes;
-import android.media.MediaPlayerBase;
+import android.media.MediaPlayerInterface;
import android.media.session.MediaController;
+import android.media.session.PlaybackState;
+import android.media.session.MediaSession;
import android.net.Uri;
import android.widget.MediaControlView2;
import android.widget.VideoView2;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executor;
/**
* Interface for connecting the public API to an updatable implementation.
@@ -44,24 +47,27 @@
void setMediaControlView2_impl(MediaControlView2 mediaControlView);
MediaController getMediaController_impl();
MediaControlView2 getMediaControlView2_impl();
- int getAudioSessionId_impl();
- void showSubtitle_impl();
- void hideSubtitle_impl();
- void setFullScreen_impl(boolean fullScreen);
+ void showSubtitle_impl(boolean show);
// TODO: remove setSpeed_impl once MediaController2 is ready.
void setSpeed_impl(float speed);
void setAudioFocusRequest_impl(int focusGain);
void setAudioAttributes_impl(AudioAttributes attributes);
- void setRouteAttributes_impl(List<String> routeCategories, MediaPlayerBase player);
+ void setRouteAttributes_impl(List<String> routeCategories, MediaPlayerInterface player);
+ // TODO: remove setRouteAttributes_impl with MediaSession.Callback once MediaSession2 is ready.
+ void setRouteAttributes_impl(List<String> routeCategories, MediaSession.Callback sessionPlayer);
void setVideoPath_impl(String path);
- void setVideoURI_impl(Uri uri);
- void setVideoURI_impl(Uri uri, Map<String, String> headers);
+ void setVideoUri_impl(Uri uri);
+ void setVideoUri_impl(Uri uri, Map<String, String> headers);
void setViewType_impl(int viewType);
int getViewType_impl();
- void setOnPreparedListener_impl(VideoView2.OnPreparedListener l);
- void setOnCompletionListener_impl(VideoView2.OnCompletionListener l);
- void setOnErrorListener_impl(VideoView2.OnErrorListener l);
- void setOnInfoListener_impl(VideoView2.OnInfoListener l);
- void setOnViewTypeChangedListener_impl(VideoView2.OnViewTypeChangedListener l);
- void setFullScreenChangedListener_impl(VideoView2.OnFullScreenChangedListener l);
+ void setCustomActions_impl(List<PlaybackState.CustomAction> actionList,
+ Executor executor, VideoView2.OnCustomActionListener listener);
+ void setOnPreparedListener_impl(Executor executor, VideoView2.OnPreparedListener l);
+ void setOnCompletionListener_impl(Executor executor, VideoView2.OnCompletionListener l);
+ void setOnErrorListener_impl(Executor executor, VideoView2.OnErrorListener l);
+ void setOnInfoListener_impl(Executor executor, VideoView2.OnInfoListener l);
+ void setOnViewTypeChangedListener_impl(
+ Executor executor, VideoView2.OnViewTypeChangedListener l);
+ void setFullScreenRequestListener_impl(
+ Executor executor, VideoView2.OnFullScreenRequestListener l);
}
diff --git a/media/java/android/media/update/ViewProvider.java b/media/java/android/media/update/ViewProvider.java
index 78c5b36..0dd8f38 100644
--- a/media/java/android/media/update/ViewProvider.java
+++ b/media/java/android/media/update/ViewProvider.java
@@ -17,8 +17,6 @@
package android.media.update;
import android.annotation.SystemApi;
-import android.graphics.Canvas;
-import android.view.KeyEvent;
import android.view.MotionEvent;
/**
@@ -42,8 +40,6 @@
CharSequence getAccessibilityClassName_impl();
boolean onTouchEvent_impl(MotionEvent ev);
boolean onTrackballEvent_impl(MotionEvent ev);
- boolean onKeyDown_impl(int keyCode, KeyEvent event);
void onFinishInflate_impl();
- boolean dispatchKeyEvent_impl(KeyEvent event);
void setEnabled_impl(boolean enabled);
}
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl b/media/java/android/media/update/VolumeProvider2Provider.java
similarity index 64%
copy from telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
copy to media/java/android/media/update/VolumeProvider2Provider.java
index f6005b6..5657af6 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
+++ b/media/java/android/media/update/VolumeProvider2Provider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 The Android Open Source Project
+ * 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.
@@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-package android.telephony.ims.internal.aidl;
+package android.media.update;
/**
- * See RcsFeature for more information.
- * {@hide}
+ * @hide
*/
-interface IImsRcsFeature {
- //Empty Default Implementation
-}
\ No newline at end of file
+// TODO(jaewan): @SystemApi
+public interface VolumeProvider2Provider {
+ int getControlType_impl();
+ int getMaxVolume_impl();
+ int getCurrentVolume_impl();
+ void setCurrentVolume_impl(int currentVolume);
+}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 051c802..7e5f581 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -34,6 +34,7 @@
"libutils",
"libbinder",
"libmedia",
+ "libmediaextractor",
"libmedia_omx",
"libmediametrics",
"libmediadrm",
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 95b07f1..4f06caa 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -1134,6 +1134,27 @@
return ListOfVectorsToArrayListOfByteArray(env, secureStops);
}
+static jobject android_media_MediaDrm_getSecureStopIds(
+ JNIEnv *env, jobject thiz) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (drm == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "MediaDrm obj is null");
+ return NULL;
+ }
+
+ List<Vector<uint8_t> > secureStopIds;
+
+ status_t err = drm->getSecureStopIds(secureStopIds);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
+ return NULL;
+ }
+
+ return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
+}
+
static jbyteArray android_media_MediaDrm_getSecureStop(
JNIEnv *env, jobject thiz, jbyteArray ssid) {
sp<IDrm> drm = GetDrm(env, thiz);
@@ -1168,7 +1189,22 @@
throwExceptionAsNecessary(env, err, "Failed to release secure stops");
}
-static void android_media_MediaDrm_releaseAllSecureStops(
+static void android_media_MediaDrm_removeSecureStop(
+ JNIEnv *env, jobject thiz, jbyteArray ssid) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (drm == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "MediaDrm obj is null");
+ return;
+ }
+
+ status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
+
+ throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
+}
+
+static void android_media_MediaDrm_removeAllSecureStops(
JNIEnv *env, jobject thiz) {
sp<IDrm> drm = GetDrm(env, thiz);
@@ -1176,9 +1212,9 @@
return;
}
- status_t err = drm->releaseAllSecureStops();
+ status_t err = drm->removeAllSecureStops();
- throwExceptionAsNecessary(env, err, "Failed to release all secure stops");
+ throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
}
@@ -1719,14 +1755,20 @@
{ "getSecureStops", "()Ljava/util/List;",
(void *)android_media_MediaDrm_getSecureStops },
+ { "getSecureStopIds", "()Ljava/util/List;",
+ (void *)android_media_MediaDrm_getSecureStopIds },
+
{ "getSecureStop", "([B)[B",
(void *)android_media_MediaDrm_getSecureStop },
{ "releaseSecureStops", "([B)V",
(void *)android_media_MediaDrm_releaseSecureStops },
- { "releaseAllSecureStops", "()V",
- (void *)android_media_MediaDrm_releaseAllSecureStops },
+ { "removeSecureStop", "([B)V",
+ (void *)android_media_MediaDrm_removeSecureStop },
+
+ { "removeAllSecureStops", "()V",
+ (void *)android_media_MediaDrm_removeAllSecureStops },
{ "getConnectedHdcpLevel", "()I",
(void *)android_media_MediaDrm_getConnectedHdcpLevel },
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 42ebf6a..ff854c5 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -68,17 +68,26 @@
}
}
-static MediaMetadataRetriever* getRetriever(JNIEnv* env, jobject thiz)
+static sp<MediaMetadataRetriever> getRetriever(JNIEnv* env, jobject thiz)
{
// No lock is needed, since it is called internally by other methods that are protected
MediaMetadataRetriever* retriever = (MediaMetadataRetriever*) env->GetLongField(thiz, fields.context);
return retriever;
}
-static void setRetriever(JNIEnv* env, jobject thiz, MediaMetadataRetriever* retriever)
+static void setRetriever(JNIEnv* env, jobject thiz, const sp<MediaMetadataRetriever> &retriever)
{
// No lock is needed, since it is called internally by other methods that are protected
- env->SetLongField(thiz, fields.context, (jlong) retriever);
+
+ if (retriever != NULL) {
+ retriever->incStrong(thiz);
+ }
+ sp<MediaMetadataRetriever> old = getRetriever(env, thiz);
+ if (old != NULL) {
+ old->decStrong(thiz);
+ }
+
+ env->SetLongField(thiz, fields.context, (jlong) retriever.get());
}
static void
@@ -87,7 +96,7 @@
jobjectArray keys, jobjectArray values) {
ALOGV("setDataSource");
- MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+ sp<MediaMetadataRetriever> retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(
env,
@@ -146,7 +155,7 @@
static void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
{
ALOGV("setDataSource");
- MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+ sp<MediaMetadataRetriever> retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return;
@@ -175,7 +184,7 @@
static void android_media_MediaMetadataRetriever_setDataSourceCallback(JNIEnv *env, jobject thiz, jobject dataSource)
{
ALOGV("setDataSourceCallback");
- MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+ sp<MediaMetadataRetriever> retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return;
@@ -325,7 +334,7 @@
{
ALOGV("getFrameAtTime: %lld us option: %d dst width: %d heigh: %d",
(long long)timeUs, option, dst_width, dst_height);
- MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+ sp<MediaMetadataRetriever> retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return NULL;
@@ -349,7 +358,7 @@
JNIEnv *env, jobject thiz, jint index)
{
ALOGV("getImageAtIndex: index %d", index);
- MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+ sp<MediaMetadataRetriever> retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return NULL;
@@ -373,7 +382,7 @@
JNIEnv *env, jobject thiz, jint frameIndex, jint numFrames)
{
ALOGV("getFrameAtIndex: frameIndex %d, numFrames %d", frameIndex, numFrames);
- MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+ sp<MediaMetadataRetriever> retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env,
"java/lang/IllegalStateException", "No retriever available");
@@ -411,7 +420,7 @@
JNIEnv *env, jobject thiz, jint pictureType)
{
ALOGV("getEmbeddedPicture: %d", pictureType);
- MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+ sp<MediaMetadataRetriever> retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return NULL;
@@ -446,7 +455,7 @@
static jobject android_media_MediaMetadataRetriever_extractMetadata(JNIEnv *env, jobject thiz, jint keyCode)
{
ALOGV("extractMetadata");
- MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+ sp<MediaMetadataRetriever> retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return NULL;
@@ -464,9 +473,7 @@
{
ALOGV("release");
Mutex::Autolock lock(sLock);
- MediaMetadataRetriever* retriever = getRetriever(env, thiz);
- delete retriever;
- setRetriever(env, thiz, (MediaMetadataRetriever*) 0);
+ setRetriever(env, thiz, NULL);
}
static void android_media_MediaMetadataRetriever_native_finalize(JNIEnv *env, jobject thiz)
@@ -533,7 +540,7 @@
static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)
{
ALOGV("native_setup");
- MediaMetadataRetriever* retriever = new MediaMetadataRetriever();
+ sp<MediaMetadataRetriever> retriever = new MediaMetadataRetriever();
if (retriever == 0) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
diff --git a/media/lib/remotedisplay/Android.mk b/media/lib/remotedisplay/Android.mk
index ea1ac2b..e88c0f1 100644
--- a/media/lib/remotedisplay/Android.mk
+++ b/media/lib/remotedisplay/Android.mk
@@ -22,9 +22,7 @@
LOCAL_MODULE:= com.android.media.remotedisplay
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, java) \
- $(call all-aidl-files-under, java)
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
include $(BUILD_JAVA_LIBRARY)
diff --git a/media/lib/signer/Android.mk b/media/lib/signer/Android.mk
index b0d3177..69ca4d2 100644
--- a/media/lib/signer/Android.mk
+++ b/media/lib/signer/Android.mk
@@ -22,9 +22,7 @@
LOCAL_MODULE:= com.android.mediadrm.signer
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, java) \
- $(call all-aidl-files-under, java)
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
include $(BUILD_JAVA_LIBRARY)
diff --git a/media/lib/tvremote/Android.mk b/media/lib/tvremote/Android.mk
index 06838c2..1ffdd62 100644
--- a/media/lib/tvremote/Android.mk
+++ b/media/lib/tvremote/Android.mk
@@ -22,9 +22,7 @@
LOCAL_MODULE:= com.android.media.tv.remoteprovider
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, java) \
- $(call all-aidl-files-under, java)
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
LOCAL_DEX_PREOPT := false
@@ -45,4 +43,4 @@
LOCAL_SRC_FILES := $(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
\ No newline at end of file
+include $(BUILD_PREBUILT)
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
index 5680d9f..b3f443b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
@@ -1860,9 +1860,6 @@
return new ArrayList<Integer>();
}
- checkArrayValuesInRange(key, availableCaps,
- CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
- CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO);
capList = Arrays.asList(CameraTestUtils.toObject(availableCaps));
return capList;
}
diff --git a/native/android/asset_manager.cpp b/native/android/asset_manager.cpp
index e70d5ea..98e9a42 100644
--- a/native/android/asset_manager.cpp
+++ b/native/android/asset_manager.cpp
@@ -18,11 +18,9 @@
#include <utils/Log.h>
#include <android/asset_manager_jni.h>
-#include <android_runtime/android_util_AssetManager.h>
#include <androidfw/Asset.h>
#include <androidfw/AssetDir.h>
#include <androidfw/AssetManager.h>
-#include <androidfw/AssetManager2.h>
#include <utils/threads.h>
#include "jni.h"
@@ -37,20 +35,21 @@
// -----
struct AAssetDir {
- std::unique_ptr<AssetDir> mAssetDir;
+ AssetDir* mAssetDir;
size_t mCurFileIndex;
String8 mCachedFileName;
- explicit AAssetDir(std::unique_ptr<AssetDir> dir) :
- mAssetDir(std::move(dir)), mCurFileIndex(0) { }
+ explicit AAssetDir(AssetDir* dir) : mAssetDir(dir), mCurFileIndex(0) { }
+ ~AAssetDir() { delete mAssetDir; }
};
// -----
struct AAsset {
- std::unique_ptr<Asset> mAsset;
+ Asset* mAsset;
- explicit AAsset(std::unique_ptr<Asset> asset) : mAsset(std::move(asset)) { }
+ explicit AAsset(Asset* asset) : mAsset(asset) { }
+ ~AAsset() { delete mAsset; }
};
// -------------------- Public native C API --------------------
@@ -105,18 +104,19 @@
return NULL;
}
- ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(amgr));
- std::unique_ptr<Asset> asset = locked_mgr->Open(filename, amMode);
- if (asset == nullptr) {
- return nullptr;
+ AssetManager* mgr = static_cast<AssetManager*>(amgr);
+ Asset* asset = mgr->open(filename, amMode);
+ if (asset == NULL) {
+ return NULL;
}
- return new AAsset(std::move(asset));
+
+ return new AAsset(asset);
}
AAssetDir* AAssetManager_openDir(AAssetManager* amgr, const char* dirName)
{
- ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(amgr));
- return new AAssetDir(locked_mgr->OpenDir(dirName));
+ AssetManager* mgr = static_cast<AssetManager*>(amgr);
+ return new AAssetDir(mgr->openDir(dirName));
}
/**
diff --git a/packages/BackupRestoreConfirmation/AndroidManifest.xml b/packages/BackupRestoreConfirmation/AndroidManifest.xml
index 8141fa7..e67b3be 100644
--- a/packages/BackupRestoreConfirmation/AndroidManifest.xml
+++ b/packages/BackupRestoreConfirmation/AndroidManifest.xml
@@ -30,6 +30,7 @@
android:title=""
android:windowSoftInputMode="stateAlwaysHidden"
android:excludeFromRecents="true"
+ android:launchMode="singleTop"
android:exported="true" >
</activity>
</application>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index 9fa7a664..d6b6bf8 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -52,7 +52,9 @@
static final String TAG = "BackupRestoreConfirmation";
static final boolean DEBUG = true;
- static final String DID_ACKNOWLEDGE = "did_acknowledge";
+ static final String KEY_DID_ACKNOWLEDGE = "did_acknowledge";
+ static final String KEY_TOKEN = "token";
+ static final String KEY_ACTION = "action";
static final int MSG_START_BACKUP = 1;
static final int MSG_BACKUP_PACKAGE = 2;
@@ -69,6 +71,7 @@
int mToken;
boolean mIsEncrypted;
boolean mDidAcknowledge;
+ String mAction;
TextView mStatusView;
TextView mCurPassword;
@@ -134,26 +137,9 @@
super.onCreate(icicle);
final Intent intent = getIntent();
- final String action = intent.getAction();
- final int layoutId;
- final int titleId;
- if (action.equals(FullBackup.FULL_BACKUP_INTENT_ACTION)) {
- layoutId = R.layout.confirm_backup;
- titleId = R.string.backup_confirm_title;
- } else if (action.equals(FullBackup.FULL_RESTORE_INTENT_ACTION)) {
- layoutId = R.layout.confirm_restore;
- titleId = R.string.restore_confirm_title;
- } else {
- Slog.w(TAG, "Backup/restore confirmation activity launched with invalid action!");
- finish();
- return;
- }
-
- mToken = intent.getIntExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, -1);
- if (mToken < 0) {
- Slog.e(TAG, "Backup/restore confirmation requested but no token passed!");
- finish();
+ boolean tokenValid = setTokenOrFinish(intent, icicle);
+ if (!tokenValid) { // already called finish()
return;
}
@@ -169,6 +155,61 @@
mObserver.setHandler(mHandler);
}
+ setViews(intent, icicle);
+ }
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ setIntent(intent);
+
+ boolean tokenValid = setTokenOrFinish(intent, null);
+ if (!tokenValid) { // already called finish()
+ return;
+ }
+
+ setViews(intent, null);
+ }
+
+ private boolean setTokenOrFinish(Intent intent, Bundle icicle) {
+ mToken = intent.getIntExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, -1);
+
+ // for relaunch, we try to use the last token before exit
+ if (icicle != null) {
+ mToken = icicle.getInt(KEY_TOKEN, mToken);
+ }
+
+ if (mToken < 0) {
+ Slog.e(TAG, "Backup/restore confirmation requested but no token passed!");
+ finish();
+ return false;
+ }
+
+ return true;
+ }
+
+ private void setViews(Intent intent, Bundle icicle) {
+ mAction = intent.getAction();
+
+ // for relaunch, we try to use the last action before exit
+ if (icicle != null) {
+ mAction = icicle.getString(KEY_ACTION, mAction);
+ }
+
+ final int layoutId;
+ final int titleId;
+ if (mAction.equals(FullBackup.FULL_BACKUP_INTENT_ACTION)) {
+ layoutId = R.layout.confirm_backup;
+ titleId = R.string.backup_confirm_title;
+ } else if (mAction.equals(FullBackup.FULL_RESTORE_INTENT_ACTION)) {
+ layoutId = R.layout.confirm_restore;
+ titleId = R.string.restore_confirm_title;
+ } else {
+ Slog.w(TAG, "Backup/restore confirmation activity launched with invalid action!");
+ finish();
+ return;
+ }
+
setTitle(titleId);
setContentView(layoutId);
@@ -202,7 +243,7 @@
// if we're a relaunch we may need to adjust button enable state
if (icicle != null) {
- mDidAcknowledge = icicle.getBoolean(DID_ACKNOWLEDGE, false);
+ mDidAcknowledge = icicle.getBoolean(KEY_DID_ACKNOWLEDGE, false);
mAllowButton.setEnabled(!mDidAcknowledge);
mDenyButton.setEnabled(!mDidAcknowledge);
}
@@ -249,7 +290,9 @@
@Override
protected void onSaveInstanceState(Bundle outState) {
- outState.putBoolean(DID_ACKNOWLEDGE, mDidAcknowledge);
+ outState.putBoolean(KEY_DID_ACKNOWLEDGE, mDidAcknowledge);
+ outState.putInt(KEY_TOKEN, mToken);
+ outState.putString(KEY_ACTION, mAction);
}
void sendAcknowledgement(int token, boolean allow, IFullBackupRestoreObserver observer) {
diff --git a/packages/MtpDocumentsProvider/AndroidManifest.xml b/packages/MtpDocumentsProvider/AndroidManifest.xml
index c0a59b3..8d79f62 100644
--- a/packages/MtpDocumentsProvider/AndroidManifest.xml
+++ b/packages/MtpDocumentsProvider/AndroidManifest.xml
@@ -3,7 +3,6 @@
package="com.android.mtp"
android:sharedUserId="android.media">
<uses-feature android:name="android.hardware.usb.host" />
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.MANAGE_USB" />
<application android:label="@string/app_label">
<provider
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
index 6c74418..f6a259d 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
@@ -889,7 +889,7 @@
private PersistenceManager() {
mStatePersistFile = new AtomicFile(new File(getFilesDir(),
- PERSIST_FILE_NAME));
+ PERSIST_FILE_NAME), "print-spooler");
}
public void writeStateLocked() {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
index 7935440..5be0176 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
@@ -547,7 +547,7 @@
private PersistenceManager(final Activity activity, final int internalLoaderId) {
mStatePersistFile = new AtomicFile(new File(activity.getFilesDir(),
- PERSIST_FILE_NAME));
+ PERSIST_FILE_NAME), "printer-history");
// Initialize enabled services to make sure they are set are the read task might be done
// before the loader updated the services the first time.
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
index faa10cc..8b00ed0 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
@@ -23,7 +23,6 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
-
import com.android.printspooler.R;
/**
@@ -411,7 +410,7 @@
mPrintButton.offsetTopAndBottom(dy);
- mDraggableContent.notifyAccessibilitySubtreeChanged();
+ mDraggableContent.notifySubtreeAccessibilityStateChangedIfNeeded();
onDragProgress(progress);
}
diff --git a/packages/SettingsLib/Android.mk b/packages/SettingsLib/Android.mk
index 69287e8..4338d26 100644
--- a/packages/SettingsLib/Android.mk
+++ b/packages/SettingsLib/Android.mk
@@ -14,10 +14,10 @@
android-support-v7-preference \
android-support-v7-appcompat \
android-support-v14-preference \
- apptoolkit-lifecycle-runtime
+ android-arch-lifecycle-runtime
LOCAL_SHARED_JAVA_LIBRARIES := \
- apptoolkit-lifecycle-common
+ android-arch-lifecycle-common
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/packages/SettingsLib/common.mk b/packages/SettingsLib/common.mk
index 14f0625..3c2ca2d 100644
--- a/packages/SettingsLib/common.mk
+++ b/packages/SettingsLib/common.mk
@@ -64,7 +64,7 @@
LOCAL_STATIC_JAVA_LIBRARIES += \
android-support-annotations \
android-support-v4 \
- apptoolkit-lifecycle-runtime \
- apptoolkit-lifecycle-common \
+ android-arch-lifecycle-runtime \
+ android-arch-lifecycle-common \
SettingsLib
endif
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 93c0e10..b3ea9fb 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Inligtingruiling"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Draadlose skermsertifisering"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktiveer Wi-Fi-woordryke aanmelding"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Laat altyd Wi-Fi-swerfskanderings toe"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Gekoppelde MAC-verewekansiging"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data is altyd aktief"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardewareversnelling vir verbinding"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Wys Bluetooth-toestelle sonder name"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Voer gasheernaam van DNS-verskaffer in"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Wys opsies vir draadlose skermsertifisering"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Verhoog Wi-Fi-aantekeningvlak, wys per SSID RSSI in Wi‑Fi-kieser"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Laat toe of verbied Wi-Fi-swerfskanderings op grond van die hoeveelheid dataverkeer wat op die koppelvlak teenwoordig is"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Verewekansig MAC-adres wanneer daar aan Wi‑Fi-netwerke gekoppel word"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Loggerbuffer se groottes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Kies loggergroottes per logbuffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Maak logskrywer se aanhoudende berging skoon?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Geregistreer"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nie geregistreer nie"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Onbeskikbaar"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d toestelle is gekoppel</item>
+ <item quantity="one">%1$d toestel is gekoppel</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Meer tyd."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Minder tyd."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index a5fb9cf..9e8749b 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"ስዕሉ አልፎ የፈሰሰባቸው አካባቢዎችን አሳይ"</item>
<item msgid="2290859360633824369">"ቀይ እና አረንጓዴ የማይለይባቸው ቦታዎች አሳይ"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (ነባሪ)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"መደበኛ ወሰኖች"</item>
<item msgid="4071574792028999443">"ምንም የዳራ ሂደቶች የሉም"</item>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 83fd2af..466c01b 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"አውታረ መረብ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"የገመድ አልባ ማሳያ እውቅና ማረጋገጫ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"የWi‑Fi ተጨማሪ ቃላት ምዝግብ ማስታወሻ መያዝ"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ሁልጊዜ የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"የተገናኘ የማክ ዘፈቀደ መስሪያ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"የተንቀሳቃሽ ስልክ ውሂብ ሁልጊዜ ገቢር ነው"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"የሃርድዌር ማቀላጠፊያን በማስተሳሰር ላይ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"የብሉቱዝ መሣሪያዎችን ያለ ስሞች አሳይ"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"የዲኤንኤስ አቅራቢ አስተናጋጅ ስም ያስገቡ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"የገመድ አልባ ማሳያ እውቅና ማረጋገጫ አማራጮችን አሳይ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"የWi‑Fi ምዝግብ ማስታወሻ አያያዝ ደረጃ ጨምር፣ በWi‑Fi መምረጫ ውስጥ በአንድ SSID RSSI አሳይ"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"በበይነገጹ ላይ ባለው የውሂብ ትራፊክ መጠን ላይ ተመስርተው የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ/ይከልክሉ"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ከWi-Fi አውታረ መረቦች ጋር ሲገናኙ የማክ አድራሻን በዘፈቀደ ይስሩ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"የምዝግብ ማስታወሻ ያዥ መጠኖች"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"በአንድ ምዝግብ ማስታወሻ ቋጥ የሚኖረው የምዝግብ ማስታወሻ ያዥ መጠኖች ይምረጡ"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"የምዝግብ ማስታወሻ ያዢ ቋሚ ማከማቻ ይጽዳ?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"የሃርድዌር ንብርብሮች ዝማኔዎችን አሳይ"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"የሃርድዌር ንብርብሮች ሲዘምኑ አረንጓዴ አብራ"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"የጂፒዩ አልፎ መሳል አርም"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"የGPU አሳዪ አዘጋጅ"</string>
<string name="disable_overlays" msgid="2074488440505934665">"የHW ተደራቢዎችን አሰናክል"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"ለማያ ገጽ ማቀናበሪያ ሁልጊዜ GPU ተጠቀም"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"የቀለም ህዋ አስመስል"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"የተመዘገበ"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"አልተመዘገበም"</string>
<string name="status_unavailable" msgid="7862009036663793314">"አይገኝም"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d መሣሪያዎች ተገናኝተዋል</item>
+ <item quantity="other">%1$d መሣሪያዎች ተገናኝተዋል</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"ተጨማሪ ጊዜ።"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"ያነሰ ጊዜ።"</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"አብራ"</string>
+ <string name="cancel" msgid="6859253417269739139">"ይቅር"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"አትረብሽን አብራ"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"በጭራሽ"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"ቅድሚያ የሚሰጠው ብቻ"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>። <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index a541cbd..3149af0 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"الشبكات"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"شهادة عرض شاشة لاسلكي"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"تمكين تسجيل Wi‑Fi Verbose"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"السماح دائمًا بعمليات فحص Wi-Fi للتجوال"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"اختيار عشوائي لعنوان MAC"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"بيانات الجوّال نشطة دائمًا"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"تسريع الأجهزة للتوصيل"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"عرض أجهزة البلوتوث بدون أسماء"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"أدخل اسم مضيف مزوّد نظام أسماء النطاقات"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"عرض خيارات شهادة عرض شاشة لاسلكي"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"زيادة مستوى تسجيل Wi-Fi، وعرض لكل SSID RSSI في منتقي Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"السماح/عدم السماح بعمليات فحص Wi-Fi للتجوال بناءً على حجم حركة البيانات في الواجهة"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"اختيار عشوائي لعنوان MAC عند الاتصال بشبكات Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"أحجام ذاكرة التخزين المؤقت للتسجيل"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"حدد أحجامًا أكبر لكل ذاكرة تخزين مؤقت للتسجيل"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"هل تريد محو سعة التخزين الدائمة للمسجِّل؟"</string>
@@ -403,4 +403,14 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"مُسجَّل"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"غير مُسجَّل"</string>
<string name="status_unavailable" msgid="7862009036663793314">"غير متاح"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="zero">عدد الأجهزة المتصلة %1$d</item>
+ <item quantity="two">عدد الأجهزة المتصلة %1$d</item>
+ <item quantity="few">عدد الأجهزة المتصلة %1$d</item>
+ <item quantity="many">عدد الأجهزة المتصلة %1$d</item>
+ <item quantity="other">عدد الأجهزة المتصلة %1$d</item>
+ <item quantity="one">عدد الأجهزة المتصلة %1$d</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"وقت أكثر."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"وقت أقل."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 9048d93..b4ee3cc 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Böyütmə sahələrini göstər"</item>
<item msgid="2290859360633824369">"Daltonizm üçün sahələri göstərin"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (Defolt)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Standart limit"</item>
<item msgid="4071574792028999443">"Fon proses yoxdur"</item>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 5b4e45c..80536e1 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Şəbəkələşmə"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Simsiz displey sertifikatlaşması"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Çoxsözlü Girişə icazə verin"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi axtarışlarına həmişə icazə verin"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Qoşulmuş MAC Randomizasiyası"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil data həmişə aktiv"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Birləşmə üçün avadanlıq akselerasiyası"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth cihazlarını adsız göstərin"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderinin host adını daxil edin"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz displey sertifikatlaşması üçün seçimləri göstərir"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi giriş səviyyəsini qaldırın, Wi‑Fi seçəndə hər SSID RSSI üzrə göstərin"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wi‑Fi Axtarışlarına data trafikinə əsasən İcazə verin/Qadağan edin"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi şəbkələrinə qoşulan zaman ixtiyari MAC ünvanı seçin"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger bufer ölçüləri"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Hər jurnal buferinı Logger ölçüsü seçin"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Loqqerin davamlı yaddaşı silinsin?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Avadanlıq düzənlərinin güncəlləşməsini göstərin"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Onlar güncəllənəndən sonra avadanlıq qatlarında işartı olsun"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU böyütməsini sazlayın"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Renderi ayarlayın"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW overlay deaktiv edin"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Həmişə ekran kompozisiyası üçün GPU istifadə edin"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Rəng sahəsini simulyasiya edin"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Qeydiyyatlı"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Qeydiyyatsız"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Əlçatmazdır"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d cihaz qoşuludur</item>
+ <item quantity="one">%1$d cihaz qoşuludur</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Daha çox vaxt."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Daha az vaxt."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Aktiv edin"</string>
+ <string name="cancel" msgid="6859253417269739139">"Ləğv et"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\"Narahat Etməyin\" rejimini aktiv edin"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Heç vaxt"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Yalnız prioritet"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 0545021..9ebb651 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Sertifikacija bežičnog ekrana"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući detaljniju evidenciju za Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvek dozvoli skeniranje Wi‑Fi-ja u romingu"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Nasumičan izbor MAC adrese tokom povezivanja"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci su uvek aktivni"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje privezivanja"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Prikaži Bluetooth uređaje bez naziva"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite ime hosta dobavljača usluge DNS-a"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaz opcija za sertifikaciju bežičnog ekrana"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećava nivo evidentiranja za Wi‑Fi. Prikaz po SSID RSSI-u u biraču Wi‑Fi mreže"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/zabrani skeniranje Wi-Fi-ja u romingu na osnovu prisutnog protoka podataka na interfejsu"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Izaberi nasumičnu MAC adresu tokom povezivanja na Wi‑Fi mreže"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera podataka u programu za evidentiranje"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izaberite veličine po baferu evidencije"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Želite li da obrišete stalni memorijski prostor programa za evidentiranje?"</string>
@@ -403,4 +403,11 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrovan je"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nije registrovan"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Nedostupno"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">Povezan je %1$d uređaj</item>
+ <item quantity="few">Povezana su %1$d uređaja</item>
+ <item quantity="other">Povezano je %1$d uređaja</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Više vremena."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Manje vremena."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index ce5ca02..8253b39c 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Паказаць вобласці з перабольшваннем"</item>
<item msgid="2290859360633824369">"Паказаць вобласці для дэйтэранамаліі"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (стандартны)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Стандартны ліміт"</item>
<item msgid="4071574792028999443">"Няма фонавых працэсаў"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 05be2228..9ea825d 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Сеткі"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Сертыфікацыя бесправаднога дысплея"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Уключыць падрабязны журнал Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Заўсёды дазваляць роўмінгавае сканіраванне Wi‑Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Стварэнне выпадковых MAC-адрасоў пры падключэнні па Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мабільная перадача даных заўсёды актыўная"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратнае паскарэнне ў рэжыме мадэма"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Паказваць прылады Bluetooth без назваў"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Увядзіце імя вузла аператара DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Паказаць опцыі сертыфікацыі бесправаднога дысплея"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Падвыс. узровень дэтал-цыі журнала Wi‑Fi у залежн. ад SSID RSSI у Wi‑Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дазволіць/забараніць роўмінгавае сканіраванне Wi‑Fi ў залежнасці ад аб\'ёму трафіку даных у інтэрфейсе"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Генерыраваць выпадковы MAC-адрас пры падключэнні да сетак Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Памеры буфера для сродку вядзення журнала"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберыце памеры сродку вядзення журнала для буфераў журнала"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Ачысціць пастаяннае сховішча журнала?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Паказаць абнаўленнi апаратнага пласта"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Апаратныя пласты набываюць зялёны колер, калi абнаўляюцца"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Адладка перамалёўкі GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Задаць рэндэрар графікі"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Адкл. апаратн. накладання"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Заўсёды выкарыстоўваць GPU для экраннай кампаноўкі"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Сімуляцыя каляр. прасторы"</string>
@@ -403,4 +402,18 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Зарэгістраваны"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Не зарэгістраваны"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Адсутнічае"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d прылада падключана</item>
+ <item quantity="few">%1$d прылады падключаны</item>
+ <item quantity="many">%1$d прылад падключана</item>
+ <item quantity="other">%1$d прылады падключана</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Больш часу."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Менш часу."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Уключыць"</string>
+ <string name="cancel" msgid="6859253417269739139">"Скасаваць"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Уключэнне рэжыму \"Не турбаваць\""</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Ніколі"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Толькі прыярытэтныя"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index ea67a98..8186a03 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Мрежи"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Безжичен дисплей"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"„Многословно“ регистр. на Wi‑Fi: Актив."</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Сканирането за роуминг на Wi-Fi да е разрешено винаги"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Рандомизиране на свързания MAC адрес"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Винаги активни мобилни данни"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардуерно ускорение за тетъринга"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Показване на устройствата с Bluetooth без имена"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Въведете името на хоста на DNS доставчика"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показване на опциите за сертифициране на безжичния дисплей"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"По-подробно регистр. на Wi‑Fi – данни за RSSI на SSID в инстр. за избор на Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Разрешаване/забраняване на сканирането за роуминг на Wi-Fi въз основа на посочения в интерфейса обем на трафика на данни"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Рандомизиране на MAC адреса при свързване с Wi-Fi мрежи"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Размери на регистрац. буфери"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Размер на един рег. буфер: Избор"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Да се изчистят ли трайно съхраняваните регистрационни данни?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Регистрирано"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Не е регистрирано"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Няма данни"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d устройства са свързани</item>
+ <item quantity="one">%1$d устройство е свързано</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Повече време."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"По-малко време."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index 60869c4..a93a9aa 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"অতিবর্ণনা এলাকা দেখান"</item>
<item msgid="2290859360633824369">"বর্ণান্ধতার জন্য এলাকা দেখান"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (ডিফল্ট)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"মানক সীমা"</item>
<item msgid="4071574792028999443">"কোন ব্যাকগ্রাউন্ড প্রক্রিয়া নেই"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index f30ed2b..2f6748f 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -142,7 +142,7 @@
<string name="tts_play_example_summary" msgid="8029071615047894486">"কথন সংশ্লেষণের উপর একটি ছোট ডেমো প্লে করুন"</string>
<string name="tts_install_data_title" msgid="4264378440508149986">"ভয়েস ডেটা ইনস্টল করুন"</string>
<string name="tts_install_data_summary" msgid="5742135732511822589">"বিবৃতি সংশ্লেষণের জন্য প্রয়োজনীয় ভয়েস ডেটা ইনস্টল করুন"</string>
- <string name="tts_engine_security_warning" msgid="8786238102020223650">"এই বিবৃতি সংশ্লেষণ ইঞ্জিন হয়তো পাসওয়ার্ড এবং ক্রেডিট কার্ড নম্বর সহ কথ্য সমস্ত টেক্সট সংগ্রহ করতে সক্ষম হতে পারে। এটি <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ইঞ্জিন থেকে আসে। এই বিবৃতি সংশ্লেষণ ইঞ্জিন সক্রিয় করবেন?"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"এই বিবৃতি সংশ্লেষণ ইঞ্জিন হয়ত পাসওয়ার্ড এবং ক্রেডিট কার্ড নম্বর সহ কথ্য সমস্ত টেক্সট সংগ্রহ করতে সক্ষম হতে পারে। এটি <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ইঞ্জিন থেকে আসে। এই বিবৃতি সংশ্লেষণ ইঞ্জিন সক্রিয় করবেন?"</string>
<string name="tts_engine_network_required" msgid="1190837151485314743">"পাঠ্য থেকে ভাষ্য আউটপুটের জন্য এই ভাষার একটি কাজ করছে এমন নেটওয়ার্ক সংযোগ প্রয়োজন।"</string>
<string name="tts_default_sample_string" msgid="4040835213373086322">"এটি হল ভাষ্য সংশ্লেষণের একটি উদাহরণ"</string>
<string name="tts_status_title" msgid="7268566550242584413">"ডিফল্ট ভাষা স্থিতি"</string>
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"নেটওয়ার্কিং"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ওয়্যারলেস ডিসপ্লে সার্টিফিকেশন"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"ওয়াই-ফাই ভারবোস লগিং সক্ষম করুন"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"সর্বদা ওয়াই ফাই রোম স্ক্যানকে অনুমতি দিন"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"সংযুক্ত MAC র্যান্ডমাইজেশন"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"মোবাইল ডেটা সব সময় সক্রিয় থাক"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"নামহীন ব্লুটুথ ডিভাইসগুলি দেখুন"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ডিএনএস প্রদানকারীর হোস্টনেম লিখুন"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ইন্টারফেসে উপস্থিত ডেটা ট্রাফিকের পরিমাণের উপরে ভিত্তি করে ওয়াই-ফাই রোম স্ক্যানকে অনুমোদিত/অননুমোদিত করুন"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ওয়াই-ফাই নেটওয়ার্কে সংযুক্ত করার সময় MAC অ্যাড্রেস র্যান্ডমাইজ করুন"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"লগার বাফারের আকারগুলি"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"লগ বাফার প্রতি অপেক্ষাকৃত বড় আকারগুলির বেছে নিন"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"লগারের স্টোরেজ সাফ করবেন?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"হার্ডওয়্যার স্তর আপডেটগুলি প্রদর্শন করুন"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"যখন হার্ডওয়্যার স্তরগুলি আপডেট হয় তখন সেগুলিকে সবুজ রঙে ফ্ল্যাশ করুন"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"ডিবাগ GPU ওভারড্র"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU রেন্ডারার সেট করুন"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW আচ্ছাদনগুলি অক্ষম করুন"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"সর্বদা স্ক্রীন কম্পোসিটিংয়ের জন্য GPU ব্যবহার করুন"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"রঙ স্থান নকল করুন"</string>
@@ -397,10 +396,22 @@
<string name="active_input_method_subtypes" msgid="3596398805424733238">"সক্রিয় ইনপুট পদ্ধতিগুলি"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"সিস্টেমের ভাষাগুলি ব্যবহার করুন"</string>
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> জন্য সেটিংস খুলতে ব্যর্থ হয়েছে"</string>
- <string name="ime_security_warning" msgid="4135828934735934248">"এই ইনপুট পদ্ধতিটি হয়তো পাসওয়ার্ড এবং ক্রেডিট কার্ড নম্বর সহ আপনার টাইপ করা সমস্ত টেক্সট সংগ্রহ করতে সক্ষম হতে পারে। এটি <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> অ্যাপ থেকে এসেছে। এই ইনপুট পদ্ধতিটি ব্যবহার করবেন?"</string>
+ <string name="ime_security_warning" msgid="4135828934735934248">"এই ইনপুট পদ্ধতিটি হয়ত পাসওয়ার্ড এবং ক্রেডিট কার্ড নম্বর সহ আপনার টাইপ করা সমস্ত টেক্সট সংগ্রহ করতে সক্ষম হতে পারে। এটি <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> অ্যাপ থেকে এসেছে। এই ইনপুট পদ্ধতিটি ব্যবহার করবেন?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"দ্রষ্টব্য: পুনরায় চালু করার পরে, আপনি আপনার ফোন আনলক না করা পর্যন্ত এই অ্যাপটিকে চালু করতে পারবেন না"</string>
<string name="ims_reg_title" msgid="7609782759207241443">"IMS রেজিস্ট্রেশনের স্থিতি"</string>
<string name="ims_reg_status_registered" msgid="933003316932739188">"রেজিস্টার করা"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"রেজিস্টার করা নয়"</string>
<string name="status_unavailable" msgid="7862009036663793314">"অনুপলব্ধ"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$dটি ডিভাইস সংযুক্ত</item>
+ <item quantity="other">%1$dটি ডিভাইস সংযুক্ত</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"আরও বেশি।"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"আরও কম।"</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"চালু করুন"</string>
+ <string name="cancel" msgid="6859253417269739139">"বাতিল"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\'বিরক্ত করবেন না\' মোড চালু করুন"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"কখনও নয়"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"শুধুমাত্র অগ্রাধিকার"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index af04a04..04cb9e9 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Prikaži područja preklapanja"</item>
<item msgid="2290859360633824369">"Prikaži područja za Deuteranomaly"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (Zadano)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Standardno ograničenje"</item>
<item msgid="4071574792028999443">"Nema pozadinskih procesa"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 915eb49..433bbdb 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogućiti Wi-Fi Verbose zapisivanje"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopustiti Wi-Fi lutajuće skeniranje"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Povezana randomizacija MAC adrese"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna mreža za prijenos podataka je uvijek aktivna"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje dijeljenja veze"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Prikaži Bluetooth uređaje bez naziva"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv host računara pružaoca DNS-a"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži opcije za certifikaciju Bežičnog prikaza"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećajte nivo Wi-Fi zapisivanja, pokazati po SSID RSSI Wi-Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/Zabrani Wi-Fi lutajuće skeniranje na osnovu količine podatkovnog saobraćaja prisutnog na interfejsu"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Nasumično odaberi MAC adresu prilikom povezivanja na Wi-Fi mreže"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera za zapisnik"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Odaberite veličine za Logger prema međumemoriji evidencije"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Želite li izbrisati trajnu pohranu zapisivača?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Prikaži dodatne informacije za ažuriranja za hardver"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Trepći hardverske slojeve zeleno kada se ažuriraju"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Otkl. greške GPU preklap."</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Postavite GPU renderer"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Onemog. HW preklapanja"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Uvijek koristi GPU za kompoziciju ekrana"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simuliraj prostor boje"</string>
@@ -403,4 +402,17 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrirano"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nije registrirano"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Nije dostupno"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d povezan uređaj</item>
+ <item quantity="few">%1$d povezana uređaja</item>
+ <item quantity="other">%1$d povezanih uređaja</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Više vremena."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Manje vremena."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Uključi"</string>
+ <string name="cancel" msgid="6859253417269739139">"Otkaži"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Uključi način rada Ne ometaj"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikada"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Samo prioriteti"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index d8c6693..60531f2 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Xarxes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificació de pantalla sense fil"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Activa el registre Wi‑Fi detallat"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permet sempre cerca de Wi-Fi en ininerància"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Aleatorització de MAC amb connexió"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dades mòbils sempre actives"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Acceleració per maquinari per compartir la xarxa"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostra els dispositius Bluetooth sense el nom"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introdueix el nom d\'amfitrió del proveïdor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra les opcions de certificació de pantalla sense fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Augmenta nivell de registre Wi‑Fi i mostra\'l per SSID RSSI al Selector de Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permet/No permetis cerques de xarxes Wi-Fi en itinerància basades en la quantitat de dades presents a la interfície"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Aleatoritza l\'adreça MAC quan estiguis connectat a una xarxa Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Mides memòria intermèdia Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Mida Logger per memòria intermèdia"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vols esborrar l\'emmagatzematge persistent del registrador?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrat"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Sense registrar"</string>
<string name="status_unavailable" msgid="7862009036663793314">"No disponible"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d dispositius connectats</item>
+ <item quantity="one">%1$d dispositiu connectat</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Més temps"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Menys temps"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 41ff8e2..058f6a7 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Sítě"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikace bezdrát. displeje"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Podrobné protokolování Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povolit Wi-Fi roaming"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Náhodné adresy MAC při připojení"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilní data jsou vždy aktivní"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarová akcelerace tetheringu"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Zobrazovat zařízení Bluetooth bez názvů"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Zadejte název hostitele poskytovatele DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobrazit možnosti certifikace bezdrátového displeje"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšit úroveň protokolování Wi‑Fi zobrazenou v SSID a RSSI při výběru sítě Wi‑Fi."</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Povolí nebo zakáže Wi-Fi roaming na základě množství datového provozu na rozhraní."</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Při připojení k sítím Wi-Fi používat náhodnou adresu MAC"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Vyrovnávací paměť protokol. nástroje"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Velikost vyrovnávací paměti protokol. nástroje"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vymazat trvalé úložiště protokolovacího nástroje?"</string>
@@ -403,4 +403,12 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrováno"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Neregistrováno"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Není k dispozici"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="few">Připojena %1$d zařízení</item>
+ <item quantity="many">Připojeno %1$d zařízení</item>
+ <item quantity="other">Připojeno %1$d zařízení</item>
+ <item quantity="one">Připojeno %1$d zařízení</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Delší doba"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Kratší doba"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 17d1f08..98bbaa2 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Netværk"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificering af trådløs skærm"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivér detaljeret Wi-Fi-logføring"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillad altid scanning af Wi-Fi-roaming"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Forbindelse med tilfældig MAC-adresse"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er altid aktiveret"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareacceleration ved netdeling"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Vis Bluetooth-enheder uden navne"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Angiv hostname for DNS-udbyder"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis valgmuligheder for certificering af trådløs skærm"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øg mængden af Wi‑Fi-logføring. Vis opdelt efter SSID RSSI i Wi‑Fi-vælgeren"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillad/forbyd scanning i forbindelse med Wi-Fi-roaming afhængigt af mængden af datatrafik i grænsefladen"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Brug en tilfældig MAC-adresse, når der oprettes forbindelse til Wi‑Fi-netværk"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Størrelser for Logger-buffer"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Vælg Logger-størrelser pr. logbuffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vil du rydde det permanente lager for logger?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registreret"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ikke registreret"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Utilgængelig"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d enhed er tilsluttet</item>
+ <item quantity="other">%1$d enheder er tilsluttet</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Mere tid."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Mindre tid."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 2fbac93..cf8a1a2 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Netzwerke"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Kabellose Übertragung"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ausführliche WLAN-Protokolle aktivieren"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"WLAN-Roamingsuchen immer zulassen"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Verbundene randomisierte MAC-Adresse"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile Datennutzung immer aktiviert"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarebeschleunigung für Tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth-Geräte ohne Namen anzeigen"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostname des DNS-Anbieters eingeben"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Optionen zur Zertifizierung für kabellose Übertragung anzeigen"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Level für WLAN-Protokollierung erhöhen, in WiFi Picker pro SSID-RSSI anzeigen"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"WLAN-Roamingsuchen je nach Umfang des Datentraffics an der Schnittstelle zulassen bzw. nicht zulassen"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"MAC-Adresse randomisieren, wenn WLAN-Verbindungen hergestellt werden"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger-Puffergrößen"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Größe pro Protokollpuffer wählen"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Speicher der dauerhaften Protokollierung löschen?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registriert"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nicht registriert"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Nicht verfügbar"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d Geräte verbunden</item>
+ <item quantity="one">%1$d Gerät verbunden</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Mehr Zeit."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Weniger Zeit."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 25de914..95dd4cd 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Δικτύωση"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Πιστοποίηση ασύρματης οθόνης"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ενεργοποίηση λεπτομερ. καταγραφής Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Να επιτρέπεται πάντα η σάρωση Wi-Fi κατά την περιαγωγή"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Τυχαιοποίηση συνδεδεμένης διεύθυνσης MAC"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Πάντα ενεργά δεδομένα κινητής τηλεφωνίας"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Σύνδεση επιτάχυνσης υλικού"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Εμφάνιση συσκευών Bluetooth χωρίς ονόματα"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Εισαγάγετε το όνομα κεντρικού υπολογιστή του παρόχου DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Εμφάνιση επιλογών για πιστοποίηση ασύρματης οθόνης"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Αύξηση επιπέδου καταγ. Wi-Fi, εμφάνιση ανά SSID RSSI στο εργαλείο επιλογής Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Να επιτρέπεται/να μην επιτρέπεται η σάρωση Wi-Fi κατά την περιαγωγή, βάσει της ποσότητας επισκεψιμότητας δεδομένων στη διεπαφή"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Τυχαιοποίηση διεύθυνσης MAC κατά τη σύνδεση σε δίκτυα Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Μέγεθος προσωρινής μνήμης για τη λειτουργία καταγραφής"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Μέγεθος αρχείων κατ/φής ανά προ/νή μνήμη αρχείου κατ/φής"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Διαγραφή αποθηκευτικού χώρου μόνιμων αρχείων καταγραφής;"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Εγγεγραμμένη"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Μη εγγεγραμμένη"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Μη διαθέσιμο"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d συσκευές συνδέθηκαν</item>
+ <item quantity="one">%1$d συσκευή συνδέθηκε</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Περισσότερη ώρα."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Λιγότερη ώρα."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index f4fceae..418b17c 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Show overdraw areas"</item>
<item msgid="2290859360633824369">"Show areas for Deuteranomaly"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (Default)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Standard limit"</item>
<item msgid="4071574792028999443">"No background processes"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 9f5353f..9b82b7c 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Connected MAC Randomisation"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Show Bluetooth devices without names"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Randomise MAC address when connecting to Wi‑Fi networks"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Clear logger persistent storage?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Show hardware layers updates"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash hardware layers green when they update"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug GPU overdraw"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Set GPU Renderer"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Disable HW overlays"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Always use GPU for screen compositing"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simulate colour space"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registered"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Not registered"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Unavailable"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d devices connected</item>
+ <item quantity="one">%1$d device connected</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"More time."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Less time."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Turn on"</string>
+ <string name="cancel" msgid="6859253417269739139">"Cancel"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Turn on Do Not Disturb"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Never"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priority only"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index f4fceae..418b17c 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Show overdraw areas"</item>
<item msgid="2290859360633824369">"Show areas for Deuteranomaly"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (Default)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Standard limit"</item>
<item msgid="4071574792028999443">"No background processes"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 9f5353f..9b82b7c 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Connected MAC Randomisation"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Show Bluetooth devices without names"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Randomise MAC address when connecting to Wi‑Fi networks"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Clear logger persistent storage?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Show hardware layers updates"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash hardware layers green when they update"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug GPU overdraw"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Set GPU Renderer"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Disable HW overlays"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Always use GPU for screen compositing"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simulate colour space"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registered"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Not registered"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Unavailable"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d devices connected</item>
+ <item quantity="one">%1$d device connected</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"More time."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Less time."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Turn on"</string>
+ <string name="cancel" msgid="6859253417269739139">"Cancel"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Turn on Do Not Disturb"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Never"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priority only"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index f4fceae..418b17c 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Show overdraw areas"</item>
<item msgid="2290859360633824369">"Show areas for Deuteranomaly"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (Default)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Standard limit"</item>
<item msgid="4071574792028999443">"No background processes"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 9f5353f..9b82b7c 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Connected MAC Randomisation"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Show Bluetooth devices without names"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Randomise MAC address when connecting to Wi‑Fi networks"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Clear logger persistent storage?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Show hardware layers updates"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash hardware layers green when they update"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug GPU overdraw"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Set GPU Renderer"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Disable HW overlays"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Always use GPU for screen compositing"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simulate colour space"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registered"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Not registered"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Unavailable"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d devices connected</item>
+ <item quantity="one">%1$d device connected</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"More time."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Less time."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Turn on"</string>
+ <string name="cancel" msgid="6859253417269739139">"Cancel"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Turn on Do Not Disturb"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Never"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priority only"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index f4fceae..418b17c 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Show overdraw areas"</item>
<item msgid="2290859360633824369">"Show areas for Deuteranomaly"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (Default)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Standard limit"</item>
<item msgid="4071574792028999443">"No background processes"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 9f5353f..9b82b7c 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Connected MAC Randomisation"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Show Bluetooth devices without names"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Randomise MAC address when connecting to Wi‑Fi networks"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Clear logger persistent storage?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Show hardware layers updates"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash hardware layers green when they update"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug GPU overdraw"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Set GPU Renderer"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Disable HW overlays"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Always use GPU for screen compositing"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simulate colour space"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registered"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Not registered"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Unavailable"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d devices connected</item>
+ <item quantity="one">%1$d device connected</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"More time."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Less time."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Turn on"</string>
+ <string name="cancel" msgid="6859253417269739139">"Cancel"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Turn on Do Not Disturb"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Never"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priority only"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index a8561fa..6c9be08 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi Verbose Logging"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Connected MAC Randomization"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Show Bluetooth devices without names"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Randomize MAC address when connecting to Wi‑Fi networks"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Clear logger persistent storage?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registered"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Not registered"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Unavailable"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d devices connected</item>
+ <item quantity="one">%1$d device connected</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"More time."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Less time."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index eeaf18f..5bc7594 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificación de pantalla inalámbrica"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Habilitar registro detallado de Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Selección aleatoria de MAC conectada"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activados"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware de conexión mediante dispositivo portátil"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sin nombre"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ingresa el nombre de host del proveedor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones de certificación de pantalla inalámbrica"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar nivel de registro Wi-Fi; mostrar por SSID RSSI en el selector de Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/no permitir las búsquedas de Wi-Fi basadas la cantidad de tráfico de datos presente en la interfaz"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Seleccionar la dirección MAC de forma aleatoria cuando se establezca conexión con redes Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Selecciona el tamaño del Logger por búfer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"¿Borrar el almacenamiento persistente del registrador?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrado"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Sin registrar"</string>
<string name="status_unavailable" msgid="7862009036663793314">"No disponible"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d dispositivos conectados</item>
+ <item quantity="one">%1$d dispositivo conectado</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Más tiempo"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Menos tiempo"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index a752db9..7334237 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Mostrar áreas sobredibujadas"</item>
<item msgid="2290859360633824369">"Mostrar áreas para deuteranomalía"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (predeterminado)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Límite estándar"</item>
<item msgid="4071574792028999443">"Sin procesos en segundo plano"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 97d9a10..3301941 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificación de pantalla inalámbrica"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Habilitar registro Wi-Fi detallado"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Orden aleatorio de direcciones MAC conectadas"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activos"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración por hardware para conexión compartida"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sin nombre"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce el nombre de host del proveedor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones para la certificación de la pantalla inalámbrica"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar el nivel de registro de Wi-Fi, mostrar por SSID RSSI en el selector Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/No permitir búsquedas de Wi-Fi basadas en la cantidad de tráfico de datos presente en la interfaz"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Ordenar las direcciones MAC de forma aleatoria al conectarse a redes Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de registrador"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Elige el tamaño del Logger por búfer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"¿Borrar almacenamiento continuo del registrador?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Ver actualizaciones capas HW"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Iluminar capas de hardware en verde al actualizarse"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar sobredibujos de GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Elegir procesador de GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Inhabilitar superposiciones HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Usar siempre la GPU para combinar pantallas"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simular espacio de color"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrado"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"No registrado"</string>
<string name="status_unavailable" msgid="7862009036663793314">"No disponible"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d dispositivos conectados</item>
+ <item quantity="one">%1$d dispositivo conectado</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Más tiempo."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Menos tiempo."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Activar"</string>
+ <string name="cancel" msgid="6859253417269739139">"Cancelar"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Activar el modo No molestar"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Solo prioritarias"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index b680b84..3447680 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Võrgustik"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Juhtmeta ekraaniühenduse sertifitseerimine"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Luba WiFi paljusõnaline logimine"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luba alati WiFi-rändluse skannimine"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Juhusliku MAC-aadressi määramine ühendamisel"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilne andmeside on alati aktiivne"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Jagamise riistvaraline kiirendus"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Kuva Bluetoothi seadmed ilma nimedeta"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Sisestage DNS-i teenusepakkuja hostinimi"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Juhtmeta ekraaniühenduse sertifitseerimisvalikute kuvamine"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Suurenda WiFi logimistaset, kuva WiFi valijas SSID RSSI järgi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Luba/keela WiFi-rändluse skannimine liidese andmeliikluse põhjal"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Määra WiFi-võrkudega ühenduse loomisel juhuslik MAC-aadress"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logija puhvri suurused"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Vali logija suur. logipuhvri kohta"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Kas kustutada logija püsivalt salvestatud andmed?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registreeritud"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ei ole registreeritud"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Pole saadaval"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d seadet on ühendatud</item>
+ <item quantity="one">%1$d seade on ühendatud</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Pikem aeg."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Lühem aeg."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index d4a5e6e..d573ab8 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Erakutsi gainidatzi diren eremuak"</item>
<item msgid="2290859360633824369">"Erakutsi daltonismorako eremuak"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (lehenetsia)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Muga estandarra"</item>
<item msgid="4071574792028999443">"Ez dago atzeko planoko prozesurik"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index ca8ea03..41fee20 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Sareak"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Hari gabeko bistaratze-egiaztatzea"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Gaitu Wi-Fi sareetan saioa hasteko modu xehatua"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Onartu beti ibiltaritzan Wi-Fi sareak bilatzea"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Konektatutako MAC helbideak ausaz aukeratzea"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Datu mugikorrak beti aktibo"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Konexioa partekatzeko hardwarearen azelerazioa"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Erakutsi Bluetooth gailuak izenik gabe"</string>
@@ -217,12 +217,12 @@
<string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS pribatua"</string>
<string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Hautatu DNS pribatuaren modua"</string>
<string name="private_dns_mode_off" msgid="8236575187318721684">"Desaktibatuta"</string>
- <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Aldakorra"</string>
+ <string name="private_dns_mode_opportunistic" msgid="7608409735589131766">"Ahal bada"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"DNS hornitzaile pribatuaren ostalari-izena"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Idatzi DNS hornitzailearen ostalari-izena"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Erakutsi hari gabeko bistaratze-egiaztapenaren aukerak"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Erakutsi datu gehiago Wi-Fi sareetan saioa hasterakoan. Erakutsi sarearen identifikatzailea eta seinalearen indarra Wi‑Fi sareen hautagailuan."</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Onartu edo debekatu ibiltaritzan Wi-Fi sareak bilatzea, interfazeko datu-trafikoaren arabera"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Aukeratu ausaz MAC helbideak Wi‑Fi sareetara konektatzean"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Erregistroen buffer-tamainak"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Hautatu erregistroen buffer-tamainak"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Erregistro iraunkorraren biltegia garbitu nahi duzu?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Hardware-geruzen eguneratzeak"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Eguneratu bitartean, hardware-geruzak berdez"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Araztu GPU gainidazketa"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Ezarri GPU errendatzailea"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desgaitu HW gainjartzeak"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Erabili beti GPU pantaila-muntaietarako"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simulatu kolore-espazioa"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Erregistratuta"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Erregistratu gabe"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Ez dago erabilgarri"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d gailu daude konektatuta</item>
+ <item quantity="one">%1$d gailu dago konektatuta</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Denbora gehiago."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Denbora gutxiago."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Aktibatu"</string>
+ <string name="cancel" msgid="6859253417269739139">"Utzi"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Aktibatu \"Ez molestatu\" modua"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Inoiz ez"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Lehentasuna dutenak soilik"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 675e382..34a3c31 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"شبکه"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"گواهینامه نمایش بیسیم"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"فعال کردن گزارشگیری طولانی Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"اسکنهای رومینگ Wi‑Fi همیشه مجاز است"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"تصادفیسازی MAC متصل"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"داده تلفن همراه همیشه فعال باشد"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"شتاب سختافزاری اتصال به اینترنت با تلفن همراه"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"نمایش دستگاههای بلوتوث بدون نام"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"نام میزبان ارائهدهنده DNS خصوصی را وارد کنید"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"نمایش گزینهها برای گواهینامه نمایش بیسیم"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"افزایش سطح گزارشگیری Wi‑Fi، نمایش به ازای SSID RSSI در انتخابکننده Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"مجاز/غیرمجاز کردن اسکنهای رومینگ Wi‑Fi براساس مقدار ترافیک داده موجود در واسط"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"تصادفی کردن نشانی MAC هنگام اتصال به شبکههای Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"اندازههای حافظه موقت ثبتکننده"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"انتخاب اندازه ثبتکننده در حافظه موقت ثبت"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"حافظه دائم ثبتکننده پاک شود؟"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"ثبتشده"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ثبت نشده است"</string>
<string name="status_unavailable" msgid="7862009036663793314">"در دسترس نیست"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d دستگاه متصل</item>
+ <item quantity="other">%1$d دستگاه متصل</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"زمان بیشتر."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"زمان کمتر."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index ba7fcd3..be19ed6 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Yhteysominaisuudet"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Langattoman näytön sertifiointi"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Käytä Wi-Fin laajennettua lokikirjausta"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Salli Wi-Fi-verkkovierailuskannaus aina"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Yhdistetty MAC-satunnaistaminen"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilidata aina käytössä"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Laitteistokiihdytyksen yhteyden jakaminen"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Näytä nimettömät Bluetooth-laitteet"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Anna isäntänimi tai DNS-tarjoaja."</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Näytä langattoman näytön sertifiointiin liittyvät asetukset"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Lisää Wi‑Fin lokikirjaustasoa, näytä SSID RSSI -kohtaisesti Wi‑Fi-valitsimessa."</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Salli/estä Wi-Fi-verkkovierailuskannaus liittymässä esiintyvän dataliikenteen perusteella."</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Käytä satunnaista MAC-osoitetta, kun yhdistät Wi-Fi-verkkoon"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Lokipuskurien koot"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Valitse puskurikohtaiset lokikoot"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Tyhjennetäänkö lokityökalun pysyvä tallennustila?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Rekisteröity"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ei rekisteröity"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Ei käytettävissä"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d laitetta liitetty</item>
+ <item quantity="one">%1$d laite liitetty</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Enemmän aikaa"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Vähemmän aikaa"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index be568ed..a6afcf8 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Afficher les zones de conflit"</item>
<item msgid="2290859360633824369">"Afficher les zones de deutéranomalie"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (par défaut)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Limite standard"</item>
<item msgid="4071574792028999443">"Aucun processus en arrière-plan"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index f266e2d..fa6006e 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Réseautage"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certification de l\'affichage sans fil"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Autoriser enreg. données Wi-Fi détaillées"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Sélection aléatoire de l\'adresse MAC lors de la connexion"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Données cellulaires toujours actives"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Afficher les appareils Bluetooth sans nom"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Entrez le nom d\'hôte du fournisseur DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options pour la certification d\'affichage sans fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler davantage les données Wi-Fi, afficher par SSID RSSI dans sélect. Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Autoriser ou non la détection de réseaux Wi-Fi en itinérance en fonction de l\'importance du transfert de données dans l\'interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Sélectionner l\'adresse MAC de manière aléatoire lors de la connexion aux réseaux Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tailles des mémoires tampons d\'enregistreur"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Tailles enreg. par tampon journal"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Supprimer les données de l\'enregistreur?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Mises à jour couches mat."</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Couches matérielles en vert une fois mises à jour"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Déboguer les conflits GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Chois. moteur rendu vidéo"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Désact. superpos. matér."</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Toujours utiliser le GPU pour la composition écran"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simuler esp. colorimétrique"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Enregistré"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Non enregistré"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Non accessible"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d appareil connecté</item>
+ <item quantity="other">%1$d appareils connectés</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Plus longtemps."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Moins longtemps."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Activer"</string>
+ <string name="cancel" msgid="6859253417269739139">"Annuler"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Activer la fonction « Ne pas déranger »"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Jamais"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Priorités seulement"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 87f00d1..5bf43b6 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Mise en réseau"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certification affichage sans fil"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Autoriser enreg. infos Wi-Fi détaillées"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Sélection aléatoire de l\'adresse MAC lors de la connexion"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Données mobiles toujours actives"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Afficher les appareils Bluetooth sans nom"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Saisissez le nom d\'hôte du fournisseur DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options de la certification de l\'affichage sans fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler plus infos Wi-Fi, afficher par RSSI de SSID dans outil sélection Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Autoriser ou non la détection de réseaux Wi-Fi en itinérance en fonction de l\'importance du trafic de données dans l\'interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Sélectionner l\'adresse MAC de manière aléatoire lors de la connexion aux réseaux Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tailles mémoires tampons enregistr."</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Tailles enreg. par tampon journal"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Effacer l\'espace de stockage persistant de l\'enregistreur ?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Enregistré"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Non enregistré"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Non disponible"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d appareil connecté</item>
+ <item quantity="other">%1$d appareils connectés</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Plus longtemps."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Moins longtemps."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index d06fe9c..0f43c9ba 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Mostrar áreas superpostas"</item>
<item msgid="2290859360633824369">"Mostrar áreas de deuteranomalía"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (Predeterminado)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Límite estándar"</item>
<item msgid="4071574792028999443">"Ningún proceso en segundo plano"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 9026aab..afd350c 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificado de visualización sen fíos"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Activar rexistro detallado da wifi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre buscas de itinerancia da wifi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Selección aleatoria de enderezo MAC coa conexión"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móbiles sempre activados"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware para conexión compartida"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sen nomes"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce o nome de host de provedor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opcións para o certificado de visualización sen fíos"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nivel de rexistro da wifi, mostrar por SSID RSSI no selector de wifi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/Non permitir buscas de itinerancia da wifi baseadas na cantidade de tráfico de datos presente na interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Selecciona aleatoriamente o enderezo MAC cando te conectes a redes wifi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de rexistrador"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Seleccionar tamaños por búfer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Queres borrar o almacenamento continuo do rexistrador?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Ver actualizacións capas"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Iluminar capas hardware en verde ao actualizarse"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar superposición GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Definir renderizador GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desact. superposicións HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizar sempre GPU para a composición da pantalla"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simular o espazo da cor"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Rexistrado"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Non rexistrado"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Non dispoñible"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d dispositivos conectados</item>
+ <item quantity="one">%1$d dispositivo conectado</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Máis tempo."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Menos tempo."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Activar"</string>
+ <string name="cancel" msgid="6859253417269739139">"Cancelar"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Activar modo Non molestar"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Só prioridade"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 00eb29c..61e497f 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"ઓવરડ્રો ક્ષેત્રો બતાવો"</item>
<item msgid="2290859360633824369">"Deuteranomaly માટેના ક્ષેત્રો બતાવો"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (ડિફૉલ્ટ)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"માનક સીમા"</item>
<item msgid="4071574792028999443">"કોઈ બૅકગ્રાઉન્ડ પ્રક્રિયાઓ નથી"</item>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index b1ee90b..13b2c4a 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"નેટવર્કિંગ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"વાયરલેસ ડિસ્પ્લે પ્રમાણન"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"વાઇ-ફાઇ વર્બોઝ લૉગિંગ સક્ષમ કરો"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"હંમેશા વાઇ-ફાઇ રોમ સ્કૅન્સને મંજૂરી આપો"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"MAC ઍડ્રેસ રેન્ડમાઇઝ કરવું ચાલુ કર્યું"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"મોબાઇલ ડેટા હંમેશાં સક્રિય"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"નામ વિનાના બ્લૂટૂથ ઉપકરણો બતાવો"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS પ્રદાતાના હોસ્ટનું નામ દાખલ કરો"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"વાઇ-ફાઇ લોગિંગ સ્તર વધારો, વાઇ-ફાઇ પીકરમાં SSID RSSI દીઠ બતાવો"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ઇન્ટરફેસ પર હાજર ડેટા ટ્રાફિકના પ્રમાણનાં આધારે વાઇ-ફાઇ રોમ સ્કૅન્સને મંજૂરી આપો/નામંજૂર કરો"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"વાઇ-ફાઇ નેટવર્ક સાથે જ્યારે કનેક્ટ કરી રહ્યાં હોય ત્યારે MAC ઍડ્રેસને રેન્ડમાઇઝ કરો"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"લોગર બફર કદ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"લૉગ દીઠ લૉગર કદ બફર પસંદ કરો"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"લૉગર નિરંતર સ્ટોરેજ સાફ કરીએ?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"હાર્ડવેર સ્તરોનાં અપડેટ્સ બતાવો"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"હાર્ડવેર સ્તરો અપડેટ થાય ત્યારે તેને લીલા રંગથી પ્રકાશિત કરો"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ઓવરડ્રો ડીબગ કરો"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU રેન્ડરર સેટ કરો"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW ઓવરલે અક્ષમ કરો"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"સ્ક્રીન જોડવા માટે હંમેશાં GPU નો ઉપયોગ કરો"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"રંગ સ્થાનનું અનુકરણ કરો"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"રજિસ્ટર કરેલ"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"રજિસ્ટર કરેલ નથી"</string>
<string name="status_unavailable" msgid="7862009036663793314">"અનુપલબ્ધ"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d ઉપકરણ કનેક્ટ કર્યું</item>
+ <item quantity="other">%1$d ઉપકરણો કનેક્ટ કર્યા</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"વધુ સમય."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"ઓછો સમય."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ચાલુ કરો"</string>
+ <string name="cancel" msgid="6859253417269739139">"રદ કરો"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"ખલેલ પાડશો નહીં ચાલુ કરો"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"ક્યારેય નહીં"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"માત્ર પ્રાધાન્યતા"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index e235fc5..a7a6920 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किंग"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"वायरलेस दिखाई देने के लिए प्रमाणन"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"वाई-फ़ाई वर्बोस लॉगिंग चालू करें"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"हमेशा वाई-फ़ाई रोम स्कैन करने दें"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"जुड़े हुए एमएसी (मैक) रैंडमाइज़ेशन (वाई-फ़ाई नेटवर्क से जुड़ते समय एमएसी पता बदले जाने की सुविधा)"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा हमेशा सक्रिय"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"हार्डवेयर से तेज़ी लाने के लिए टेदर करें"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"बिना नाम वाले ब्लूटूथ डिवाइस दिखाएं"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS सेवा देने वाले का होस्टनाम डालें"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस दिखाई देने के लिए प्रमाणन विकल्प दिखाएं"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाई-फ़ाई प्रवेश स्तर बढ़ाएं, वाई-फ़ाई पिकर में प्रति SSID RSSI दिखाएं"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"इंटरफ़ेस पर वर्तमान में मौजूद डेटा ट्रैफ़िक के आधार पर वाई-फ़ाई रोम स्कैन करने देता/नहीं देता है"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"वाई-फ़ाई से जुड़ते समय अलग-अलग एमएसी पते इस्तेमाल करें"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफ़र आकार"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफ़र लॉगर आकार चुनें"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"लॉगर सतत मेमोरी साफ़ करें?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"रजिस्टर है"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"रजिस्टर नहीं है"</string>
<string name="status_unavailable" msgid="7862009036663793314">"अनुपलब्ध"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d डिवाइस जुड़े हैं</item>
+ <item quantity="other">%1$d डिवाइस जुड़े हैं</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"ज़्यादा समय."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"कम समय."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index a854987..6ca3e07 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući opširnu prijavu na Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopusti slobodno traženje Wi-Fi mreže"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Nasumični odabir MAC-a pri povezivanju"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci uvijek aktivni"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje za modemsko povezivanje"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Prikaži Bluetooth uređaje bez naziva"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv hosta davatelja usluge DNS-a"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaži opcije za certifikaciju bežičnog prikaza"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećana razina prijave na Wi‑Fi, prikaz po SSID RSSI-ju u Biraču Wi‑Fi-ja"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dopustite ili blokirajte slobodno traženje Wi-Fi mreža na temelju količine podatkovnog prometa na sučelju."</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Nasumično odaberi MAC adresu pri povezivanju s Wi-Fi mrežama"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Veličine međuspremnika zapisnika"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Odaberite veličinu međuspremnika zapisnika"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Želite li izbrisati trajnu pohranu zapisivača?"</string>
@@ -403,4 +403,11 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrirano"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nije registrirano"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Nije dostupno"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">Povezan je %1$d uređaj</item>
+ <item quantity="few">Povezana su %1$d uređaja</item>
+ <item quantity="other">Povezano je %1$d uređaja</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Više vremena."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Manje vremena."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 553ed88..a842d06 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Hálózatok"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Vezeték nélküli kijelző tanúsítványa"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Részletes Wi-Fi-naplózás engedélyezése"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi-roaming ellenőrzésének engedélyezése mindig"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Csatlakoztatott MAC-címek randomizálása"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"A mobilhálózati kapcsolat mindig aktív"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Internetmegosztás hardveres gyorsítása"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Név nélküli Bluetooth-eszközök megjelenítése"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Adja meg a DNS-szolgáltató gazdagépnevét"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vezeték nélküli kijelző tanúsítványával kapcsolatos lehetőségek megjelenítése"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-naplózási szint növelése, RSSI/SSID megjelenítése a Wi‑Fi-választóban"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"A Wi-Fi-roaming ellenőrzésének engedélyezése vagy letiltása az interfészen jelen lévő adatforgalom mennyiségétől függően"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"MAC-cím véletlenszerű generálása Wi‑Fi-hálózatra való csatlakozáskor"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Naplózási puffer mérete"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Naplózási pufferméret kiválasztása"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Törli a naplózó program állandó tárhelyét?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Regisztrált"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nem regisztrált"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Nem érhető el"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d eszköz csatlakozik</item>
+ <item quantity="one">%1$d eszköz csatlakozik</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Több idő."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Kevesebb idő."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 7406554..e72bd77 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Ցույց տալ գերազանցված հատվածները"</item>
<item msgid="2290859360633824369">"Ցույց տալ դալտոնիզմի ոլորտները"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (կանխադրված)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Սովորական սահման"</item>
<item msgid="4071574792028999443">"Հետնաշերտում գործողություններ չկան"</item>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index dced49f5..7c3c3ad 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Ցանց"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Անլար էկրանի վկայագրում"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Միացնել Wi‑Fi մանրամասն գրանցամատյանները"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Միշտ թույլատրել Wi‑Fi ռոումինգի որոնումը"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"MAC հասցեների պատահական ընտրություն Wi-Fi-ին միանալիս"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Բջջային ինտերնետը միշտ ակտիվ է"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Սարքակազմի արագացման միացում"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Ցուցադրել Bluetooth սարքերն առանց անունների"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Մուտքագրեք DNS ծառայության մատակարարի խնամորդի անունը"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ցույց տալ անլար էկրանի հավաստագրման ընտրանքները"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Բարձրացնել մակարդակը, Wi‑Fi ընտրիչում ամեն մի SSID-ի համար ցույց տալ RSSI"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Թույլատրել/արգելել Wi‑Fi ռոումինգի որոնումը՝ կախված միջերեսում տվյալների երթևեկի ծավալից"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Պատահականորեն ընտրել MAC հասցեն Wi-Fi ցանցերին միանալիս"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Տեղեկամատյանի պահնակի չափերը"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Ընտրեք տեղեկամատյանի չափը մեկ պահնակի համար"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Ջնջե՞լ մատյանի մշտական հիշողությունը:"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Գրանցված է"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Գրանցված չէ"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Անհասանելի"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">Միացված է %1$d սարք</item>
+ <item quantity="other">Միացված է %1$d սարք</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Ավելացնել ժամանակը:"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Պակասեցնել ժամանակը:"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 0e2217d..724cb54 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Tampilkan area overdraw"</item>
<item msgid="2290859360633824369">"Tampilkan area untuk Buta Warna"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (Default)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Batas standar"</item>
<item msgid="4071574792028999443">"Tanpa proses latar belakang"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 5c06766..69a593c 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Jaringan"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Sertifikasi layar nirkabel"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktifkan Pencatatan Log Panjang Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Selalu izinkan Pemindaian Roaming Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Pengacakan MAC yang Terhubung"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Data seluler selalu aktif"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Akselerasi hardware tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Tampilkan perangkat Bluetooth tanpa nama"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan hostname penyedia DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tampilkan opsi untuk sertifikasi layar nirkabel"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan level pencatatan log Wi-Fi, tampilkan per SSID RSSI di Pemilih Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Izinkan/Larang Pemindaian Roaming Wi-Fi berdasarkan jumlah lalu lintas data yang ada di antarmuka"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Acak alamat MAC saat menghubungkan ke jaringan Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Ukuran penyangga pencatat log"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Ukuran Pencatat Log per penyangga log"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Hapus penyimpanan tetap pencatat log?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Tunjukkan pembaruan lapisan hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Lapisan hardware berkedip hijau saat memperbarui"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug overdraw oleh GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Setel Perender GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Nonaktifkan lapisan HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Selalu gunakan GPU untuk pengomposisian layar"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simulasikan ruang warna"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Terdaftar"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Tidak terdaftar"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Tidak Tersedia"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d perangkat terhubung</item>
+ <item quantity="one">%1$d perangkat terhubung</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Lebih lama."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Lebih cepat."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Aktifkan"</string>
+ <string name="cancel" msgid="6859253417269739139">"Batal"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Aktifkan mode Jangan Ganggu"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Tidak pernah"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Hanya untuk prioritas"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 21b8b0e..2c0a08b 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Netkerfi"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Vottun þráðlausra skjáa"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Kveikja á ítarlegri skráningu Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Leyfa alltaf reikileit með Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Slembival MAC-vistfanga við tengingu"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Alltaf kveikt á farsímagögnum"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Vélbúnaðarhröðun fyrir tjóðrun"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Sýna Bluetooth-tæki án heita"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Slá inn hýsilheiti DNS-veitu"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Sýna valkosti fyrir vottun þráðlausra skjáa"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Auka skráningarstig Wi-Fi, sýna RSSI fyrir hvert SSID í Wi-Fi vali"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Leyfa/banna reikileit með Wi-Fi á grunni þess hversu mikil gagnaumferð er fyrir hendi í viðmótinu"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Velja MAC-vistfang af handahófi þegar tengst er við Wi‑Fi net"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Annálsritastærðir biðminna"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Veldu annálsritastærðir á biðminni"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Hreinsa varanlega geymslu annálsrita?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Skráð"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ekki skráð"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Ekki tiltækt"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d tæki tengt</item>
+ <item quantity="other">%1$d tæki tengd</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Meiri tími."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Minni tími."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index 42a246d..630fe3d 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Mostra aree overdraw"</item>
<item msgid="2290859360633824369">"Mostra aree con deuteranomalia"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (predefinito)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Limite standard"</item>
<item msgid="4071574792028999443">"Nessun processo in background"</item>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 7408b25..da73e18 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Reti"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificazione display wireless"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Attiva registrazione dettagliata Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Consenti sempre scansioni roaming Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Selezione casuale dell\'indirizzo MAC con connessione"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dati mobili sempre attivi"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering accelerazione hardware"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostra dispositivi Bluetooth senza nome"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Inserisci il nome host del provider DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opzioni per la certificazione display wireless"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumenta il livello di registrazione Wi-Fi, mostrando il SSID RSSI nel selettore Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Consenti/vieta scansioni roaming Wi-Fi basate sulla quantità di traffico dati presente a livello di interfaccia"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Seleziona indirizzo MAC casuale con reti Wi-Fi collegate"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Dimensioni buffer Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Seleziona dimensioni Logger per buffer log"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Cancellare i dati nello spazio di archiviazione permanente del logger?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Aggiornam. livelli hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Lampeggia verde se aggiornam. livelli hardware"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug overdraw GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Imposta renderer GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Disabilita overlay HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Usa sempre GPU per la composizione dello schermo"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simula spazio colore"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrato"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Non registrato"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Non disponibile"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d dispositivi connessi</item>
+ <item quantity="one">%1$d dispositivo connesso</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Più tempo."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Meno tempo."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Attiva"</string>
+ <string name="cancel" msgid="6859253417269739139">"Annulla"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Attiva Non disturbare"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Mai"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Solo con priorità"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index fceaacc..adfa890 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"תקשורת רשתות"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"אישור של תצוגת WiFi"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"הפעל רישום מפורט של Wi‑Fi ביומן"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"התר תמיד סריקות נדידה של Wi‑Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"חיבור כתובת MAC אקראית"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"חבילת הגלישה פעילה תמיד"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"שיפור מהירות באמצעות חומרה לצורך שיתוף אינטרנט בין ניידים"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"הצגת מכשירי Bluetooth ללא שמות"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"צריך להזין את שם המארח של ספק DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"הצג אפשרויות עבור אישור של תצוגת WiFi"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"העלה את רמת הרישום של Wi‑Fi ביומן, הצג לכל SSID RSSI ב-Wi‑Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"התר/מנע סריקות נדידה של Wi-Fi בהתבסס על נפח תנועת הנתונים הקיימת בממשק"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"יצירת כתובת MAC אקראית בהתחברות לרשתות Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"גדלי מאגר של יומן רישום"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"בחר גדלים של יוצר יומן לכל מאגר יומן"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"האם למחוק את אחסון המתעד המתמיד?"</string>
@@ -403,4 +403,12 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"רשום"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"לא רשום"</string>
<string name="status_unavailable" msgid="7862009036663793314">"לא זמין"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="two">%1$d מכשירים מחוברים</item>
+ <item quantity="many">%1$d מכשירים מחוברים</item>
+ <item quantity="other">%1$d מכשירים מחוברים</item>
+ <item quantity="one">מכשיר אחד מחובר</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"יותר זמן."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"פחות זמן."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 671320b..1c0a941 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ネットワーク"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ワイヤレスディスプレイ認証"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi詳細ログの有効化"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fiローミングスキャンを常に許可する"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"接続先 MAC のランダム化"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"モバイルデータを常に ON にする"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"テザリング時のハードウェア アクセラレーション"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth デバイスを名前なしで表示"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS プロバイダのホスト名を入力"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ワイヤレスディスプレイ認証のオプションを表示"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fiログレベルを上げて、Wi-Fi選択ツールでSSID RSSIごとに表示します"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"インターフェースのデータトラフィック量に基づいたWi-Fiローミングスキャンを許可するかしないかを設定できます"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi ネットワーク接続時の MAC アドレスのランダム化"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ログバッファのサイズ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"各ログバッファのログサイズを選択"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ログの永続ストレージを消去しますか?"</string>
@@ -405,4 +405,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"登録済み"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"未登録"</string>
<string name="status_unavailable" msgid="7862009036663793314">"不明"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d 台の端末が接続されています</item>
+ <item quantity="one">%1$d 台の端末が接続されています</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"長くします。"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"短くします。"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 1948460..6c08a98 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ქსელი"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"უსადენო ეკრანის სერტიფიცირება"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi-ს დაწვრილებითი აღრიცხვის ჩართვა"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Roam სკანირების მუდამ დაშვება"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"დაკავშირებულია MAC მისამართის შემთხვევითობა"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"მობილური ინტერნეტის ყოველთვის გააქტიურება"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ტეტერინგის აპარატურული აჩქარება"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth-მოწყობილობების ჩვენება სახელების გარეშე"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"შეიყვანეთ DNS პროვაიდერის სერვერის სახელი"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"უსადენო ეკრანის სერტიფიცირების ვარიანტების ჩვენება"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-ს აღრიცხვის დონის გაზრდა, Wi‑Fi ამომრჩეველში ყოველ SSID RSSI-ზე ჩვენება"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wifi Roam სკანირების დაშვება/აკრძალვა, ინტერფეისზე არსებული მონაცემთა ტრაფიკზე დაფუძნებით"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"MAC მისამართის შემთხვევითობა ჩაირთოს, როცა Wi‑Fi-ქსელებთან დაკავშირება ხდება"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ჟურნალიზაციის ბუფერის ზომები"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"აირჩიეთ ჟურნ. ზომა / ჟურნ. ბუფერზე"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"გსურთ მუდმივი ჟურნალირების მეხსიერების გასუფთავება?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"რეგისტრირებული"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"არარეგისტრირებული"</string>
<string name="status_unavailable" msgid="7862009036663793314">"მიუწვდომელია"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">დაკავშირებულია %1$d მოწყობილობა</item>
+ <item quantity="one">დაკავშირებულია %1$d მოწყობილობა</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"მეტი დრო."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"ნაკლები დრო."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index b0ba2ff..6d0ac63 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Үстінен бастырылған аймақтарды көрсету"</item>
<item msgid="2290859360633824369">"Дейтераномалия аймақтарын көрсету"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (әдепкі)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Стандартты шектеу"</item>
<item msgid="4071574792028999443">"Фондық үрдістер жоқ"</item>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 2d03f7f..d9a7d03 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Желі орнату"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Сымсыз дисплей сертификаты"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi егжей-тегжейлі журналға тір. қосу"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi роумингін іздеулерге әрқашан рұқсат ету"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Қосылу кезінде MAC мекенжайларын еркін таңдау"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобильдік деректер әрқашан қосулы"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингтің аппараттық жеделдетуі"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Атаусыз Bluetooth құрылғыларын көрсету"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS провайдерінің хост атауын енгізіңіз"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Сымсыз дисплей растау опцияларын көрсету"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi жур. тір. дең. арт., Wi‑Fi желісін таңдағышта әр SSID RSSI бойынша көрсету"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфейсте бар деректер трафигінің мөлшерінің негізінде Wi-Fi роумингін іздеулерге рұқсат ету/тыйым салу"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi желісіне қосылу кезінде MAC мекенжайларын еркін таңдау"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Журналға тіркеуші буферінің өлшемдері"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Әр журнал буфері үшін журналға тіркеуші өлшемдерін таңдау"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Тіркеуіштің тұрақты жадын тазарту керек пе?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Компьютерлік жабдықтама қабаттарының жаңартулары"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Жаңартылғанда компьютерлік жабдықтама қабаттарының жасыл шамы жануы"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Үстінен бастырылғанды жөндеу"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU бейне өңдеу құралын таңдау"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Жабдықпен үстінен бастыруды өшіру"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Экранды жасақтау үшін әрқашан графикалық процессор қолдану қажет"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Түстер аймағына еліктеу"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Тіркелген"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Тіркелмеген"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Қол жетімсіз"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d құрылғы қосылды</item>
+ <item quantity="one">%1$d құрылғы қосылды</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Көбірек уақыт."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Азырақ уақыт."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Қосу"</string>
+ <string name="cancel" msgid="6859253417269739139">"Бас тарту"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\"Мазаламау\" режимін қосу"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Ешқашан"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Маңыздылары ғана"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index 3cbdc37..4328c18 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"បង្ហាញតំបន់ដែលលើស"</item>
<item msgid="2290859360633824369">"បង្ហាញតំបន់សម្រាប់ Deuteranomaly"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (លំនាំដើម)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"ដែនកំណត់ស្តង់ដារ"</item>
<item msgid="4071574792028999443">"គ្មានដំណើរការក្នុងផ្ទៃខាងក្រោយ"</item>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 1d2476c..da55fbf 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ការភ្ជាប់បណ្ដាញ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"បង្ហាញការកំណត់រចនាសម្ព័ន្ធឥតខ្សែ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"បើកកំណត់ហេតុរៀបរាប់វ៉ាយហ្វាយ"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"តែងតែអនុញ្ញាតការវិភាគរ៉ូមវ៉ាយហ្វាយ"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"ការជ្រើសរើស MAC ដោយចៃដន្យ នៅពេលបានភ្ជាប់"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ទិន្នន័យទូរសព្ទចល័តដំណើរការជានិច្ច"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ការបង្កើនល្បឿនផ្នែករឹងសម្រាប់ការភ្ជាប់"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"បង្ហាញឧបករណ៍ប្ល៊ូធូសគ្មានឈ្មោះ"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"បញ្ចូលឈ្មោះម៉ាស៊ីនរបស់ក្រុមហ៊ុនផ្ដល់សេវា DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"បង្ហាញជម្រើសសម្រាប់វិញ្ញាបនបត្របង្ហាញឥតខ្សែ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"បង្កើនកម្រិតកំណត់ហេតុវ៉ាយហ្វាយបង្ហាញក្នុង SSID RSSI ក្នុងកម្មវិធីជ្រើសវ៉ាយហ្វាយ"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"អនុញ្ញាត/មិនអនុញ្ញាតការវិភាគរ៉ូមវ៉ាយហ្វាយផ្អែកលើចំនួនការបង្ហាញចរាចរណ៍ទិន្នន័យនៅចំណុចប្រទាក់"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ជ្រើសរើសអាសយដ្ឋាន MAC ដោយចៃដន្យ នៅពេលភ្ជាប់បណ្តាញ Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ទំហំ buffer របស់ Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ជ្រើសទំហំ Logger per log buffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ជម្រះទំហំផ្ទុក logger ដែលប្រើបានយូរឬ?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"បង្ហាញបច្ចុប្បន្នភាពស្រទាប់ផ្នែករឹង"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ស្រទាប់ផ្នែករឹងបញ្ចេញពន្លឺបៃតង ពេលពួកវាធ្វើបច្ចុប្បន្នភាព"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"កែកំហុសការលើស GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"កំណត់កម្មវិធីបំប្លែង GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"បិទការត្រួត HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"ប្រើ GPU ជានិច្ចសម្រាប់ផ្សំអេក្រង់"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"ក្លែងធ្វើចន្លោះពណ៌"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"បានចុះឈ្មោះ"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"មិនបានចុះឈ្មោះ"</string>
<string name="status_unavailable" msgid="7862009036663793314">"មិនមាន"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">បានភ្ជាប់ឧបករណ៍ %1$d</item>
+ <item quantity="one">បានភ្ជាប់ឧបករណ៍ %1$d</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"រយៈពេលច្រើនជាង។"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"រយៈពេលតិចជាង។"</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"បើក"</string>
+ <string name="cancel" msgid="6859253417269739139">"បោះបង់"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"បើកមុខងារកុំរំខាន"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"កុំឱ្យសោះ"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"អាទិភាពប៉ុណ្ណោះ"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 455b0a9..e1cc086 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"ಓವರ್ಡ್ರಾ ಪ್ರದೇಶಗಳನ್ನು ತೋರಿಸು"</item>
<item msgid="2290859360633824369">"ಡ್ಯೂಟರ್ನೋಮಲಿಗಾಗಿ ಪ್ರದೇಶಗಳನ್ನು ತೋರಿಸು"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (ಡೀಫಾಲ್ಟ್)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"ಪ್ರಮಾಣಿತ ಮಿತಿ"</item>
<item msgid="4071574792028999443">"ಹಿನ್ನೆಲೆ ಪ್ರಕ್ರಿಯೆಗಳು ಇಲ್ಲ"</item>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 385308a..1e53b88 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ನೆಟ್ವರ್ಕಿಂಗ್"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ವೈರ್ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi ವೆರ್ಬೋಸ್ ಲಾಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ವೈ-ಫೈ ರೋಮ್ ಸ್ಕ್ಯಾನ್ಗಳನ್ನು ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"MAC ಯಾದೃಚ್ಛಿಕರಣವನ್ನು ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ಮೊಬೈಲ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ಹಾರ್ಡ್ವೇರ್ನ ವೇಗವರ್ಧನೆಯನ್ನು ಟೆಥರಿಂಗ್ ಮಾಡಿ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"ಹೆಸರುಗಳಿಲ್ಲದ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ತೋರಿಸಿ"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ಪೂರೈಕೆದಾರರ ಹೋಸ್ಟ್ಹೆಸರನ್ನು ನಮೂದಿಸಿ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ವೈರ್ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ತೋರಿಸು"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ಇಂಟರ್ಫೇಸ್ನಲ್ಲಿ ಲಭ್ಯವಿರುವ ಡೇಟಾ ಟ್ರಾಫಿಕ್ ಆಧಾರದ ಮೇಲೆ Wi‑Fi ರೋಮ್ ಸ್ಕ್ಯಾನ್ಗಳನ್ನು ಅನುಮತಿಸಿ/ನಿರಾಕರಿಸಿ"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳು ಸಂಪರ್ಕಿಸುವಾಗ MAC ವಿಳಾಸವನ್ನು ಯಾದೃಚ್ಛಿಕಗೊಳಿಸಿ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ಲಾಗರ್ ಬಫರ್ ಗಾತ್ರಗಳು"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್ಗೆ ಲಾಗರ್ ಗಾತ್ರಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ಶಾಶ್ವತವಾಗಿರುವ ಸಂಗ್ರಹಣೆ ಲಾಗರ್ ಅನ್ನು ತೆರವುಗೊಳಿಸುವುದೇ?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"ಹಾರ್ಡ್ವೇರ್ ಲೇಯರ್ ಅಪ್ಡೇಟ್"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ಅವುಗಳು ನವೀಕರಿಸಿದಾಗ ಹಾರ್ಡ್ವೇರ್ ಲೇಯರ್ಗಳು ಹಸಿರು ಫ್ಲ್ಯಾಶ್ ಆಗುತ್ತದೆ"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ಓವರ್ಡ್ರಾ ಡೀಬಗ್"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU ರೆಂಡರರ್ ಹೊಂದಿಸಿ"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW ಓವರ್ಲೇ ನಿಷ್ಕ್ರಿಯ"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"ಸ್ಕ್ರೀನ್ ಸಂಯೋಜನೆಗಾಗಿ ಯಾವಾಗಲೂ GPU ಬಳಸಿ"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"ಬಣ್ಣದ ಸ್ಥಳ ಸಿಮ್ಯುಲೇಟ್"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"ನೋಂದಾಯಿಸಲಾಗಿದೆ"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ನೋಂದಾಯಿಸಲಾಗಿಲ್ಲ"</string>
<string name="status_unavailable" msgid="7862009036663793314">"ಲಭ್ಯವಿಲ್ಲ"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d ಸಾಧನಗಳನ್ನು ಸಂಪರ್ಕಿಸಲಾಗಿದೆ</item>
+ <item quantity="other">%1$d ಸಾಧನಗಳನ್ನು ಸಂಪರ್ಕಿಸಲಾಗಿದೆ</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"ಹೆಚ್ಚು ಸಮಯ."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"ಕಡಿಮೆ ಸಮಯ."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ಆನ್ ಮಾಡಿ"</string>
+ <string name="cancel" msgid="6859253417269739139">"ರದ್ದುಮಾಡಿ"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಅನ್ನು ಆನ್ ಮಾಡಿ"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"ಎಂದೂ ಇಲ್ಲ"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"ಆದ್ಯತೆ ಮಾತ್ರ"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index e1be8dc..f2f952d 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"네트워크"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"무선 디스플레이 인증서"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi 상세 로깅 사용"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi 로밍 스캔 항상 허용"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"연결된 MAC 임의 선택"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"항상 모바일 데이터 활성화"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"테더링 하드웨어 가속"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"이름이 없는 블루투스 기기 표시"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS 제공업체의 호스트 이름 입력"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"무선 디스플레이 인증서 옵션 표시"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi 로깅 수준을 높이고, Wi‑Fi 선택도구에서 SSID RSSI당 값을 표시합니다."</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"인터페이스에 표시되는 데이터 트래픽의 양을 기반으로 Wi-Fi 로밍 스캔을 허용하거나 허용하지 않습니다."</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi 네트워크에 연결할 때 MAC 주소 임의 선택"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"로거 버퍼 크기"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"로그 버퍼당 로거 크기 선택"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"로거 영구 저장소를 삭제하시겠습니까?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"등록됨"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"등록되지 않음"</string>
<string name="status_unavailable" msgid="7862009036663793314">"사용할 수 없음"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">기기 %1$d개 연결됨</item>
+ <item quantity="one">기기 %1$d개 연결됨</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"시간 늘리기"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"시간 줄이기"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 721bfaa7..7b1587a 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Үстүнө тартуу аймагын көргөзүү"</item>
<item msgid="2290859360633824369">"Дейтераномалиялуулар үчүн мейкиндикти көргөзүү"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (Демейки)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Стандарттык чектөө"</item>
<item msgid="4071574792028999443">"Фондо процесстер жок"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index d323df2..1fc446f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Тармактык байланыштарды кеңейтүү"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Зымсыз дисплейди аныктоо"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi дайын-даректүү протоколун иштетүү"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi Роуминг Скандоо мүмкүнчүлүгүнө ар дайым уруксат берилсин"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Кокустан тандалган MAC дарегине туташты"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилдик Интернет иштей берсин"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингдин иштешин тездетүү"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Аталышсыз Bluetooth түзмөктөрү көрсөтүлсүн"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS түйүндүн аталышын киргизиңиз"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Зымсыз дисплейди сертификатто мүмкүнчүлүктөрүн көргөзүү"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi Кармагычта Wi‑Fi протокол деңгээлин жогорулатуу жана ар бир SSID RSSI үчүн көрсөтүү."</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфейстеги дайындар трафигинин көлөмүнө жараша Wi-Fi Роуминг скандоо мүмкүнчүлүгүн иштетүү/өчүрүү"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi тармагына туташууда кокустан тандаган MAC дарегин колдонуу"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Каттагыч буферлеринин өлчөмдөрү"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Каттоо буфери үчүн Каттагычтын көлөмүн тандаңыз"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Таржымалдын туруктуу диски тазалансынбы?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Катмарлардын аппараттык жаңырышы"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Катмарлардын аппараттык жаңырышын жашыл м-н белг."</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU үстүнө тартуусун жөндөө"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU өткөргүчүн жөндөө"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Аппар. катмарлаш-у өчүрүү"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Экранды калыптоодо ар дайым GPU колдонулсун"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Түс мейкиндигин эмуляциялоо"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Катталган"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Катталган эмес"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Жеткиликсиз"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d түзмөк туташып турат</item>
+ <item quantity="one">%1$d түзмөк туташып турат</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Көбүрөөк убакыт."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Азыраак убакыт."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Күйгүзүү"</string>
+ <string name="cancel" msgid="6859253417269739139">"Жокко чыгаруу"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\"Тынчымды алба\" режимин күйгүзүү"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Эч качан"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Шашылыш эскертмелер гана"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 6aa8ffc..d38f931 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"ສະແດງຂອບເຂດການແຕ້ມທັບ"</item>
<item msgid="2290859360633824369">"ສະແດງພື້ນທີ່ສຳລັບ Deuteranomaly"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (ຄ່າເລີ່ມຕົ້ນ)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"ຂີດຈຳກັດມາດຕະຖານ"</item>
<item msgid="4071574792028999443">"ບໍ່ມີໂປຣເຊສພື້ນຫຼັງ"</item>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 1e58af1..f65d894 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ການສ້າງເຄືອຂ່າຍ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ສະແດງການຮັບຮອງຂອງລະບົບໄຮ້ສາຍ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"ເປີດນຳໃຊ້ການເກັບປະຫວັດ Verbose Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ອະນຸຍາດການສະແກນການໂຣມ Wi‑Fi ສະເໝີ"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"ເຊື່ອມຕໍ່ການສຸ່ມ MAC ແລ້ວ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ເປີດໃຊ້ອິນເຕີເນັດມືຖືຕະຫຼອດເວລາ"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ເປີດໃຊ້ການເລັ່ງຄວາມໄວດ້ວຍຮາດແວ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"ສະແດງອຸປະກອນ Bluetooth ທີ່ບໍ່ມີຊື່"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ລະບຸຊື່ໂຮສຂອງຜູ້ໃຫ້ບໍລິການ DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ສະແດງໂຕເລືອກສຳລັບການສະແດງການຮັບຮອງລະບົບໄຮ້ສາຍ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ເພີ່ມລະດັບການເກັບປະຫວັດ Wi‑Fi, ສະແດງຕໍ່ SSID RSSI ໃນ Wi‑Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ອະນຸຍາດ/ບໍ່ອະນຸຍາດການສະແກນການໂຣມ Wi-Fi ອີງຕາມຈຳນວນຂໍ້ມູນທີ່ເກີດຂຶ້ນໃນລະດັບສ່ວນຕິດຕໍ່"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ສຸ່ມທີ່ຢູ່ MAC ເມື່ອເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ຂະໜາດບັບເຟີໂຕລັອກ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ເລືອກຂະໜາດລັອກຕໍ່ບັບເຟີ"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ລຶບລ້າງບ່ອນຈັດເກັບຖາວອນຂອງຕົວບັນທຶກບໍ່?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"ສະແດງການອັບເດດເລເຢີຂອງຮາດແວ"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ກະພິບເລເຢີຂອງຮາດແວໃຫ້ເປັນສີຂຽວເມື່ອມີການອັບເດດ"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"ແກ້ບັນຫາການແຕ້ມທັບຂອງ GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"ກຳນົດຕົວເຣັນເດີ GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"ປິດການເຮັດວຽກ HW overlays"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"ໃຊ້ GPU ໃນການວາງອົງປະກອບໜ້າຈໍສະເໝີ"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"ຈຳລອງ color space"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"ລົງທະບຽນແລ້ວ"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ບໍ່ໄດ້ລົງທະບຽນ"</string>
<string name="status_unavailable" msgid="7862009036663793314">"ບໍ່ມີຂໍ້ມູນ"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">ເຊື່ອມຕໍ່ %1$d ອຸປະກອນແລ້ວ</item>
+ <item quantity="one">ເຊື່ອມຕໍ່ %1$d ອຸປະກອນແລ້ວ</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"ເພີ່ມເວລາ."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"ຫຼຸດເວລາ."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ເປີດ"</string>
+ <string name="cancel" msgid="6859253417269739139">"ຍົກເລີກ"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"ເປີດໂໝດຫ້າມລົບກວນ"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"ບໍ່ໃຊ້"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"ສຳຄັນເທົ່ານັ້ນ"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index a35cd3c..879054e 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Tinklai"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Belaidžio rodymo sertifikavimas"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Įgal. „Wi‑Fi“ daugiaž. įraš. į žurnalą"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Visada leisti „Wi-Fi“ tarptiklinio ryšio nuskaitymą"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Atsitiktinis MAC adreso parinkimas prisijungiant"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiliojo ryšio duomenys visada suaktyvinti"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Įrenginio kaip modemo naudojimo aparatinės įrangos spartinimas"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Rodyti „Bluetooth“ įrenginius be pavadinimų"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Įveskite DNS teikėjo prieglobos serverio pavadinimą"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rodyti belaidžio rodymo sertifikavimo parinktis"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Padidinti „Wi‑Fi“ įrašymo į žurnalą lygį, rodyti SSID RSSI „Wi-Fi“ rinkiklyje"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Leisti / neleisti „Wi‑Fi“ tarptinklinio ryšio nuskaitymo, atsižvelgiant į sąsajos duomenų srauto kiekį"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Atsitiktinai parinkti MAC adresą prisijungiant prie „Wi‑Fi“ tinklų"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Registruotuvo buferio dydžiai"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pasir. registr. dydž. žurn. bufer."</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Išvalyti nuolatinę registruotuvo saugyklą?"</string>
@@ -403,4 +403,12 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Užregistruota"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Neužregistruota"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Užimta"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">Prijungtas %1$d įrenginys</item>
+ <item quantity="few">Prijungti %1$d įrenginiai</item>
+ <item quantity="many">Prijungta %1$d įrenginio</item>
+ <item quantity="other">Prijungta %1$d įrenginių</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Daugiau laiko."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Mažiau laiko."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 8239d9f..345d9af 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Tīklošana"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Bezvadu attēlošanas sertifikācija"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Iespējot Wi‑Fi detalizēto reģistrēšanu"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vienmēr atļaut Wi‑Fi meklēšanu"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Nejaušu MAC adrešu izveide savienojuma laikā"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Vienmēr aktīvs mobilo datu savienojums"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Paātrināta aparatūras darbība piesaistei"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Rādīt Bluetooth ierīces bez nosaukumiem"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ievadiet DNS pakalpojumu sniedzēja saimniekdatora nosaukumu"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rādīt bezvadu attēlošanas sertifikācijas iespējas"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Palieliniet Wi‑Fi reģistrēšanas līmeni; rādīt katram SSID RSSI Wi‑Fi atlasītājā."</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Atļaujiet/neatļaujiet Wi‑Fi meklēšanu, pamatojoties uz saskarnē saņemto datplūsmas apjomu."</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Izveidot nejaušas MAC adreses, izveidojot savienojumu ar Wi‑Fi tīkliem"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Reģistrētāja buferu lielumi"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Atlasīt reģistrētāja bufera liel."</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vai notīrīt reģistrētāja pastāvīgo krātuvi?"</string>
@@ -403,4 +403,11 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Reģistrēts"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Nav reģistrēts"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Nepieejams"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="zero">Pievienotas %1$d ierīces</item>
+ <item quantity="one">Pievienota %1$d ierīce</item>
+ <item quantity="other">Pievienotas %1$d ierīces</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Vairāk laika."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Mazāk laika."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 2d9d73ce..e10b3fb 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Прикажи пречекорени делови"</item>
<item msgid="2290859360633824369">"Прикажи делови за лица со девтераномалија"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (стандардно)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Стандардна граница"</item>
<item msgid="4071574792028999443">"Нема процеси во заднина"</item>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index eaa5539..48c7bec 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Вмрежување"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Приказ на сертификација на безжична мрежа"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Овозможи преопширно пријавување Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Секогаш дозволувај Wi‑Fi скенирање во роаминг"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Поврзана MAC-рандомизација"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилниот интернет е секогаш активен"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско забрзување за врзување"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Прикажувај уреди со Bluetooth без имиња"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Внесете име на хост на операторот на DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Покажи ги опциите за безжичен приказ на сертификат"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Зголеми Wi‑Fi ниво на пријавување, прикажи по SSID RSSI во Wi‑Fi бирач"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволи/Забрани Wi‑Fi скенирање во роаминг според количината на постоечкиот податочен сообраќај на интерфејсот."</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Користи MAC-адреса по случаен избор при поврзување на Wi‑Fi мрежи"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Величини на меѓумеморија на забележувач"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Величина/меѓумеморија на дневник"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Да се избрише постојаната меморија на дневникот?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Ажурир. слоеви на хардвер"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Осветли слоеви на хардвер со зелено кога се ажур."</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Отстр. греш. на GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Постави прикажувач на GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Оневозможи HW преклопувања"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Секогаш користи GPU за составување екран"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Симулирај простор на бои"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Регистриран"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Не е регистриран"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Недостапен"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">Поврзан е %1$d уред</item>
+ <item quantity="other">Поврзани се %1$d уреди</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Повеќе време."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Помалку време."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Вклучи"</string>
+ <string name="cancel" msgid="6859253417269739139">"Откажи"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Исклучување на „Не вознемирувај“"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Никогаш"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Само приоритетно"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 121c287..615a020 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"ഓവർഡ്രോ ഭാഗങ്ങൾ ദൃശ്യമാക്കുക"</item>
<item msgid="2290859360633824369">"വർണ്ണാന്ധതയ്ക്കായുള്ള ഭാഗങ്ങൾ ദൃശ്യമാക്കുക"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (ഡിഫോൾട്ട്)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"അടിസ്ഥാന പരിധി"</item>
<item msgid="4071574792028999443">"പശ്ചാത്തല പ്രോസസ്സുകൾ ഒന്നുമില്ല"</item>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 0ddfc79..93407ec 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"നെറ്റ്വര്ക്കിംഗ്"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"വയർലെസ് ഡിസ്പ്ലേ സർട്ടിഫിക്കേഷൻ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"വൈഫൈ വെർബോസ് ലോഗിംഗ് പ്രവർത്തനക്ഷമമാക്കുക"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"എപ്പോഴും വൈഫൈ റോം സ്കാൻ അനുവദിക്കൂ"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"കണക്റ്റ് ചെയ്ത MAC ക്രമരഹിതമാക്കൽ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"മൊബൈൽ ഡാറ്റ എല്ലായ്പ്പോഴും സജീവം"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ടെതറിംഗ് ഹാർഡ്വെയർ ത്വരിതപ്പെടുത്തൽ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"പേരില്ലാത്ത Bluetooth ഉപകരണങ്ങൾ കാണിക്കുക"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ദാതാവിന്റെ ഹോസ്റ്റുനാമം നൽകുക"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"വയർലെസ് ഡിസ്പ്ലേ സർട്ടിഫിക്കേഷനായി ഓപ്ഷനുകൾ ദൃശ്യമാക്കുക"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"വൈഫൈ പിക്കറിൽ ഓരോ SSID RSSI പ്രകാരം കാണിക്കാൻ വൈഫൈ ലോഗിംഗ് നില വർദ്ധിപ്പിക്കുക"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ഇന്റർഫേസിലെ ഡാറ്റ ട്രാഫിക്ക് സാന്നിദ്ധ്യത്തിന്റെ കണക്ക് അടിസ്ഥാനമാക്കി വൈഫൈ റോം സ്കാനുകൾ അനുവദിക്കുക/അനുവദിക്കാതിരിക്കുക"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"വൈഫൈ നെറ്റ്വർക്കുകളിലേക്ക് കണക്റ്റ് ചെയ്യുമ്പോൾ MAC വിലാസം ക്രമരഹിതമാക്കുക"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ലോഗർ ബഫർ വലുപ്പം"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ഓരോ ലോഗ് ബഫറിനും വലുപ്പം തിരഞ്ഞെടുക്കൂ"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ലോഗർ സ്ഥിര സ്റ്റോറേജ് മായ്ക്കണോ?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"ഹാർഡ്വെയർ ലേയർ അപ്ഡേറ്റ് കാണിക്കൂ"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ഹാർഡ്വെയർ ലേയറുകളുടെ അപ്ഡേറ്റുകൾ പൂർത്തിയാകുമ്പോൾ അവ പച്ച നിറത്തിൽ പ്രകാശിപ്പിക്കുക"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ഓവർഡ്രോ ഡീബഗ്ഗുചെയ്യുക"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU റെൻഡറർ സജ്ജീകരിക്കുക"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW ഓവർലേ നിഷ്ക്രിയമാക്കൂ"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"സ്ക്രീൻ കമ്പോസിറ്റുചെയ്യലിനായി എല്ലായ്പ്പോഴും GPU ഉപയോഗിക്കുക"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"വർണ്ണ സ്പെയ്സ് പ്രവർത്തിപ്പിക്കുക"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"രജിസ്റ്റർ ചെയ്തു"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"രജിസ്റ്റർ ചെയ്തിട്ടില്ല"</string>
<string name="status_unavailable" msgid="7862009036663793314">"ലഭ്യമല്ല"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d ഉപകരണങ്ങൾ കണക്റ്റ് ചെയ്തു</item>
+ <item quantity="one">%1$d ഉപകരണം കണക്റ്റ് ചെയ്തു</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"കൂടുതൽ സമയം."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"കുറഞ്ഞ സമയം."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ഓണാക്കുക"</string>
+ <string name="cancel" msgid="6859253417269739139">"റദ്ദാക്കുക"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\'ശല്യപ്പെടുത്തരുത്\' ഓണാക്കുക"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"ഒരിക്കലും ഇല്ല"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"മുൻഗണന മാത്രം"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 67c6495..5652c8d 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Сүлжээ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Утасгүй дэлгэцийн сертификат"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Verbose лог-г идэвхжүүлэх"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Роум сканыг байнга зөвшөөрөх"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Холбогдсон дурын MAC хаяг үүсгэлт (Randomization)"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобайл дата байнга идэвхтэй"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Модем болгох хардвер хурдасгуур"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Нэргүй Bluetooth төхөөрөмжийг харуулах"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS-н үйлчилгээ үзүүлэгчийн хостын нэрийг оруулах"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Утасгүй дэлгэцийн сертификатын сонголтыг харуулах"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi лог-н түвшинг нэмэгдүүлэх, Wi‑Fi Сонгогч дээрх SSID-д ногдох RSSI-г харуулах"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфэйс дээрх дата трафикын хэмжээнээс хамааран Wi‑Fi Роум Скан-г зөвшөөрөх/үл зөвшөөрөх"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi сүлжээнд холбогдох үедээ шинэ дурын (random) MAC хаяг үүсгэх"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Логгерын буферын хэмжээ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Лог буфер бүрт ногдох логгерын хэмжээг сонгоно уу"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Нэвтрэгчийн тогтмол санг устгах уу?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Бүртгэсэн"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Бүртгээгүй"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Байхгүй"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d төхөөрөмж холбосон</item>
+ <item quantity="one">%1$d төхөөрөмж холбосон</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Их хугацаа."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Бага хугацаа."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index eeb0a16..a15869e 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किंग"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"वायरलेस डिस्प्ले प्रमाणीकरण"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"वाय-फाय व्हर्बोझ लॉगिंग सक्षम करा"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"वाय-फाय रोम स्कॅनला नेहमी अनुमती द्या"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"कनेक्ट केलेले MAC Randomization"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा नेहमी सक्रिय"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिंग हार्डवेअर प्रवेग"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"नावांशिवाय ब्लूटूथ डिव्हाइस दाखवा"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS पुरवठादाराचे होस्टनाव टाका"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाय-फाय लॉगिंग स्तर वाढवा, वाय-फाय सिलेक्टरमध्ये प्रति SSID RSSI दर्शवा"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"वाय-फाय रोम स्कॅनला इंटरफेसवर उपस्थित असलेल्या रहदारी डेटाच्या प्रमाणावर आधारित अनुमती द्या/अनुमती देऊ नका"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"वाय-फाय नेटवर्कशी कनेक्ट करताना MAC अॅड्रेस रँडमाइझ करा"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफर आकार"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफर लॉगर आकार निवडा"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"लॉगरवर सतत असणारा संचय साफ करायचा?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"नोंदवलेले"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"नोंदवलेले नाही"</string>
<string name="status_unavailable" msgid="7862009036663793314">"अनुपलब्ध"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d डिव्हाइस कनेक्ट केले आहे</item>
+ <item quantity="other">%1$d डिव्हाइस कनेक्ट केली आहेत</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"जास्त वेळ."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"कमी वेळ."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index a69024c..713dc82 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Perangkaian"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Pensijilan paparan wayarles"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Dayakan Pengelogan Berjela-jela Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sentiasa benarkan Imbasan Perayauan Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Perawakan MAC Tersambung"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Data mudah alih sentiasa aktif"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Pecutan perkakasan penambatan"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Tunjukkan peranti Bluetooth tanpa nama"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan nama hos pembekal DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tunjukkan pilihan untuk pensijilan paparan wayarles"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan tahap pengelogan Wi-Fi, tunjuk setiap SSID RSSI dalam Pemilih Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Benarkan/Jangan benarkan Imbasan Perayauan Wi-Fi berdasarkan jumlah trafik data yang ada pada antara muka"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Rawakkan alamat MAC apabila menyambung ke rangkaian Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Saiz penimbal pengelog"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pilih saiz Pengelog bagi setiap penimbal log"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Kosongkan storan gigih pengelog?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Berdaftar"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Tidak didaftarkan"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Tidak tersedia"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d peranti disambungkan</item>
+ <item quantity="one">%1$d peranti disambungkan</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Lagi masa."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Kurang masa."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index 8e3ed3f..435cdf5 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"ရှိရင်းစွဲထက်ပိုသော ဧရိယာများကိုပြရန်"</item>
<item msgid="2290859360633824369">"အရောင်ရောနှောသောဧရိယာများပြရန်"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (မူရင်း)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"သတ်မှတ်စံနှုန်း"</item>
<item msgid="4071574792028999443">"နောက်ခံပြုလုပ်နေသောလုပ်ငန်းစဉ်မရှိ"</item>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 5e78249..22ac322 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ချိတ်ဆက်ဆောင်ရွက်ခြင်း"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ကြိုးမဲ့ပြသမှု အသိအမှတ်ပြုလက်မှတ်"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Verbose မှတ်တမ်းတင်ခြင်းအား ဖွင့်မည်"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi ရွမ်းရှာဖွေမှုကို အမြဲတမ်း ခွင့်ပြုမည်"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"MAC ကျပန်းပြုလုပ်မှုကို ချိတ်ဆက်ထားခြင်း"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"မိုဘိုင်းဒေတာကို အမြဲဖွင့်ထားရန်"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ဖုန်းကို မိုဒမ်အဖြစ်အသုံးပြုမှု စက်ပစ္စည်းဖြင့် အရှိန်မြှင့်တင်ခြင်း"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"အမည်မရှိသော ဘလူးတုသ်စက်ပစ္စည်းများကို ပြသရန်"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ဝန်ဆောင်မှုပေးသူ၏ အင်တာနက်လက်ခံဝန်ဆောင်ပေးသူအမည်ကို ထည့်ပါ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ကြိုးမဲ့ အခင်းအကျင်း အသိအမှတ်ပြုလက်မှတ်အတွက် ရွေးချယ်စရာများပြရန်"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi မှတ်တမ်းတင်ခြင်း နှုန်းအားမြင့်ကာ၊ Wi‑Fi ရွေးရာတွင် SSID RSSI ဖြင့်ပြပါ"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"မျက်နှာပြင်တွင် ဖော်ပြသည့် အချက်လက် အသွားအလာ ပမာဏပေါ်တွင် အခြေခံ၍ WIFI ရွမ်းရှာဖွေမှုအား ဖွင့်/ပိတ်မည်"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi ကွန်ရက်များသို့ ချိတ်ဆက်သည့်အခါ MAC လိပ်စာ ကျပန်းပြုလုပ်ခြင်း"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"လော့ဂါး ဘာဖား ဆိုက်များ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"လော့ ဘာဖားတွက် လော့ဂါးဆိုက် ရွေး"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"မှတ်တမ်းထိန်းသိမ်းပေးသည့် သိုလှောင်ခန်းကို ရှင်းလင်းမလား။"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"ဟာ့ဒ်ဝဲအလွှာများအဆင်မြှင့်မှုကိုပြရန်"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"အပ်ဒိတ်လုပ်ချိန် ဟာ့ဒ်ဝဲအလွှာများ အစိမ်းရောင်ပြပါ"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ပိုသုံးစွဲမှုအမှားရှာဖွေပြင်ဆင်ရန်"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Renderer သတ်မှတ်ပါ"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HWထပ်ဆင့်အရာများပိတ်ရန်"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"GPU ကိုမျက်နှာပြင်ခင်းကျင်းရာတွင် အမြဲသုံးပါ။"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"အရောင်နေရာတူအောင် ဖန်တီးသည်"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"မှတ်ပုံတင်ထားသည်"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"မှတ်ပုံတင်မထားပါ"</string>
<string name="status_unavailable" msgid="7862009036663793314">"မရရှိနိုင်ပါ။"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">စက် %1$d ခု ချိတ်ဆက်ထားသည်</item>
+ <item quantity="one">စက် %1$d ခု ချိတ်ဆက်ထားသည်</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"အချိန်တိုးရန်။"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"အချိန်လျှော့ရန်။"</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ဖွင့်ရန်"</string>
+ <string name="cancel" msgid="6859253417269739139">"မလုပ်တော့"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\'မနှောင့်ယှက်ရ\' ဖွင့်ခြင်း"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"ဘယ်တော့မှ"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"ဦးစားပေးများသာ"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>။ <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 1882e2e..9c304b8 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Vis overtrekksområder"</item>
<item msgid="2290859360633824369">"Vis områder for deuteranomali"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (standard)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Standard grense"</item>
<item msgid="4071574792028999443">"Ingen bakgrunnsprosesser"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d45bbc3..c501596 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Nettverk"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Trådløs skjermsertifisering"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktiver detaljert Wi-Fi-loggføring"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillat alltid skanning for Wi-Fi-roaming"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Tilfeldig MAC-adresse ved tilkobling"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er alltid aktiv"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvareakselerasjon for internettdeling"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Vis Bluetooth-enheter uten navn"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Skriv inn vertsnavnet til DNS-leverandøren"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis alternativer for sertifisering av trådløs skjerm"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øk Wi-Fi-loggenivå – vis per SSID RSSI i Wi-Fi-velgeren"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillat / ikke tillat skanning for Wi-Fi-roaming basert på mengden datatrafikk til stede i grensesnittet"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Angi tilfeldig MAC-adresse når du kobler til Wi-Fi-nettverk"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Bufferstørrelser for logg"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Velg loggstørrelse per loggbuffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vil du tømme det varige logglageret?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrert"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ikke registrert"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Ikke tilgjengelig"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d enheter er tilkoblet</item>
+ <item quantity="one">%1$d enhet er tilkoblet</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Mer tid."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Mindre tid."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index de6b86e..cd016e0 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"overdraw क्षेत्रहरू देखाउनुहोस्"</item>
<item msgid="2290859360633824369">"Deuteranomaly का लागि क्षेत्रहरू देखाउनुहोस्"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (पूर्वनिर्धारित मान)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"मानक सीमा"</item>
<item msgid="4071574792028999443">"कुनै पृष्ठभूमि प्रक्रियाहरू छैनन्"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index d26541c..a44ac29 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किङ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ताररहित प्रदर्शन प्रमाणीकरण"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi वर्बोज लग सक्षम पार्नुहोस्"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi घुम्ने स्क्यान गर्न सधैँ अनुमति दिनुहोस्"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"जडान गरिएको MAC को अनियमितता"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा सधैँ सक्रिय राख्नुहोस्"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिङको लागि हार्डवेयरको प्रवेग"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"नामकरण नगरिएका ब्लुटुथ यन्त्रहरू देखाउनुहोस्"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS प्रदायकको होस्टनाम प्रविष्ट गर्नुहोस्"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ताररहित प्रदर्शन प्रमाणीकरणका लागि विकल्पहरू देखाउनुहोस्"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi लग स्तर बढाउनुहोस्, Wi-Fi चयनकर्तामा प्रति SSID RSSI देखाइन्छ"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wi-Fi घुम्ने स्क्यान इन्टरफेसमा रहेको डेटा यातायातको मात्रामा आधारित अनुमति दिनुहोस्/नदिनुहोस्"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi नेटवर्कहरूमा जडान गर्ने बेला MAC को ठेगाना अनियमित गर्नुहोस्"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"लगर बफर आकारहरू"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"लग बफर प्रति लगर आकार चयन गर्नुहोस्"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"लगरको निरन्तर भण्डारणलाई खाली गर्ने हो?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"हार्डवेयर तह अद्यावधिक देखाउनुहोस्"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"फ्ल्यास हार्डवेयर तहहरू अपडेट हुँदा हरिया हुन्छन्"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU overdraw डिबग गर्नुहोस्"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU रेन्डरर सेट गर्नुहोस्"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW ओवरले असक्षम पार्नुहोस्"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"स्क्रिन कोम्पजिट गर्न लागि सधैँ GPU प्रयोग गर्नुहोस्"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"रंग स्पेस अनुकरण गर्नुहोस्"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"दर्ता गरिएको"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"दर्ता नगरिएको"</string>
<string name="status_unavailable" msgid="7862009036663793314">"अनुपलब्ध"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d यन्त्रहरू जडान गरिए</item>
+ <item quantity="one">%1$d यन्त्र जडान गरियो</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"थप समय।"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"कम समय।"</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"सक्रिय गर्नुहोस्"</string>
+ <string name="cancel" msgid="6859253417269739139">"रद्द गर्नुहोस्"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"बाधा नपुऱ्याउनुहोस् नामक मोडलाई सक्रिय गर्नुहोस्"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"कहिल्यै होइन"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"प्राथमिकता मात्र"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>। <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index ce25cc7..9fe32ff 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Netwerken"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificering van draadloze weergave"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Uitgebreide wifi-logregistratie insch."</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Altijd roamingscans voor wifi toestaan"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Willekeurig MAC-adres bij verbinding"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data altijd actief"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareversnelling voor tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth-apparaten zonder namen weergeven"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Geef hostnaam van DNS-provider op"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Opties weergeven voor certificering van draadloze weergave"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Logniveau voor wifi verhogen, weergeven per SSID RSSI in wifi-kiezer"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Roamingscans voor wifi (niet) toestaan op basis van de hoeveelheid dataverkeer die aanwezig is bij de interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Een willekeurig MAC-adres bij het maken van verbinding met wifi-netwerken"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger-buffergrootten"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Kies Logger-grootten per logbuffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Persistente loggeropslag wissen?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Geregistreerd"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Niet geregistreerd"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Niet beschikbaar"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d apparaten verbonden</item>
+ <item quantity="one">%1$d apparaat verbonden</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Meer tijd."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Minder tijd."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index 750aee0..85e6f81 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"ਓਵਰਡ੍ਰਾ ਖੇਤਰ ਦਿਖਾਓ"</item>
<item msgid="2290859360633824369">"Deuteranomaly ਲਈ ਖੇਤਰ ਦਿਖਾਓ"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"ਸਟੈਂਡਰਡ ਸੀਮਾ"</item>
<item msgid="4071574792028999443">"ਕੋਈ ਪਿਛੋਕੜ ਪ੍ਰਕਿਰਿਆਵਾਂ ਨਹੀਂ"</item>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index d64c30f..863b17c 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ਨੈੱਟਵਰਕਿੰਗ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"ਵਾਈ-ਫਾਈ ਵਰਬੋਸ ਲੌਗਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ਹਮੇਸ਼ਾਂ ਵਾਈ‑ਫਾਈ ਰੋਮ ਸਕੈਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"ਬੇਤਰਤੀਬਵਾਰ ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ MAC ਪਤਾ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ਮੋਬਾਈਲ ਡਾਟਾ ਹਮੇਸ਼ਾਂ ਕਿਰਿਆਸ਼ੀਲ"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ਟੈਦਰਿੰਗ ਹਾਰਡਵੇਅਰ ਐਕਸੈੱਲਰੇਸ਼ਨ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"ਅਨਾਮ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਦਿਖਾਓ"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ਪ੍ਰਦਾਨਕ ਦਾ ਹੋਸਟਨਾਮ ਦਾਖਲ ਕਰੋ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰੋ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ਵਾਈ‑ਫਾਈ ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, ਵਾਈ‑ਫਾਈ Picker ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ਇੰਟਰਫੇਸ ਤੇ ਮੌਜੂਦ ਡਾਟਾ ਟ੍ਰੈਫਿਕ ਦੀ ਮਾਤਰਾ ਦੇ ਆਧਾਰ ਤੇ ਵਾਈ-ਫਾਈ ਰੋਮ ਸਕੈਨ ਦੀ ਆਗਿਆ ਦਿਓ/ਅਸਵੀਕਾਰ ਕਰੋ"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ ਨਾਲ ਕਨੈਕਟ ਹੋਣ \'ਤੇ MAC ਪਤਾ ਬੇਤਰਤੀਬਵਾਰ ਚੁਣੋ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ਲੌਗਰ ਬਫ਼ਰ ਆਕਾਰ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ਪ੍ਰਤੀ ਲੌਗ ਬਫ਼ਰ ਲੌਗਰ ਆਕਾਰ ਚੁਣੋ"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ਕੀ ਲੌਗਰ ਪ੍ਰਸਿੱਸਟੈਂਟ ਸਟੋਰੇਜ ਨੂੰ ਸਾਫ਼ ਕਰਨਾ ਹੈ?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਾਂ ਦੇ ਅੱਪਡੇਟਾਂ ਦਿਖਾਓ"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਾਂ ਅੱਪਡੇਟ ਹੋਣ \'ਤੇ ਉਨ੍ਹਾਂ ਨੂੰ ਹਰਾ ਕਰੋ"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ਓਵਰਡ੍ਰਾ ਡੀਬੱਗ ਕਰੋ"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU ਰੈਂਡਰਰ ਸੈੱਟ ਕਰੋ"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW ਓਵਰਲੇਜ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"ਸਕ੍ਰੀਨ ਕੰਪੋਜਿਟਿੰਗ ਲਈ ਹਮੇਸ਼ਾਂ GPU ਵਰਤੋ"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"ਰੰਗ ਸਪੇਸ ਦੀ ਨਕਲ ਕਰੋ"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"ਰਜਿਸਟਰ ਕੀਤੀ ਗਈ"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ਰਜਿਸਟਰ ਨਹੀਂ ਕੀਤੀ ਗਈ"</string>
<string name="status_unavailable" msgid="7862009036663793314">"ਅਣਉਪਲਬਧ"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d ਡੀਵਾਈਸ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ</item>
+ <item quantity="other">%1$d ਡੀਵਾਈਸ ਕਨੈਕਟ ਕੀਤੇ ਗਏ</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"ਹੋਰ ਸਮਾਂ।"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"ਘੱਟ ਸਮਾਂ।"</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ਚਾਲੂ ਕਰੋ"</string>
+ <string name="cancel" msgid="6859253417269739139">"ਰੱਦ ਕਰੋ"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"ਕਦੇ ਵੀ ਨਹੀਂ"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"ਸਿਰਫ਼ ਤਰਜੀਹੀ"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>। <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index c0427c8..3141219 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Pokaż przerysowywane obszary"</item>
<item msgid="2290859360633824369">"Pokaż obszary dostosowane do deuteranomalii"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (domyślnie)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Standardowy limit"</item>
<item msgid="4071574792028999443">"Brak procesów w tle"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index d50528d..a363ee2 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Sieci"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wyświetlacz bezprzewodowy"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Szczegółowy dziennik Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Zawsze szukaj Wi-Fi w roamingu"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Losowe generowanie adresu MAC przy łączeniu"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna transmisja danych zawsze aktywna"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Akceleracja sprzętowa tetheringu"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Pokaż urządzenia Bluetooth bez nazw"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Wpisz nazwę hosta dostawcy DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaż opcje certyfikacji wyświetlacza bezprzewodowego"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zwiększ poziom rejestrowania Wi‑Fi, pokazuj według RSSI SSID w selektorze Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Zezwalaj/nie zezwalaj na wyszukiwanie sieci Wi-Fi w roamingu w zależności od natężenia ruchu"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wygeneruj losowo adres MAC podczas łączenia z siecią Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Rozmiary bufora Rejestratora"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Wybierz rozmiary Rejestratora/bufor dziennika"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Wyczyścić pamięć trwałych dzienników?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Pokaż zmiany warstw sprzęt."</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Oznaczaj aktualizowane warstwy sprzętowe na zielono"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Debuguj przerysowania GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Ustaw mech. render. GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Wyłącz nakładki HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Zawsze używaj GPU do komponowania ekranu"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Symuluj przestrzeń kolorów"</string>
@@ -403,4 +402,18 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Zarejestrowane"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Niezarejestrowane"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Niedostępny"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="few">%1$d urządzenia podłączone</item>
+ <item quantity="many">%1$d urządzeń podłączonych</item>
+ <item quantity="other">%1$d urządzenia podłączonego</item>
+ <item quantity="one">%1$d urządzenie podłączone</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Więcej czasu."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Mniej czasu."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Włącz"</string>
+ <string name="cancel" msgid="6859253417269739139">"Anuluj"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Włącz tryb Nie przeszkadzać"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nigdy"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Tylko priorytet"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index 4695829..aa5aed0 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Mostrar áreas de overdraw"</item>
<item msgid="2290859360633824369">"Mostrar áreas para daltonismo"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (padrão)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Limite padrão"</item>
<item msgid="4071574792028999443">"Sem processos em segundo plano"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 67fda03..b13a9c0 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de Display sem fio"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar registro extenso de Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Escolha aleatória de MAC conectado"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sem nomes"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Informe o nome do host do provedor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/proibir verificações de roaming de Wi-Fi com base no volume do tráfego de dados presente na interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Escolher o endereço MAC de forma aleatória quando estiver conectado a redes Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Limpar armazenamento de logger constante?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Atual. camad. de hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Piscar camadas de hardware em verde ao atualizar"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar overdraw da GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Definir renderiz. de GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desativar sobreposição HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Sempre usar a GPU para composição de tela"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simular espaço de cores"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrado"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Não registrado"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Não disponível"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d dispositivo conectado</item>
+ <item quantity="other">%1$d dispositivos conectados</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Mais tempo."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Menos tempo."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Ativar"</string>
+ <string name="cancel" msgid="6859253417269739139">"Cancelar"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Ativar o \"Não perturbe\""</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Somente prioridade"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index d7496454c4..16e3d2b 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de display sem fios"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar o registo verboso de Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre a deteção de Wi-Fi em roaming"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Seleção aleatória do MAC ligado"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware para ligação (à Internet) via telemóvel"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sem nomes"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduza o nome de anfitrião do fornecedor DNS."</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções da certificação de display sem fios"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de reg. de Wi-Fi, mostrar por RSSI de SSID no Selec. de Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/impedir a deteção de Wi-Fi em roaming com base na quantidade de tráfego de dados presente na interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Selecionar aleatoriamente o endereço MAC quando estabelecer ligação a redes Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos da memória intermédia do registo"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Selec. tam. reg. p/ mem. int. reg."</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Pretende limpar o armazenamento persistente do registo?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registado"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Não registado"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Indisponível"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d dispositivos ligados</item>
+ <item quantity="one">%1$d dispositivo ligado</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Mais tempo."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Menos tempo."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index 4695829..aa5aed0 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Mostrar áreas de overdraw"</item>
<item msgid="2290859360633824369">"Mostrar áreas para daltonismo"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (padrão)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Limite padrão"</item>
<item msgid="4071574792028999443">"Sem processos em segundo plano"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 67fda03..b13a9c0 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de Display sem fio"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar registro extenso de Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Escolha aleatória de MAC conectado"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sem nomes"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Informe o nome do host do provedor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/proibir verificações de roaming de Wi-Fi com base no volume do tráfego de dados presente na interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Escolher o endereço MAC de forma aleatória quando estiver conectado a redes Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Limpar armazenamento de logger constante?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Atual. camad. de hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Piscar camadas de hardware em verde ao atualizar"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar overdraw da GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Definir renderiz. de GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desativar sobreposição HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Sempre usar a GPU para composição de tela"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simular espaço de cores"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrado"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Não registrado"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Não disponível"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d dispositivo conectado</item>
+ <item quantity="other">%1$d dispositivos conectados</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Mais tempo."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Menos tempo."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Ativar"</string>
+ <string name="cancel" msgid="6859253417269739139">"Cancelar"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Ativar o \"Não perturbe\""</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nunca"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Somente prioridade"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index b62014e..e30e6d5 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Afișați zonele cu suprapunere"</item>
<item msgid="2290859360633824369">"Afișați zonele de deuteranomalie"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (prestabilit)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Limita standard"</item>
<item msgid="4071574792028999443">"Nu există procese de fundal"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 1e91d82..9c3f0902 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Conectare la rețele"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificare Ecran wireless"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Înregistrare prin Wi-Fi de volume mari de date"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Se permite întotdeauna scanarea traficului Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Afișare aleatorie a dispozitivului MAC conectat"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Date mobile permanent active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Accelerare hardware pentru tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Afișați dispozitivele Bluetooth fără nume"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduceți numele de gazdă al furnizorului de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afișați opțiunile pentru certificarea Ecran wireless"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Măriți niv. de înr. prin Wi‑Fi, afișați în fcț. de SSID RSSI în Selectorul Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permiteți/Nu permiteți scanarea traficului Wi-Fi în funcție de traficul de date din interfață"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Afișează aleatoriu adresa MAC când te conectezi la rețele Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Dimensiunile tamponului jurnalului"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Dimensiuni jurnal / tampon jurnal"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Ștergeți stocarea permanentă a jurnalului?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Actualiz. strat. hardware"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Straturile hardware clipesc verde la actualizare"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depanați suprapunerea"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Setați GPU pentru redare"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Dezactivați suprapun. HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizați mereu GPU pentru compunerea ecranului"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simulați spațiu culoare"</string>
@@ -403,4 +402,17 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Înregistrat"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Neînregistrat"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Indisponibilă"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="few">%1$d dispozitive conectate</item>
+ <item quantity="other">%1$d de dispozitive conectate</item>
+ <item quantity="one">%1$d dispozitiv conectat</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Mai mult timp."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Mai puțin timp."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Activați"</string>
+ <string name="cancel" msgid="6859253417269739139">"Anulați"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Activați Nu deranja"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Niciodată"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Numai cu prioritate"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 693332f..bdf8a4a 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Сети"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Серт. беспроводн. мониторов"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Подробный журнал Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Всегда включать поиск сетей Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Создание случайных MAC-адресов при подключении по Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Не отключать мобильный Интернет"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Аппаратное ускорение в режиме модема"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Показывать Bluetooth-устройства без названий"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введите имя хоста поставщика услуг DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показывать параметры сертификации беспроводных мониторов"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"При выборе Wi‑Fi указывать в журнале RSSI для каждого SSID"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Включать или отключать поиск сетей Wi-Fi во время передачи данных в зависимости от объема трафика"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Генерировать случайные MAC-адреса при подключении к сетям Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Размер буфера журнала"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберите размер буфера журнала"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Очистить постоянный диск журнала?"</string>
@@ -403,4 +403,12 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Зарегистрирован"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Не зарегистрирован"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Недоступно"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">Подключено %1$d устройство</item>
+ <item quantity="few">Подключено %1$d устройства</item>
+ <item quantity="many">Подключено %1$d устройств</item>
+ <item quantity="other">Подключено %1$d устройства</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Увеличить продолжительность"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Уменьшить продолжительность"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index 2808ba3..b056a9c 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"වැඩිකොට දක්වනවා ඇති ප්රදේශ පෙන්වන්න"</item>
<item msgid="2290859360633824369">"අපවිෂවීම සඳහා ප්රදේශ පෙන්වන්න"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (පෙරනිමි)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"සම්මත සීමාව"</item>
<item msgid="4071574792028999443">"පසුබිම් ක්රියාවලි නොමැත"</item>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 6abd14d..38dbe0a 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ජාලකරණය"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"නොරැහැන් සංදර්ශක සහතිකය"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"විස්තරාත්මක Wi‑Fi ලොග් කිරීම සබල කරන්න"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi රෝම් පරිලෝකන වෙතට සැමවිට අවසර දෙන්න"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"සම්බන්ධිත MAC සසම්භාවීකරණය"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ජංගම දත්ත සැමවිට ක්රියාකාරීය"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ටෙදරින් දෘඪාංග ත්වරණය"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"නම් නොමැති බ්ලූටූත් උපාංග පෙන්වන්න"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS සැපයුම්කරුගේ සත්කාරක නම ඇතුළු කරන්න"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"නොරැහැන් සංදර්ශක සහතිකය සඳහා විකල්ප පෙන්වන්න"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ලොග් මට්ටම වැඩි කරන්න, Wi‑Fi තෝරනයෙහි SSID RSSI අනුව පෙන්වන්න"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"අතුරු මුහුණතෙහි ඇති දත්ත තදබදය අනුව Wi‑Fi රෝම් පරිලෝකන වෙත ඉඩ දෙන්න/නොදෙන්න"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi ජාලවලට සම්බන්ධ වීමේදී MAC ලිපිනය සසම්භාවීකරණය"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ලෝගයේ අන්තරාවක ප්රමාණය"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ලොග අන්තරාවකට ලෝගයේ ප්රමාණය තෝරන්න"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ලොගකරු නොනවතින ගබඩාව හිස් කරන්නද?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"දෘඨාංග ස්ථර යාවත්කාලීන"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"යාවත්කාලින වන විට දෘඩාංග තලය කොළ පහන් දැල්වෙන්න"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU වැඩිකොට දැක්වීම නිදොස් කරන්න"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU විදැහුම සකසන්න"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW වසාලන අක්රිය කරන්න"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"තිර සංයුක්ත කිරීමට සැමවිටම GPU භාවිතා කරන්න"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"වර්ණ අවකාශය අනුකරණය කරන්න"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"ලියාපදිංචි වී ඇත"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ලියාපදිංචි වී නැත"</string>
<string name="status_unavailable" msgid="7862009036663793314">"ලබාගත නොහැක"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">උපාංග %1$dක් සම්බන්ධ කරන ලදී</item>
+ <item quantity="other">උපාංග %1$dක් සම්බන්ධ කරන ලදී</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"වේලාව වැඩියෙන්."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"වේලාව අඩුවෙන්."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ක්රියාත්මක කරන්න"</string>
+ <string name="cancel" msgid="6859253417269739139">"අවලංගු කරන්න"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"බාධා නොකරන්න ක්රියාත්මක කරන්න"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"කිසි විටක නැත"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"ප්රමුඛතා පමණි"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 8cc2dac..3d7cf28 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Siete"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikácia bezdrôtového zobrazenia"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Podrobné denníky Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povoliť funkciu Wi‑Fi Roam Scans"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Randomizácia pripojených adries MAC"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilné dáta ponechať vždy aktívne"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardvérovú akcelerácia pre tethering"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Zobrazovať zariadenia Bluetooth bez názvov"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Zadajte názov hostiteľa poskytovateľa DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobraziť možnosti certifikácie bezdrôtového zobrazenia"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšiť úroveň denníkov Wi‑Fi, zobrazovať podľa SSID RSSI pri výbere siete Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Povoliť alebo zakázať funkciu Wifi Roam Scans na základe objemu prenosu údajov v rozhraní"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Randomizovať adresu MAC pri pripájaní k sieťam Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Vyrovnávacia pamäť nástroja denníkov"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Veľkosť vyrovnávacej pamäte nástroja denníkov"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vymazať trvalé úložisko zapisovača do denníka?"</string>
@@ -403,4 +403,12 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrované"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Neregistrované"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Nie je k dispozícii"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="few">%1$d pripojené zariadenia</item>
+ <item quantity="many">%1$d pripojeného zariadenia</item>
+ <item quantity="other">%1$d pripojených zariadení</item>
+ <item quantity="one">%1$d pripojené zariadenie</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Dlhší čas."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Kratší čas."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index a924bdb..2d1cb55 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Pokaži risanje zunaj vidnega območja"</item>
<item msgid="2290859360633824369">"Pokaži območja za devteranomalijo"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (privzeto)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Standardna omejitev"</item>
<item msgid="4071574792028999443">"Ni postopkov v ozadju"</item>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index af8eb6e..fecc548 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Omrežja"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Potrdilo brezžičnega zaslona"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogoči podrob. zapis. dnevnika za Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vedno omogoči iskanje omrežij Wi-Fi za gostovanje"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Dodelitev naključnega naslova MAC ob vzpostavitvi povezave"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Prenos podatkov v mobilnem omrežju je vedno aktiven"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Strojno pospeševanje za internetno povezavo prek mobilnega telefona"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Naprave Bluetooth prikaži brez imen"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Vnesite ime gostitelja pri ponudniku strežnika DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži možnosti za potrdilo brezžičnega zaslona"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povečaj raven zapis. dnev. za Wi-Fi; v izbir. Wi‑Fi-ja pokaži glede na SSID RSSI"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Omogoči/onemogoči iskanje omrežij Wi-Fi za gostovanje glede na količino podatkovnega prometa pri vmesniku"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Dodelitev naključnega naslova MAC pri povezovanju z omrežji Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Velikosti medpomn. zapisov. dnevnika"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izberite velikost medpomnilnika dnevnika"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Želite izbrisati trajno shranjevanje dnevniškega orodja?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Pokaži pos. sl. str. opr."</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Obarvaj sloje strojne opreme zeleno ob posodobitvi"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Prekoračitev območja GPE"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Nastavi upodabljalnik GPE"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Onem. strojni medp."</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Za sestavljanje slike vedno uporabi graf. procesor"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simul. barvnega prostora"</string>
@@ -403,4 +402,18 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrirana"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ni registrirana"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Ni na voljo"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">Povezana je %1$d naprava</item>
+ <item quantity="two">Povezani sta %1$d napravi</item>
+ <item quantity="few">Povezane so %1$d naprave</item>
+ <item quantity="other">Povezanih je %1$d naprav</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Daljši čas."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Krajši čas."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Vklopi"</string>
+ <string name="cancel" msgid="6859253417269739139">"Prekliči"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Vklop načina »ne moti«"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikoli"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Samo prednostno"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index 244a534..5bd5b1d 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Shfaq zonat e konfliktit"</item>
<item msgid="2290859360633824369">"Shfaq zonat për deuteranomalinë"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (e parazgjedhur)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Kufizim standard"</item>
<item msgid="4071574792028999443">"Nuk ka procese në sfond"</item>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 88b1057..0999b75 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Rrjetet"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikimi i ekranit valor"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivizo hyrjen Wi-Fi Verbose"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Lejo gjithmonë skanimet për Wi-Fi edhe kur je në lëvizje"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Zgjedhja e rastësishme e MAC të lidhur"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Të dhënat celulare gjithmonë aktive"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Përshpejtimi i harduerit për ndarjen"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Shfaq pajisjet me Bluetooth pa emra"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Fut emrin e pritësit të ofruesit të DNS-së"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Shfaq opsionet për certifikimin e ekranit valor"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Rrit nivelin regjistrues të Wi‑Fi duke shfaqur SSID RSSI-në te Zgjedhësi i Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Lejo/Ndalo skanimet për Wi‑Fi në roaming, bazuar në sasinë e trafikut të të dhënave të pranishme në ndërfaqe"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Zgjidh rastësisht adresën MAC kur lidhesh me rrjete Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Madhësitë e regjistruesit"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Përzgjidh madhësitë e regjistruesit"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Do të pastrosh hapësirën ruajtëse të vazhdueshme të regjistruesit?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Shfaq përditësimet e shtresave të harduerit"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Ndriço në të gjelbër shtresat e harduerit që përditësohen"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Korrigjo konfliktet e GPU-së"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Cakto interpret. e GPU-së"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Çaktivizo mbishtresimin e HW-së"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Përdor gjithmonë GPU-në për përbërjen e ekranit"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simulo hapësirën e ngjyrës"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Regjistruar"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Paregjistruar"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Nuk ofrohet"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d pajisje të lidhura</item>
+ <item quantity="one">%1$d pajisje e lidhur</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Më shumë kohë."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Më pak kohë."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Aktivizo"</string>
+ <string name="cancel" msgid="6859253417269739139">"Anulo"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Aktivizo \"Mos shqetëso\""</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Asnjëherë"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Vetëm me prioritet"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 362fc1f..226315b 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Умрежавање"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Сертификација бежичног екрана"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Омогући детаљнију евиденцију за Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Увек дозволи скенирање Wi‑Fi-ја у ромингу"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Насумичан избор MAC адресе током повезивања"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилни подаци су увек активни"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско убрзање привезивања"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Прикажи Bluetooth уређаје без назива"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Унесите име хоста добављача услуге DNS-а"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Приказ опција за сертификацију бежичног екрана"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Повећава ниво евидентирања за Wi‑Fi. Приказ по SSID RSSI-у у бирачу Wi‑Fi мреже"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволи/забрани скенирање Wi-Fi-ја у ромингу на основу присутног протока података на интерфејсу"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Изабери насумичну MAC адресу током повезивања на Wi‑Fi мреже"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Величине бафера података у програму за евидентирање"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Изаберите величине по баферу евиденције"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Желите ли да обришете стални меморијски простор програма за евидентирање?"</string>
@@ -403,4 +403,11 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Регистрован je"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Није регистрован"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Недоступно"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">Повезан је %1$d уређај</item>
+ <item quantity="few">Повезана су %1$d уређаја</item>
+ <item quantity="other">Повезано је %1$d уређаја</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Више времена."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Мање времена."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 230dfee..874294f 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Nätverk"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifiering för Wi-Fi-skärmdelning"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivera utförlig loggning för Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillåt alltid sökning efter Wi-Fi-roaming"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Ansluten MAC-slumpgenerering"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata alltid aktiverad"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvaruacceleration för internetdelning"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Visa namnlösa Bluetooth-enheter"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ange värdnamn för DNS-leverantör"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Visa certifieringsalternativ för Wi-Fi-skärmdelning"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Öka loggningsnivån för Wi-Fi, visa per SSID RSSI i Wi‑Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillåt/tillåt inte sökning efter Wi-Fi-roaming utifrån mängden datatrafik i gränssnittet"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Generera en slumpmässig MAC-adress när du ansluter till Wi‑Fi-nätverk"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Buffertstorlekar för logg"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Välj loggstorlekar per loggbuffert"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vill du rensa lagringsutrymmet för loggar?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrerad"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Ej registrerad"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Inte tillgängligt"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d enheter är anslutna</item>
+ <item quantity="one">%1$d enhet är ansluten</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Längre tid."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Kortare tid."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index b694687..c320aeb 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Onyesha maeneo yaliyoondolewa"</item>
<item msgid="2290859360633824369">"Onyesha sehemu za Upofu Rangi Kijani"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (Chaguo-msingi)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Kiwango cha wastani"</item>
<item msgid="4071574792028999443">"Hakuna mchakato wa mandari nyuma"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 1d46260..72850d4 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Mtandao"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Chaguo za cheti cha kuonyesha pasiwaya"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Washa Uwekaji kumbukumbu za WiFi kutumia Sauti"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Ruhusu Uchanganuzi wa Matumizi ya Mitandao mingine"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Anwani za MAC Zinazowekwa kwa Nasibu"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Iendelee kutumia data ya simu"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Kuongeza kasi kwa kutumia maunzi ili kusambaza mtandao"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Onyesha vifaa vya Bluetooth visivyo na majina"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Weka jina la mpangishi wa huduma za DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Onyesha chaguo za cheti cha kuonyesha pasiwaya"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Ongeza hatua ya uwekaji kumbukumbu ya Wi-Fi, onyesha kwa kila SSID RSSI kwenye Kichukuzi cha Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Ruhusu au Zuia Uchanganuzi wa Matumizi ya Mitandao mingine ya Wifi kulingana na kiasi cha trafiki ya data kilicho kwenye kiolesura"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Weka anwani ya MAC kwa nasibu wakati unaunganisha kwenye mitandao ya Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Ukubwa wa kiweka bafa ya kumbukumbu"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Chagua ukubwa wa kila Kumbukumbu"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Ungependa kufuta data iliyo kwenye hifadhi ya kiweka kumbukumbu za mara kwa mara?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Onyesha sasisho za safu za maunzi"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Angaza kijani safu za maunzi zinaposasisha"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Tatua uondoaji wa GPU"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"Weka Kiwasilishaji cha GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Lemaza miekeleo ya HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Daima tumia GPU kwa mchanganyiko wa skrini"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Kuiga nafasi ya rangi"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Imesajiliwa"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Haijasajiliwa"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Hapatikani"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">Imeunganisha vifaa %1$d</item>
+ <item quantity="one">Imeunganisha kifaa %1$d</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Muda zaidi."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Muda kidogo."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Washa"</string>
+ <string name="cancel" msgid="6859253417269739139">"Ghairi"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Washa kipengele cha Usinisumbue"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Kamwe"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Kipaumbele tu"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 2d75c01..aa24fde 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"ஓவர்டிரா பகுதிகளைக் காட்டு"</item>
<item msgid="2290859360633824369">"நிறக்குருடின் பகுதிகளைக் காட்டு"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (இயல்பு)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"நிலையான வரம்பு"</item>
<item msgid="4071574792028999443">"பின்புலச் செயல்முறைகள் இல்லை"</item>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index e9fd79b..64bc434 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"நெட்வொர்க்கிங்"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"வயர்லெஸ் காட்சிக்கான சான்றிதழ்"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"வைஃபை அதிவிவர நுழைவை இயக்கு"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"எப்போதும் வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"இணைக்கப்பட்ட MAC Randomization"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"மொபைல் டேட்டாவை எப்போதும் இயக்கத்திலேயே வை"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"பெயர்கள் இல்லாத புளூடூத் சாதனங்களைக் காட்டு"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS வழங்குநரின் ஹோஸ்ட் பெயரை உள்ளிடவும்"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"வயர்லெஸ் காட்சி சான்றுக்கான விருப்பங்களைக் காட்டு"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wifi நுழைவு அளவை அதிகரித்து, வைஃபை தேர்வியில் ஒவ்வொன்றிற்கும் SSID RSSI ஐ காட்டுக"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"இடைமுகத்தில் உள்ள ட்ராஃபிக் தரவின் அளவைப் பொறுத்து வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி/அனுமதிக்காதே"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi நெட்வொர்க்குகளில் இணைக்கும்போது Randomize MAC இன் முகவரி"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"லாகர் பஃபர் அளவுகள்"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"லாக் பஃபர் ஒன்றிற்கு லாகர் அளவுகளைத் தேர்வுசெய்க"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"லாகரின் நிலையான சேமிப்பகத்தை அழிக்கவா?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"வன்பொருள் லேயர்களின் புதுப்பிப்புகளைக் காட்டு"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"வன்பொருள் லேயர்களைப் புதுப்பிக்கும்போது, அவற்றைப் பச்சை நிறத்தில் காட்டு"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ஓவர்டிராவைப் பிழைதிருத்து"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU ரெண்டரரை அமை"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW மேலடுக்குகளை முடக்கு"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"திரைத் தொகுத்தலுக்கு எப்போதும் GPU ஐப் பயன்படுத்து"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"வண்ணத்தின் இடைவெளியை உருவகப்படுத்து"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"பதிவு செய்யப்பட்டது"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"பதிவு செய்யப்படவில்லை"</string>
<string name="status_unavailable" msgid="7862009036663793314">"கிடைக்கவில்லை"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d சாதனங்கள் இணைக்கப்பட்டன</item>
+ <item quantity="one">%1$d சாதனம் இணைக்கப்பட்டது</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"நேரத்தை அதிகரிக்கும்."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"நேரத்தைக் குறைக்கும்."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ஆன் செய்"</string>
+ <string name="cancel" msgid="6859253417269739139">"ரத்துசெய்"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"தொந்தரவு செய்ய வேண்டாம் என்பதை ஆன் செய்யும்"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"ஒருபோதும் வேண்டாம்"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"முக்கியமானவை மட்டும்"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 39d84dd..ce99f63 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"ఓవర్డ్రా ప్రాంతాలను చూపండి"</item>
<item msgid="2290859360633824369">"డ్యూటెరానోమలీ కోసం ప్రాంతాలను చూపండి"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (డిఫాల్ట్)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"ప్రామాణిక పరిమితి"</item>
<item msgid="4071574792028999443">"నేపథ్య ప్రాసెస్లు లేవు"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index c2b738a..2e00dfb 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"నెట్వర్కింగ్"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"వైర్లెస్ ప్రదర్శన ప్రమాణీకరణ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi విశదీకృత లాగింగ్ను ప్రారంభించండి"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi సంచార స్కాన్లను ఎల్లప్పుడూ అనుమతించు"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"MAC యాదృచ్ఛికతకు కనెక్ట్ చేయబడింది"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"మొబైల్ డేటాని ఎల్లప్పుడూ సక్రియంగా ఉంచు"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"టెథెరింగ్ హార్డ్వేర్ వేగవృద్ధి"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"పేర్లు లేని బ్లూటూత్ పరికరాలు చూపించు"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ప్రదాత యొక్క హోస్ట్పేరును నమోదు చేయండి"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"వైర్లెస్ ప్రదర్శన సర్టిఫికెట్ కోసం ఎంపికలను చూపు"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ఎంపికలో SSID RSSI ప్రకారం చూపబడే Wi‑Fi లాగింగ్ స్థాయిని పెంచండి"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ఇంటర్ఫేస్లో ఉండే డేటా ట్రాఫిక్ పరిమాణం ఆధారంగా Wi‑Fi సంచార స్కాన్లను అనుమతించు/నిరాకరించు"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi నెట్వర్క్కు కనెక్ట్ చేస్తున్నప్పుడు MAC చిరునామాను యాదృచ్ఛికం చేయండి"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"లాగర్ బఫర్ పరిమాణాలు"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"లాగ్ బఫర్కి లాగర్ పరిమా. ఎంచుకోండి"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"లాగర్ నిరంతర నిల్వలోని డేటాను తీసివేయాలా?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"హార్డ్వేర్ లేయర్ల అప్డేట్లను చూపండి"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"హార్డ్వేర్ లేయర్లు నవీకరించబడినప్పుడు వాటిని ఆకుపచ్చ రంగులో ఫ్లాష్ చేయండి"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ఓవర్డ్రాను డీబగ్ చేయండి"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Rendererని సెట్ చేయండి"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW అతివ్యాప్తులను నిలిపివేయి"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"స్క్రీన్ కంపోజిషనింగ్ కోసం ఎల్లప్పుడూ GPUని ఉపయోగించు"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"రంగు అంతరాన్ని అనుకరించు"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"నమోదు చేయబడింది"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"నమోదు కాలేదు"</string>
<string name="status_unavailable" msgid="7862009036663793314">"అందుబాటులో లేదు"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d పరికరాలు కనెక్ట్ చేయబడ్డాయి</item>
+ <item quantity="one">%1$d పరికరం కనెక్ట్ చేయబడింది</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"ఎక్కువ సమయం."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"తక్కువ సమయం."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ఆన్ చేయండి"</string>
+ <string name="cancel" msgid="6859253417269739139">"రద్దు చేయి"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"అంతరాయం కలిగించవద్దును ఆన్ చేయండి"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"ఎప్పటికీ"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"ప్రాధాన్యత మాత్రమే"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 57b12a5..9f7bc73 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"เครือข่าย"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"การรับรองการแสดงผลแบบไร้สาย"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"เปิดใช้การบันทึกรายละเอียด Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ใช้การสแกน Wi-Fi ข้ามเครือข่ายเสมอ"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"การสุ่ม MAC ที่เชื่อมต่อ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"เปิดใช้อินเทอร์เน็ตมือถือเสมอ"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"การเร่งฮาร์ดแวร์การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"แสดงอุปกรณ์บลูทูธที่ไม่มีชื่อ"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ป้อนชื่อโฮสต์ของผู้ให้บริการ DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"แสดงตัวเลือกสำหรับการรับรองการแสดงผล แบบไร้สาย"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"เพิ่มระดับการบันทึก Wi‑Fi แสดงต่อ SSID RSSI ในตัวเลือก Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"อนุญาต/ไม่อนุญาตการสแกน Wi-Fi ข้ามเครือข่าย ตามปริมาณข้อมูลการเข้าชมที่ปรากฏในอินเทอร์เฟซ"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"สุ่มที่อยู่ MAC เมื่อเชื่อมต่อกับเครือข่าย Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ขนาดบัฟเฟอร์ของ Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"เลือกขนาด Logger ต่อบัฟเฟอร์ไฟล์บันทึก"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ล้างพื้นที่เก็บข้อมูลถาวรของตัวบันทึกไหม"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"ลงทะเบียนแล้ว"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"ไม่ได้ลงทะเบียน"</string>
<string name="status_unavailable" msgid="7862009036663793314">"ไม่ว่าง"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">มีอุปกรณ์ที่เชื่อมต่อ %1$d เครื่อง</item>
+ <item quantity="one">มีอุปกรณ์ที่เชื่อมต่อ %1$d เครื่อง</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"เวลามากขึ้น"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"เวลาน้อยลง"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 72261af..1b5eb2f 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certification ng wireless display"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"I-enable ang Pagla-log sa Wi‑Fi Verbose"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Palaging payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Nakakonektang MAC Randomization"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Palaging aktibo ang mobile data"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardware acceleration para sa pag-tether"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Ipakita ang mga Bluetooth device na walang pangalan"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ilagay ang hostname ng DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ipakita ang mga opsyon para sa certification ng wireless display"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Pataasin ang antas ng Wi‑Fi logging, ipakita sa bawat SSID RSSI sa Wi‑Fi Picker"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Payagan/Huwag payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi batay sa dami ng trapiko ng data na mayroon sa interface"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"I-randomize ang MAC address kapag kumokonekta sa mga Wi‑Fi network"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Mga laki ng buffer ng Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pumili ng mga laki ng Logger bawat log buffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"I-clear ang tuluy-tuloy na storage ng logger?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Nakarehistro"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Hindi nakarehistro"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Hindi available"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d device ang nakakonekta</item>
+ <item quantity="other">%1$d na device ang nakakonekta</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Dagdagan ang oras."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Bawasan ang oras."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 948e4e5..b570e88 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Ağ işlemleri"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Kablosuz ekran sertifikası"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Kablosuz Ayrıntılı Günlük Kaydını etkinleştir"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Kablosuz Dolaşım Taramalarına daima izin ver"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Bağlı MAC Rastgele Seçimi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil veri her zaman etkin"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering donanım hızlandırıcısı"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Adsız Bluetooth cihazlarını göster"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS sağlayıcının ana makine adını gir"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Kablosuz ekran sertifikası seçeneklerini göster"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Kablosuz günlük kaydı seviyesini artır. Kablosuz Seçici\'de her bir SSID RSSI için göster."</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Arayüzde mevcut veri trafiği miktarına bağlı olarak Kablosuz Dolaşım Taramalarına İzin Verin/Vermeyin"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Kablosuz ağlara bağlanırken MAC adresini rastgele seç"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Günlük Kaydedici arabellek boyutları"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Gün. arabel. başına Gün. Kayd. boyutunu seç"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Günlük kaydedici kalıcı depolama alanı silinsin mi?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Kaydettirildi"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Kaydettirilmedi"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Kullanılamıyor"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d cihaz bağlı</item>
+ <item quantity="one">%1$d cihaz bağlı</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Daha uzun süre."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Daha kısa süre."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 664fda7..e9f6c06 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Мережі"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Сертифікація бездрот. екрана"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Докладний запис у журнал Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Завжди шукати мережі Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Довільний вибір MAC-адрес під час з’єднання"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Не вимикати мобільне передавання даних"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратне прискорення під час використання телефона в режимі модема"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Показувати пристрої Bluetooth без назв"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введіть ім’я хосту постачальника послуг DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показати параметри сертифікації бездротового екрана"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Показувати в журналі RSSI для кожного SSID під час вибору Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволити чи заборонити Wi-Fi шукати роумінг на основі обсягу трафіку даних в інтерфейсі"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Довільно вибирати MAC-адресу під час з’єднання з мережами Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Розміри буфера журналу"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Виберіть розміри буфера журналу"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Очистити постійну пам’ять журналу?"</string>
@@ -403,4 +403,12 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Зареєстровано"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Не зареєстровано"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Недоступно"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">Під’єднано %1$d пристрій</item>
+ <item quantity="few">Під’єднано %1$d пристрої</item>
+ <item quantity="many">Під’єднано %1$d пристроїв</item>
+ <item quantity="other">Під’єднано %1$d пристрою</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Більше часу."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Менше часу."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 8d46582..5efc872 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"اوور ڈرا والے حصے دکھائیں"</item>
<item msgid="2290859360633824369">"Deuteranomaly کیلئے حصے دکھائیں"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (ڈیفالٹ)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"معیاری حد"</item>
<item msgid="4071574792028999443">"کوئی پس منظر والے پروسیسز نہیں ہیں"</item>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 226b862..41ec303 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"نیٹ ورکنگ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"وائرلیس ڈسپلے سرٹیفیکیشن"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi وربوس لاگنگ فعال کریں"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ہمیشہ Wi‑Fi روم اسکینز کی اجازت دیں"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"منسلک کردہ MAC رینڈمائزیشن"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"موبائل ڈیٹا ہمیشہ فعال رکھیں"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ٹیدرنگ ہارڈویئر سرعت کاری"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"بغیر نام والے بلوٹوتھ آلات دکھائیں"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS فراہم کنندہ کے میزبان کا نام درج کریں"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"وائرلیس ڈسپلے سرٹیفیکیشن کیلئے اختیارات دکھائیں"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi لاگنگ لیول میں اضافہ کریں، Wi‑Fi منتخب کنندہ میں فی SSID RSSI دکھائیں"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"انٹرفیس پر موجود ڈیٹا ٹریفک کی مقدار کی بنیاد پر Wi‑Fi روم اسکینز کی اجازت دیں/اجازت نہ دیں"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi نیٹ ورکس سے منسلک کرتے وقت MAC پتے کو غیر مرتب کریں"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"لاگر بفر کے سائز"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"فی لاگ بفر لاگر کے سائز منتخب کریں"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"لاگر مستقل اسٹوریج صاف کریں؟"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"ہارڈویئر پرتوں کی اپ ڈیٹس دکھائیں"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ہارڈویئر پرتیں اپ ڈیٹ ہونے پر سبز رنگ میں جھلملائیں"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU اوور ڈرا کو ڈیبگ کریں"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU رینڈرر سیٹ کریں"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HW اوور لیز غیر فعال کریں"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"سکرین کی ساخت بنانے کیلئے ہمیشہ GPU استعمال کریں"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"رنگ کی جگہ کو تحریک دیں"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"رجسٹر شدہ"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"رجسٹر نہیں ہے"</string>
<string name="status_unavailable" msgid="7862009036663793314">"غیر دستیاب"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d آلات منسلک ہیں</item>
+ <item quantity="one">%1$d آلہ منسلک ہے</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"زیادہ وقت۔"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"کم وقت۔"</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"آن کریں"</string>
+ <string name="cancel" msgid="6859253417269739139">"منسوخ کریں"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"\'ڈسٹرب نہ کریں\' کو آن کریں"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"کبھی نہیں"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"صرف ترجیحی"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 16d325fe..813c44f 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"Ortiqcha chizilgan joylarni ko‘rsatish"</item>
<item msgid="2290859360633824369">"Muayyan rangdagi hududlarni ajratib belgilash"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL (standart)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"Standard cheklov"</item>
<item msgid="4071574792028999443">"Fondagi jarayonlarsiz"</item>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index fdb3ef4..0a65c13 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Tarmoqlar"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Simsiz monitor sertifikatlari"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Batafsil Wi-Fi jurnali"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi tarmoqlarini qidirishga doim ruxsat"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Ulangan MAC randomizatsiyasi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil internet doim yoniq tursin"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Modem rejimida apparatli tezlashtirish"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bluetooth qurilmalarini nomlarisiz ko‘rsatish"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderining host nomini kiriting"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz monitorlarni sertifikatlash parametrini ko‘rsatish"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi ulanishini tanlashda har bir SSID uchun jurnalda ko‘rsatilsin"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Ma’lumotlarni uzatish vaqtida trafik hajmiga qarab Wi-Fi tarmoqlarni qidirish funksiyasini yoqish yoki o‘chirish"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi tarmoqlarga ulanishda MAC manzilini tasodifiy tanlash"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Jurnal buferi hajmi"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Jurnal xotirasi hajmini tanlang"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Jurnalning doimiy xotirasi tozalansinmi?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Apparatli yangilanishlarni ko‘rsatish"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Yangilanganda apparatli darajalarni yashil bilan belgilash"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ortiqcha chiziqlarini o‘chirish"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU renderlash vositasi"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Apparatli qatlamlarni o‘ch. qo‘yish"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Ekranda tasvirlarni biriktirish uchun doim GPU ishlatilsin"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Rang maydonini simulyatsiyalash"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registratsiya qilingan"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Registratsiya qilinmagan"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Mavjud emas"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d ta qurilma ulangan</item>
+ <item quantity="one">%1$d ta qurilma ulangan</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Ko‘proq vaqt."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Kamroq vaqt."</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Yoqish"</string>
+ <string name="cancel" msgid="6859253417269739139">"Bekor qilish"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Bezovta qilinmasin rejimini yoqing"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Hech qachon"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Faqat muhimlari"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index a7a5855..5d8f543 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Mạng"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Chứng nhận hiển thị không dây"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Bật ghi nhật ký chi tiết Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luôn cho phép quét chuyển vùng Wi‑Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Lựa chọn ngẫu nhiên địa chỉ MAC khi kết nối"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dữ liệu di động luôn hiện hoạt"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tăng tốc phần cứng cho chia sẻ kết nối"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Hiển thị các thiết bị Bluetooth không có tên"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Nhập tên máy chủ của nhà cung cấp DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Hiển thị tùy chọn chứng nhận hiển thị không dây"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tăng mức ghi nhật ký Wi‑Fi, hiển thị mỗi SSID RSSI trong bộ chọn Wi‑Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Cho phép/Không cho phép quét chuyển vùng Wi‑Fi dựa trên lưu lượng truy cập dữ liệu có tại giao diện"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Lựa chọn ngẫu nhiên địa chỉ MAC khi kết nối với mạng Wi‑Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Kích cỡ tải trình ghi"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Chọn kích thước Trình ghi/lần tải nhật ký"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Xóa bộ nhớ ổn định trong trình ghi nhật ký?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Đã đăng ký"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Chưa được đăng ký"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Không có"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d thiết bị được kết nối</item>
+ <item quantity="one">%1$d thiết bị được kết nối</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Nhiều thời gian hơn."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Ít thời gian hơn."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index dc24afd..7b451ae 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -234,10 +234,6 @@
<item msgid="7688197031296835369">"显示过度绘制区域"</item>
<item msgid="2290859360633824369">"显示适合绿色弱视患者查看的区域"</item>
</string-array>
- <string-array name="debug_hw_renderer_entries">
- <item msgid="2578620445459945681">"OpenGL(默认)"</item>
- <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
- </string-array>
<string-array name="app_process_limit_entries">
<item msgid="3401625457385943795">"标准限制"</item>
<item msgid="4071574792028999443">"不允许后台进程"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 5a1d067..7bd7e7d 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"网络"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"无线显示认证"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"启用WLAN详细日志记录功能"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允许WLAN漫游扫描"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"连接时随机选择 MAC 网址"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"始终开启移动数据网络"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"网络共享硬件加速"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"显示没有名称的蓝牙设备"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"输入 DNS 提供商的主机名"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"显示无线显示认证选项"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"提升WLAN日志记录级别(在WLAN选择器中显示每个SSID的RSSI)"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根据接口中目前的数据流量允许/禁止WLAN漫游扫描"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"连接到 WLAN 网络时随机选择 MAC 地址"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"日志记录器缓冲区大小"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"选择每个日志缓冲区的日志记录器大小"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"要清除永久存储的日志记录器数据吗?"</string>
@@ -275,7 +275,6 @@
<string name="show_hw_layers_updates" msgid="5645728765605699821">"显示硬件层更新"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash 硬件层在进行更新时会显示为绿色"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"调试 GPU 过度绘制"</string>
- <string name="debug_hw_renderer" msgid="7568529019431785816">"设置 GPU 渲染程序"</string>
<string name="disable_overlays" msgid="2074488440505934665">"停用 HW 叠加层"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"始终使用 GPU 进行屏幕合成"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"模拟颜色空间"</string>
@@ -403,4 +402,16 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"已注册"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"未注册"</string>
<string name="status_unavailable" msgid="7862009036663793314">"无法获取"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">已连接 %1$d 个设备</item>
+ <item quantity="one">已连接 %1$d 个设备</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"增加时间。"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"减少时间。"</string>
+ <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"开启"</string>
+ <string name="cancel" msgid="6859253417269739139">"取消"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"开启“勿扰”模式"</string>
+ <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"永不"</string>
+ <string name="zen_interruption_level_priority" msgid="2078370238113347720">"仅限优先事项"</string>
+ <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>。<xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index acc3bb8..695990d 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"網絡"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"無線螢幕分享認證"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"啟用 Wi‑Fi 詳細記錄"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"永遠允許 Wi-Fi 漫遊掃描"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"已連線的 MAC 隨機化處理"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"一律保持啟用流動數據"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"網絡共享硬件加速"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"顯示沒有名稱的藍牙裝置"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"輸入網域名稱系統 (DNS) 供應商的主機名稱"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根據介面中目前的數據流量允許/禁止 WiFi 漫遊掃描"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"連線至 Wi‑Fi 網絡時隨機產生 MAC 位址"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"記錄器緩衝區空間"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"選取每個記錄緩衝區的記錄器空間"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"要清除記錄器的持久儲存空間嗎?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"已註冊"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"未註冊"</string>
<string name="status_unavailable" msgid="7862009036663793314">"無法使用"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d 部已連線的裝置</item>
+ <item quantity="one">%1$d 部已連線的裝置</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"增加時間。"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"減少時間。"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 775b928..6b7d7e8 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"網路連線"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"無線螢幕分享認證"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"啟用 Wi‑Fi 詳細紀錄設定"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允許 Wi-Fi 漫遊掃描"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"已連線的 MAC 隨機化處理"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"行動數據連線一律保持啟用狀態"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"數據連線硬體加速"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"顯示沒有名稱的藍牙裝置"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"輸入 DNS 供應商的主機名稱"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根據介面中目前的數據流量允許/禁止 Wi-Fi 漫遊掃描"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"連線至 Wi‑Fi 網路時隨機化 MAC 位址"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"紀錄器緩衝區空間"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"選取每個紀錄緩衝區的紀錄器空間"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"要清除永久儲存的記錄器資料嗎?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"已註冊"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"未註冊"</string>
<string name="status_unavailable" msgid="7862009036663793314">"無法取得"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="other">%1$d 個已連線的裝置</item>
+ <item quantity="one">%1$d 個已連線的裝置</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"增加時間。"</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"減少時間。"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 13b1603..c5d6627 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -196,7 +196,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Ukunethiwekha"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Ukunikezwa isitifiketi sokubukeka okungenantambo"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Nika amandlaukungena kwe-Wi-Fi Verbose"</string>
- <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vumela njalo ukuskena kokuzula kwe-Wi-Fi"</string>
+ <string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Okungahleliwe kwe-MAC exhunyiwe"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Idatha yeselula ihlala isebenza"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"I-Tethering hardware acceleration"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Bonisa amadivayisi e-Bluetooth ngaphandle kwamagama"</string>
@@ -222,7 +222,7 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Faka igama lomsingathi womhlinzeki we-DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Bonisa izinketho zokunikeza isitifiketi ukubukeka okungenantambo"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"khuphula izinga lokungena le-Wi-Fi, bonisa nge-SSID RSSI engayodwana kusikhethi se-Wi-Fi"</string>
- <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Vumela/Ungavumeli ukuskena kokuzula kwe-Wi-Fi okususelwa kunani ledatha yethrafikhi ekhona ekusebenzisaneni"</string>
+ <string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Ungahleli ikheli le-MAC uma kuxhumeke kumanethiwekhi e-Wi-Fi"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Amasayizi weloga ngebhafa"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Khetha amasayizi weloga ngebhafa ngayinye yelogu"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Sula isitoreji seloga eqhubekayo?"</string>
@@ -403,4 +403,10 @@
<string name="ims_reg_status_registered" msgid="933003316932739188">"Kubhalisiwe"</string>
<string name="ims_reg_status_not_registered" msgid="6529783773485229486">"Akubhalisiwe"</string>
<string name="status_unavailable" msgid="7862009036663793314">"Ayitholakali"</string>
+ <plurals name="wifi_tether_connected_summary" formatted="false" msgid="3871603864314407780">
+ <item quantity="one">%1$d amadivayisi axhunyiwe</item>
+ <item quantity="other">%1$d amadivayisi axhunyiwe</item>
+ </plurals>
+ <string name="accessibility_manual_zen_more_time" msgid="1636187409258564291">"Isikhathi esiningi."</string>
+ <string name="accessibility_manual_zen_less_time" msgid="6590887204171164991">"Isikhathi esincane."</string>
</resources>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 77df02b..c926e1f 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -468,18 +468,6 @@
<item>show_deuteranomaly</item>
</string-array>
- <!-- Titles for debug renderer preference. [CHAR LIMIT=50] -->
- <string-array name="debug_hw_renderer_entries">
- <item>OpenGL (Default)</item>
- <item>OpenGL (Skia)</item>
- </string-array>
-
- <!-- Values for debug renderer preference. -->
- <string-array name="debug_hw_renderer_values" translatable="false" >
- <item>opengl</item>
- <item>skiagl</item>
- </string-array>
-
<!-- Titles for app process limit preference. [CHAR LIMIT=35] -->
<string-array name="app_process_limit_entries">
<item>Standard limit</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 4156653..486a9bb 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -679,9 +679,6 @@
<!-- UI debug setting: show the amount of overdraw in apps using the GPU [CHAR LIMIT=25] -->
<string name="debug_hw_overdraw">Debug GPU overdraw</string>
- <!-- UI debug setting: select the renderer to use by RenderThread [CHAR LIMIT=25] -->
- <string name="debug_hw_renderer">Set GPU Renderer</string>
-
<!-- UI debug setting: disable use of overlays? [CHAR LIMIT=25] -->
<string name="disable_overlays">Disable HW overlays</string>
<!-- UI debug setting: disable use of overlays summary [CHAR LIMIT=50] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index fce5dd9..7728f66 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -363,6 +363,26 @@
}
/**
+ * Check if {@param packageName} is restricted by the profile or device owner from using
+ * metered data.
+ *
+ * @return EnforcedAdmin object containing the enforced admin component and admin user details,
+ * or {@code null} if the {@param packageName} is not restricted.
+ */
+ public static EnforcedAdmin checkIfMeteredDataRestricted(Context context,
+ String packageName, int userId) {
+ final EnforcedAdmin enforcedAdmin = getProfileOrDeviceOwner(context, userId);
+ if (enforcedAdmin == null) {
+ return null;
+ }
+
+ final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ return dpm.isMeteredDataDisabledForUser(enforcedAdmin.component, packageName, userId)
+ ? enforcedAdmin : null;
+ }
+
+ /**
* Checks if {@link android.app.admin.DevicePolicyManager#setAutoTimeRequired} is enforced
* on the device.
*
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 5c73d54..3a0ae9f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -48,6 +48,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
import android.text.format.Formatter;
import android.util.IconDrawableFactory;
import android.util.Log;
@@ -1282,7 +1283,8 @@
// A location where extra info can be placed to be used by custom filters.
public Object extraInfo;
- AppEntry(Context context, ApplicationInfo info, long id) {
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ public AppEntry(Context context, ApplicationInfo info, long id) {
apkFile = new File(info.sourceDir);
this.id = id;
this.info = info;
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java
new file mode 100644
index 0000000..f740f7c
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.service.settings.suggestions.ISuggestionService;
+import android.service.settings.suggestions.Suggestion;
+import android.support.annotation.Nullable;
+import android.support.annotation.WorkerThread;
+import android.util.Log;
+
+import java.util.List;
+
+/**
+ * A controller class to access suggestion data.
+ */
+public class SuggestionController {
+
+ /**
+ * Callback interface when service is connected/disconnected.
+ */
+ public interface ServiceConnectionListener {
+ /**
+ * Called when service is connected.
+ */
+ void onServiceConnected();
+
+ /**
+ * Called when service is disconnected.
+ */
+ void onServiceDisconnected();
+ }
+
+ private static final String TAG = "SuggestionController";
+ private static final boolean DEBUG = false;
+
+ private final Context mContext;
+ private final Intent mServiceIntent;
+
+ private ServiceConnection mServiceConnection;
+ private ISuggestionService mRemoteService;
+ private ServiceConnectionListener mConnectionListener;
+
+ /**
+ * Create a new controller instance.
+ *
+ * @param context caller context
+ * @param service The component name for service.
+ * @param listener listener to receive service connected/disconnected event.
+ */
+ public SuggestionController(Context context, ComponentName service,
+ ServiceConnectionListener listener) {
+ mContext = context.getApplicationContext();
+ mConnectionListener = listener;
+ mServiceIntent = new Intent().setComponent(service);
+ mServiceConnection = createServiceConnection();
+ }
+
+ /**
+ * Start the controller.
+ */
+ public void start() {
+ mContext.bindServiceAsUser(mServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE,
+ android.os.Process.myUserHandle());
+ }
+
+ /**
+ * Stop the controller.
+ */
+ public void stop() {
+ if (mRemoteService != null) {
+ mRemoteService = null;
+ mContext.unbindService(mServiceConnection);
+ }
+ }
+
+ /**
+ * Get setting suggestions.
+ */
+ @Nullable
+ @WorkerThread
+ public List<Suggestion> getSuggestions() {
+ if (!isReady()) {
+ return null;
+ }
+ try {
+ return mRemoteService.getSuggestions();
+ } catch (NullPointerException e) {
+ Log.w(TAG, "mRemote service detached before able to query", e);
+ return null;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error when calling getSuggestion()", e);
+ return null;
+ }
+ }
+
+ public void dismissSuggestions(Suggestion suggestion) {
+ if (!isReady()) {
+ Log.w(TAG, "SuggestionController not ready, cannot dismiss " + suggestion.getId());
+ return;
+ }
+ try {
+ mRemoteService.dismissSuggestion(suggestion);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error when calling dismissSuggestion()", e);
+ }
+ }
+
+ public void launchSuggestion(Suggestion suggestion) {
+ if (!isReady()) {
+ Log.w(TAG, "SuggestionController not ready, cannot launch " + suggestion.getId());
+ return;
+ }
+
+ try {
+ mRemoteService.launchSuggestion(suggestion);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error when calling launchSuggestion()", e);
+ }
+ }
+
+ /**
+ * Whether or not the manager is ready
+ */
+ private boolean isReady() {
+ return mRemoteService != null;
+ }
+
+ /**
+ * Create a new {@link ServiceConnection} object to handle service connect/disconnect event.
+ */
+ private ServiceConnection createServiceConnection() {
+ return new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) {
+ Log.d(TAG, "Service is connected");
+ }
+ mRemoteService = ISuggestionService.Stub.asInterface(service);
+ if (mConnectionListener != null) {
+ mConnectionListener.onServiceConnected();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (mConnectionListener != null) {
+ mRemoteService = null;
+ mConnectionListener.onServiceDisconnected();
+ }
+ }
+ };
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java
new file mode 100644
index 0000000..46fc32f
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import android.app.LoaderManager;
+import android.arch.lifecycle.OnLifecycleEvent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Loader;
+import android.os.Bundle;
+import android.service.settings.suggestions.Suggestion;
+import android.support.annotation.Nullable;
+import android.util.Log;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.List;
+
+/**
+ * Manages IPC communication to SettingsIntelligence for suggestion related services.
+ */
+public class SuggestionControllerMixin implements SuggestionController.ServiceConnectionListener,
+ android.arch.lifecycle.LifecycleObserver, LoaderManager.LoaderCallbacks<List<Suggestion>> {
+
+ public interface SuggestionControllerHost {
+ /**
+ * Called when suggestion data fetching is ready.
+ */
+ void onSuggestionReady(List<Suggestion> data);
+
+ /**
+ * Returns {@link LoaderManager} associated with the host. If host is not attached to
+ * activity then return null.
+ */
+ @Nullable
+ LoaderManager getLoaderManager();
+ }
+
+ private static final String TAG = "SuggestionCtrlMixin";
+ private static final boolean DEBUG = false;
+
+ private final Context mContext;
+ private final SuggestionController mSuggestionController;
+ private final SuggestionControllerHost mHost;
+
+ private boolean mSuggestionLoaded;
+
+ public SuggestionControllerMixin(Context context, SuggestionControllerHost host,
+ Lifecycle lifecycle, ComponentName componentName) {
+ mContext = context.getApplicationContext();
+ mHost = host;
+ mSuggestionController = new SuggestionController(mContext, componentName,
+ this /* serviceConnectionListener */);
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_START)
+ public void onStart() {
+ if (DEBUG) {
+ Log.d(TAG, "SuggestionController started");
+ }
+ mSuggestionController.start();
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+ public void onStop() {
+ if (DEBUG) {
+ Log.d(TAG, "SuggestionController stopped.");
+ }
+ mSuggestionController.stop();
+ }
+
+ @Override
+ public void onServiceConnected() {
+ final LoaderManager loaderManager = mHost.getLoaderManager();
+ if (loaderManager != null) {
+ loaderManager.restartLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS,
+ null /* args */, this /* callback */);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected() {
+ if (DEBUG) {
+ Log.d(TAG, "SuggestionService disconnected");
+ }
+ final LoaderManager loaderManager = mHost.getLoaderManager();
+ if (loaderManager != null) {
+ loaderManager.destroyLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS);
+ }
+ }
+
+ @Override
+ public Loader<List<Suggestion>> onCreateLoader(int id, Bundle args) {
+ if (id == SuggestionLoader.LOADER_ID_SUGGESTIONS) {
+ mSuggestionLoaded = false;
+ return new SuggestionLoader(mContext, mSuggestionController);
+ }
+ throw new IllegalArgumentException("This loader id is not supported " + id);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<List<Suggestion>> loader, List<Suggestion> data) {
+ mSuggestionLoaded = true;
+ mHost.onSuggestionReady(data);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<List<Suggestion>> loader) {
+ mSuggestionLoaded = false;
+ }
+
+ public boolean isSuggestionLoaded() {
+ return mSuggestionLoaded;
+ }
+
+ public void dismissSuggestion(Suggestion suggestion) {
+ mSuggestionController.dismissSuggestions(suggestion);
+ }
+
+ public void launchSuggestion(Suggestion suggestion) {
+ mSuggestionController.launchSuggestion(suggestion);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java
new file mode 100644
index 0000000..9c1af1e
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import android.content.Context;
+import android.service.settings.suggestions.Suggestion;
+import android.util.Log;
+
+import com.android.settingslib.utils.AsyncLoader;
+
+import java.util.List;
+
+public class SuggestionLoader extends AsyncLoader<List<Suggestion>> {
+
+ public static final int LOADER_ID_SUGGESTIONS = 42;
+ private static final String TAG = "SuggestionLoader";
+
+ private final SuggestionController mSuggestionController;
+
+ public SuggestionLoader(Context context, SuggestionController controller) {
+ super(context);
+ mSuggestionController = controller;
+ }
+
+ @Override
+ protected void onDiscardResult(List<Suggestion> result) {
+
+ }
+
+ @Override
+ public List<Suggestion> loadInBackground() {
+ final List<Suggestion> data = mSuggestionController.getSuggestions();
+ if (data == null) {
+ Log.d(TAG, "data is null");
+ } else {
+ Log.d(TAG, "data size " + data.size());
+ }
+ return data;
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 754b881..e11017c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -32,7 +32,6 @@
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;
import android.net.ScoredNetwork;
-import android.net.WifiKey;
import android.net.wifi.IWifiManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
@@ -43,6 +42,7 @@
import android.net.wifi.WifiNetworkScoreCache;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.Bundle;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -52,6 +52,7 @@
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.TtsSpan;
+import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -60,11 +61,11 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@@ -91,6 +92,9 @@
*/
public static final int HIGHER_FREQ_5GHZ = 5900;
+ /** The key which identifies this AccessPoint grouping. */
+ private String mKey;
+
@IntDef({Speed.NONE, Speed.SLOW, Speed.MODERATE, Speed.FAST, Speed.VERY_FAST})
@Retention(RetentionPolicy.SOURCE)
public @interface Speed {
@@ -116,14 +120,8 @@
int VERY_FAST = 30;
}
- /**
- * Experimental: we should be able to show the user the list of BSSIDs and bands
- * for that SSID.
- * For now this data is used only with Verbose Logging so as to show the band and number
- * of BSSIDs on which that network is seen.
- */
- private final ConcurrentHashMap<String, ScanResult> mScanResultCache =
- new ConcurrentHashMap<String, ScanResult>(32);
+ /** The underlying set of scan results comprising this AccessPoint. */
+ private final ArraySet<ScanResult> mScanResults = new ArraySet<>();
/**
* Map of BSSIDs to scored networks for individual bssids.
@@ -133,17 +131,13 @@
*/
private final Map<String, TimestampedScoredNetwork> mScoredNetworkCache = new HashMap<>();
- /** Maximum age of scan results to hold onto while actively scanning. **/
- private static final long MAX_SCAN_RESULT_AGE_MILLIS = 25000;
-
static final String KEY_NETWORKINFO = "key_networkinfo";
static final String KEY_WIFIINFO = "key_wifiinfo";
- static final String KEY_SCANRESULT = "key_scanresult";
static final String KEY_SSID = "key_ssid";
static final String KEY_SECURITY = "key_security";
static final String KEY_SPEED = "key_speed";
static final String KEY_PSKTYPE = "key_psktype";
- static final String KEY_SCANRESULTCACHE = "key_scanresultcache";
+ static final String KEY_SCANRESULTS = "key_scanresults";
static final String KEY_SCOREDNETWORKCACHE = "key_scorednetworkcache";
static final String KEY_CONFIG = "key_config";
static final String KEY_FQDN = "key_fqdn";
@@ -216,7 +210,10 @@
public AccessPoint(Context context, Bundle savedState) {
mContext = context;
- mConfig = savedState.getParcelable(KEY_CONFIG);
+
+ if (savedState.containsKey(KEY_CONFIG)) {
+ mConfig = savedState.getParcelable(KEY_CONFIG);
+ }
if (mConfig != null) {
loadConfig(mConfig);
}
@@ -236,12 +233,11 @@
if (savedState.containsKey(KEY_NETWORKINFO)) {
mNetworkInfo = savedState.getParcelable(KEY_NETWORKINFO);
}
- if (savedState.containsKey(KEY_SCANRESULTCACHE)) {
- ArrayList<ScanResult> scanResultArrayList =
- savedState.getParcelableArrayList(KEY_SCANRESULTCACHE);
- mScanResultCache.clear();
- for (ScanResult result : scanResultArrayList) {
- mScanResultCache.put(result.BSSID, result);
+ if (savedState.containsKey(KEY_SCANRESULTS)) {
+ Parcelable[] scanResults = savedState.getParcelableArray(KEY_SCANRESULTS);
+ mScanResults.clear();
+ for (Parcelable result : scanResults) {
+ mScanResults.add((ScanResult) result);
}
}
if (savedState.containsKey(KEY_SCOREDNETWORKCACHE)) {
@@ -268,8 +264,10 @@
}
update(mConfig, mInfo, mNetworkInfo);
- // Do not evict old scan results on initial creation
+ // Calculate required fields
+ updateKey();
updateRssi();
+
mId = sLastId.incrementAndGet();
}
@@ -295,30 +293,75 @@
copyFrom(other);
}
- AccessPoint(Context context, ScanResult result) {
+ AccessPoint(Context context, Collection<ScanResult> results) {
mContext = context;
- initWithScanResult(result);
+
+ if (results.isEmpty()) {
+ throw new IllegalArgumentException("Cannot construct with an empty ScanResult list");
+ }
+ mScanResults.addAll(results);
+
+ // Information derived from scan results
+ ScanResult firstResult = results.iterator().next();
+ ssid = firstResult.SSID;
+ bssid = firstResult.BSSID;
+ security = getSecurity(firstResult);
+ if (security == SECURITY_PSK) {
+ pskType = getPskType(firstResult);
+ }
+ updateKey();
+ updateRssi();
+
+ // Passpoint Info
+ mIsCarrierAp = firstResult.isCarrierAp;
+ mCarrierApEapType = firstResult.carrierApEapType;
+ mCarrierName = firstResult.carrierName;
+
mId = sLastId.incrementAndGet();
}
+ @VisibleForTesting void loadConfig(WifiConfiguration config) {
+ ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
+ bssid = config.BSSID;
+ security = getSecurity(config);
+ updateKey();
+ networkId = config.networkId;
+ mConfig = config;
+ }
+
+ /** Updates {@link #mKey} and should only called upon object creation/initialization. */
+ private void updateKey() {
+ // TODO(sghuman): Consolidate Key logic on ScanResultMatchInfo
+
+ StringBuilder builder = new StringBuilder();
+
+ if (TextUtils.isEmpty(getSsidStr())) {
+ builder.append(getBssid());
+ } else {
+ builder.append(getSsidStr());
+ }
+
+ builder.append(',').append(getSecurity());
+ mKey = builder.toString();
+ }
+
/**
* Copy accesspoint information. NOTE: We do not copy tag information because that is never
* set on the internal copy.
- * @param that
*/
void copyFrom(AccessPoint that) {
- that.evictOldScanResults();
this.ssid = that.ssid;
this.bssid = that.bssid;
this.security = that.security;
+ this.mKey = that.mKey;
this.networkId = that.networkId;
this.pskType = that.pskType;
this.mConfig = that.mConfig; //TODO: Watch out, this object is mutated.
this.mRssi = that.mRssi;
this.mInfo = that.mInfo;
this.mNetworkInfo = that.mNetworkInfo;
- this.mScanResultCache.clear();
- this.mScanResultCache.putAll(that.mScanResultCache);
+ this.mScanResults.clear();
+ this.mScanResults.addAll(that.mScanResults);
this.mScoredNetworkCache.clear();
this.mScoredNetworkCache.putAll(that.mScoredNetworkCache);
this.mId = that.mId;
@@ -426,7 +469,7 @@
if (WifiTracker.sVerboseLogging) {
builder.append(",rssi=").append(mRssi);
- builder.append(",scan cache size=").append(mScanResultCache.size());
+ builder.append(",scan cache size=").append(mScanResults.size());
}
return builder.append(')').toString();
@@ -468,7 +511,7 @@
*/
private boolean updateScores(WifiNetworkScoreCache scoreCache, long maxScoreCacheAgeMillis) {
long nowMillis = SystemClock.elapsedRealtime();
- for (ScanResult result : mScanResultCache.values()) {
+ for (ScanResult result : mScanResults) {
ScoredNetwork score = scoreCache.getScoredNetwork(result);
if (score == null) {
continue;
@@ -555,7 +598,7 @@
mIsScoredNetworkMetered |= score.meteredHint;
}
} else {
- for (ScanResult result : mScanResultCache.values()) {
+ for (ScanResult result : mScanResults) {
ScoredNetwork score = scoreCache.getScoredNetwork(result);
if (score == null) {
continue;
@@ -566,19 +609,21 @@
return oldMetering == mIsScoredNetworkMetered;
}
- private void evictOldScanResults() {
- long nowMs = SystemClock.elapsedRealtime();
- for (Iterator<ScanResult> iter = mScanResultCache.values().iterator(); iter.hasNext(); ) {
- ScanResult result = iter.next();
- // result timestamp is in microseconds
- if (nowMs - result.timestamp / 1000 > MAX_SCAN_RESULT_AGE_MILLIS) {
- iter.remove();
- }
+ public static String getKey(ScanResult result) {
+ StringBuilder builder = new StringBuilder();
+
+ if (TextUtils.isEmpty(result.SSID)) {
+ builder.append(result.BSSID);
+ } else {
+ builder.append(result.SSID);
}
+
+ builder.append(',').append(getSecurity(result));
+ return builder.toString();
}
- public boolean matches(ScanResult result) {
- return ssid.equals(result.SSID) && security == getSecurity(result);
+ public String getKey() {
+ return mKey;
}
public boolean matches(WifiConfiguration config) {
@@ -622,9 +667,12 @@
return mRssi;
}
- public ConcurrentHashMap<String, ScanResult> getScanResults() {
- return mScanResultCache;
- }
+ /**
+ * Returns the underlying scan result set.
+ *
+ * <p>Callers should not modify this set.
+ */
+ public Set<ScanResult> getScanResults() { return mScanResults; }
public Map<String, TimestampedScoredNetwork> getScoredNetworkCache() {
return mScoredNetworkCache;
@@ -645,7 +693,7 @@
}
int rssi = UNREACHABLE_RSSI;
- for (ScanResult result : mScanResultCache.values()) {
+ for (ScanResult result : mScanResults) {
if (result.level > rssi) {
rssi = result.level;
}
@@ -853,7 +901,6 @@
}
if (WifiTracker.sVerboseLogging) {
- evictOldScanResults();
summary.append(WifiUtils.buildLoggingSummary(this, config));
}
@@ -950,28 +997,6 @@
mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
}
- void loadConfig(WifiConfiguration config) {
- ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
- bssid = config.BSSID;
- security = getSecurity(config);
- networkId = config.networkId;
- mConfig = config;
- }
-
- private void initWithScanResult(ScanResult result) {
- ssid = result.SSID;
- bssid = result.BSSID;
- security = getSecurity(result);
- if (security == SECURITY_PSK)
- pskType = getPskType(result);
-
- mScanResultCache.put(result.BSSID, result);
- updateRssi();
- mIsCarrierAp = result.isCarrierAp;
- mCarrierApEapType = result.carrierApEapType;
- mCarrierName = result.carrierName;
- }
-
public void saveWifiState(Bundle savedState) {
if (ssid != null) savedState.putString(KEY_SSID, getSsidStr());
savedState.putInt(KEY_SECURITY, security);
@@ -979,9 +1004,8 @@
savedState.putInt(KEY_PSKTYPE, pskType);
if (mConfig != null) savedState.putParcelable(KEY_CONFIG, mConfig);
savedState.putParcelable(KEY_WIFIINFO, mInfo);
- evictOldScanResults();
- savedState.putParcelableArrayList(KEY_SCANRESULTCACHE,
- new ArrayList<ScanResult>(mScanResultCache.values()));
+ savedState.putParcelableArray(KEY_SCANRESULTS,
+ mScanResults.toArray(new Parcelable[mScanResults.size()]));
savedState.putParcelableArrayList(KEY_SCOREDNETWORKCACHE,
new ArrayList<>(mScoredNetworkCache.values()));
if (mNetworkInfo != null) {
@@ -1003,49 +1027,58 @@
}
/**
- * Update the AP with the given scan result.
+ * Sets {@link #mScanResults} to the given collection.
*
- * @param result the ScanResult to add to the AccessPoint scan cache
- * @param evictOldScanResults whether stale scan results should be removed
- * from the cache during this update process
- * @return true if the scan result update caused a change in state which would impact ranking
- * or AccessPoint rendering (e.g. wifi level, security)
+ * @param scanResults a collection of scan results to add to the internal set
+ * @throws IllegalArgumentException if any of the given ScanResults did not belong to this AP
*/
- boolean update(ScanResult result, boolean evictOldScanResults) {
- if (matches(result)) {
- int oldLevel = getLevel();
+ void setScanResults(Collection<ScanResult> scanResults) {
- /* Add or update the scan result for the BSSID */
- mScanResultCache.put(result.BSSID, result);
- if (evictOldScanResults) evictOldScanResults();
- updateRssi();
- int newLevel = getLevel();
-
- if (newLevel > 0 && newLevel != oldLevel) {
- // Only update labels on visible rssi changes
- updateSpeed();
- if (mAccessPointListener != null) {
- mAccessPointListener.onLevelChanged(this);
- }
+ // Validate scan results are for current AP only
+ String key = getKey();
+ for (ScanResult result : scanResults) {
+ String scanResultKey = AccessPoint.getKey(result);
+ if (!mKey.equals(scanResultKey)) {
+ throw new IllegalArgumentException(
+ String.format("ScanResult %s\nkey of %s did not match current AP key %s",
+ result, scanResultKey, key));
}
+ }
+
+
+ int oldLevel = getLevel();
+ mScanResults.clear();
+ mScanResults.addAll(scanResults);
+ updateRssi();
+ int newLevel = getLevel();
+
+ // If newLevel is 0, there will be no displayed Preference since the AP is unreachable
+ if (newLevel > 0 && newLevel != oldLevel) {
+ // Only update labels on visible rssi changes
+ updateSpeed();
+ if (mAccessPointListener != null) {
+ mAccessPointListener.onLevelChanged(this);
+ }
+ }
+
+ if (mAccessPointListener != null) {
+ mAccessPointListener.onAccessPointChanged(this);
+ }
+
+ if (!scanResults.isEmpty()) {
+ ScanResult result = scanResults.iterator().next();
+
// This flag only comes from scans, is not easily saved in config
if (security == SECURITY_PSK) {
pskType = getPskType(result);
}
- if (mAccessPointListener != null) {
- mAccessPointListener.onAccessPointChanged(this);
- }
-
// The carrier info in the ScanResult is set by the platform based on the SSID and will
// always be the same for all matching scan results.
mIsCarrierAp = result.isCarrierAp;
mCarrierApEapType = result.carrierApEapType;
mCarrierName = result.carrierName;
-
- return true;
}
- return false;
}
/** Attempt to update the AccessPoint and return true if an update occurred. */
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index dd55188..109eb97 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -77,19 +77,6 @@
private int mDefaultIconResId;
private int mWifiSpeed = Speed.NONE;
- public static String generatePreferenceKey(AccessPoint accessPoint) {
- StringBuilder builder = new StringBuilder();
-
- if (TextUtils.isEmpty(accessPoint.getSsidStr())) {
- builder.append(accessPoint.getBssid());
- } else {
- builder.append(accessPoint.getSsidStr());
- }
-
- builder.append(',').append(accessPoint.getSecurity());
- return builder.toString();
- }
-
@Nullable
private static StateListDrawable getFrictionStateListDrawable(Context context) {
TypedArray frictionSld;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
index 3dec1d3..2993a0d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
@@ -23,6 +23,7 @@
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.os.Bundle;
+import android.os.Parcelable;
import android.support.annotation.Keep;
import com.android.settingslib.wifi.AccessPoint.Speed;
@@ -58,7 +59,7 @@
private String mCarrierName = null;
Context mContext;
- private ArrayList<ScanResult> mScanResultCache;
+ private ArrayList<ScanResult> mScanResults;
private ArrayList<TimestampedScoredNetwork> mScoredNetworkCache;
@Keep
@@ -84,8 +85,9 @@
if (mProviderFriendlyName != null) {
bundle.putString(AccessPoint.KEY_PROVIDER_FRIENDLY_NAME, mProviderFriendlyName);
}
- if (mScanResultCache != null) {
- bundle.putParcelableArrayList(AccessPoint.KEY_SCANRESULTCACHE, mScanResultCache);
+ if (mScanResults != null) {
+ bundle.putParcelableArray(AccessPoint.KEY_SCANRESULTS,
+ mScanResults.toArray(new Parcelable[mScanResults.size()]));
}
if (mScoredNetworkCache != null) {
bundle.putParcelableArrayList(AccessPoint.KEY_SCOREDNETWORKCACHE, mScoredNetworkCache);
@@ -229,8 +231,8 @@
return this;
}
- public TestAccessPointBuilder setScanResultCache(ArrayList<ScanResult> scanResultCache) {
- mScanResultCache = scanResultCache;
+ public TestAccessPointBuilder setScanResults(ArrayList<ScanResult> scanResults) {
+ mScanResults = scanResults;
return this;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index c56e1da..1ac56a9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -39,11 +39,13 @@
import android.os.Looper;
import android.os.Message;
import android.os.Process;
+import android.os.SystemClock;
import android.provider.Settings;
import android.support.annotation.GuardedBy;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.text.format.DateUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
@@ -78,6 +80,9 @@
*/
private static final long DEFAULT_MAX_CACHED_SCORE_AGE_MILLIS = 20 * DateUtils.MINUTE_IN_MILLIS;
+ /** Maximum age of scan results to hold onto while actively scanning. **/
+ private static final long MAX_SCAN_RESULT_AGE_MILLIS = 25000;
+
private static final String TAG = "WifiTracker";
private static final boolean DBG() {
return Log.isLoggable(TAG, Log.DEBUG);
@@ -142,6 +147,8 @@
= new AccessPointListenerAdapter();
private final HashMap<String, Integer> mSeenBssids = new HashMap<>();
+
+ // TODO(sghuman): Change this to be keyed on AccessPoint.getKey
private final HashMap<String, ScanResult> mScanResultCache = new HashMap<>();
private Integer mScanId = 0;
@@ -455,34 +462,42 @@
}
private Collection<ScanResult> updateScanResultCache(final List<ScanResult> newResults) {
- mScanId++;
+ // TODO(sghuman): Delete this and replace it with the Map of Ap Keys to ScanResults
for (ScanResult newResult : newResults) {
if (newResult.SSID == null || newResult.SSID.isEmpty()) {
continue;
}
mScanResultCache.put(newResult.BSSID, newResult);
- mSeenBssids.put(newResult.BSSID, mScanId);
}
- if (mScanId > NUM_SCANS_TO_CONFIRM_AP_LOSS) {
- if (DBG()) Log.d(TAG, "------ Dumping SSIDs that were expired on this scan ------");
- Integer threshold = mScanId - NUM_SCANS_TO_CONFIRM_AP_LOSS;
- for (Iterator<Map.Entry<String, Integer>> it = mSeenBssids.entrySet().iterator();
- it.hasNext(); /* nothing */) {
- Map.Entry<String, Integer> e = it.next();
- if (e.getValue() < threshold) {
- ScanResult result = mScanResultCache.get(e.getKey());
- if (DBG()) Log.d(TAG, "Removing " + e.getKey() + ":(" + result.SSID + ")");
- mScanResultCache.remove(e.getKey());
- it.remove();
- }
- }
- if (DBG()) Log.d(TAG, "---- Done Dumping SSIDs that were expired on this scan ----");
+ // Don't evict old results if no new scan results
+ if (!mStaleScanResults) {
+ evictOldScans();
}
+ // TODO(sghuman): Update a Map<ApKey, List<ScanResults>> variable to be reused later after
+ // double threads have been removed.
+
return mScanResultCache.values();
}
+ /**
+ * Remove old scan results from the cache.
+ *
+ * <p>Should only ever be invoked from {@link #updateScanResultCache(List)} when
+ * {@link #mStaleScanResults} is false.
+ */
+ private void evictOldScans() {
+ long nowMs = SystemClock.elapsedRealtime();
+ for (Iterator<ScanResult> iter = mScanResultCache.values().iterator(); iter.hasNext(); ) {
+ ScanResult result = iter.next();
+ // result timestamp is in microseconds
+ if (nowMs - result.timestamp / 1000 > MAX_SCAN_RESULT_AGE_MILLIS) {
+ iter.remove();
+ }
+ }
+ }
+
private WifiConfiguration getWifiConfigurationForNetworkId(
int networkId, final List<WifiConfiguration> configs) {
if (configs != null) {
@@ -541,10 +556,12 @@
/* Lookup table to more quickly update AccessPoints by only considering objects with the
* correct SSID. Maps SSID -> List of AccessPoints with the given SSID. */
- Multimap<String, AccessPoint> apMap = new Multimap<String, AccessPoint>();
+ Multimap<String, AccessPoint> existingApMap = new Multimap<String, AccessPoint>();
final Collection<ScanResult> results = updateScanResultCache(newScanResults);
+ // TODO(sghuman): This entire block only exists to populate the WifiConfiguration for
+ // APs, remove and refactor
if (configs != null) {
for (WifiConfiguration config : configs) {
if (config.selfAdded && config.numAssociation == 0) {
@@ -568,7 +585,7 @@
accessPoint.setUnreachable();
}
accessPoints.add(accessPoint);
- apMap.put(accessPoint.getSsidStr(), accessPoint);
+ existingApMap.put(accessPoint.getSsidStr(), accessPoint);
} else {
// If we aren't using saved networks, drop them into the cache so that
// we have access to their saved info.
@@ -579,6 +596,9 @@
final List<NetworkKey> scoresToRequest = new ArrayList<>();
if (results != null) {
+ // TODO(sghuman): Move this loop to updateScanResultCache and make instance variable
+ // after double handlers are removed.
+ ArrayMap<String, List<ScanResult>> scanResultsByApKey = new ArrayMap<>();
for (ScanResult result : results) {
// Ignore hidden and ad-hoc networks.
if (result.SSID == null || result.SSID.length() == 0 ||
@@ -591,27 +611,45 @@
scoresToRequest.add(key);
}
- boolean found = false;
- for (AccessPoint accessPoint : apMap.getAll(result.SSID)) {
- // We want to evict old scan results if are current results are not stale
- if (accessPoint.update(result, !mStaleScanResults)) {
- found = true;
- break;
- }
+ String apKey = AccessPoint.getKey(result);
+ List<ScanResult> resultList;
+ if (scanResultsByApKey.containsKey(apKey)) {
+ resultList = scanResultsByApKey.get(apKey);
+ } else {
+ resultList = new ArrayList<>();
+ scanResultsByApKey.put(apKey, resultList);
}
- if (!found && mIncludeScans) {
- AccessPoint accessPoint = getCachedOrCreate(result, cachedAccessPoints);
+
+ resultList.add(result);
+ }
+
+ for (Map.Entry<String, List<ScanResult>> entry : scanResultsByApKey.entrySet()) {
+ // List can not be empty as it is dynamically constructed on each iteration
+ ScanResult firstResult = entry.getValue().get(0);
+ boolean found = false;
+ for (AccessPoint accessPoint : existingApMap.getAll(firstResult.SSID)) {
+ accessPoint.setScanResults(entry.getValue());
+ found = true;
+ break;
+ }
+
+ // Only create a new AP / add to the list if it wasn't already in the saved configs
+ if (!found) {
+ AccessPoint accessPoint =
+ getCachedOrCreate(entry.getValue(), cachedAccessPoints);
if (mLastInfo != null && mLastNetworkInfo != null) {
accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
}
- if (result.isPasspointNetwork()) {
+ // TODO(sghuman): Move isPasspointNetwork logic into AccessPoint.java
+ if (firstResult.isPasspointNetwork()) {
// Retrieve a WifiConfiguration for a Passpoint provider that matches
// the given ScanResult. This is used for showing that a given AP
// (ScanResult) is available via a Passpoint provider (provider friendly
// name).
try {
- WifiConfiguration config = mWifiManager.getMatchingWifiConfig(result);
+ WifiConfiguration config =
+ mWifiManager.getMatchingWifiConfig(firstResult);
if (config != null) {
accessPoint.update(config);
}
@@ -621,7 +659,6 @@
}
accessPoints.add(accessPoint);
- apMap.put(accessPoint.getSsidStr(), accessPoint);
}
}
}
@@ -662,17 +699,18 @@
}
@VisibleForTesting
- AccessPoint getCachedOrCreate(ScanResult result, List<AccessPoint> cache) {
+ AccessPoint getCachedOrCreate(
+ List<ScanResult> scanResults,
+ List<AccessPoint> cache) {
final int N = cache.size();
for (int i = 0; i < N; i++) {
- if (cache.get(i).matches(result)) {
+ if (cache.get(i).getKey().equals(AccessPoint.getKey(scanResults.get(0)))) {
AccessPoint ret = cache.remove(i);
- // evict old scan results only if we have fresh results
- ret.update(result, !mStaleScanResults);
+ ret.setScanResults(scanResults);
return ret;
}
}
- final AccessPoint accessPoint = new AccessPoint(mContext, result);
+ final AccessPoint accessPoint = new AccessPoint(mContext, scanResults);
accessPoint.setListener(mAccessPointListenerAdapter);
return accessPoint;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
index 932c6fd..fd48eea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
@@ -109,7 +109,7 @@
// TODO: sort list by RSSI or age
long nowMs = SystemClock.elapsedRealtime();
- for (ScanResult result : accessPoint.getScanResults().values()) {
+ for (ScanResult result : accessPoint.getScanResults()) {
if (result.frequency >= AccessPoint.LOWER_FREQ_5GHZ
&& result.frequency <= AccessPoint.HIGHER_FREQ_5GHZ) {
// Strictly speaking: [4915, 5825]
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index ec594a6..1440311 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -40,6 +40,7 @@
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.os.Bundle;
+import android.os.Parcelable;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
@@ -277,7 +278,8 @@
scanResult.BSSID = "bssid";
scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
scanResult.capabilities = "";
- assertThat(ap.update(scanResult, true /* evict old scan results */)).isTrue();
+
+ ap.setScanResults(Collections.singletonList(scanResult));
assertThat(ap.getRssi()).isEqualTo(expectedRssi);
}
@@ -477,7 +479,7 @@
result.carrierApEapType = WifiEnterpriseConfig.Eap.SIM;
result.carrierName = carrierName;
- AccessPoint ap = new AccessPoint(mContext, result);
+ AccessPoint ap = new AccessPoint(mContext, Collections.singletonList(result));
assertThat(ap.getSummary()).isEqualTo(String.format(mContext.getString(
R.string.available_via_carrier), carrierName));
assertThat(ap.isCarrierAp()).isEqualTo(true);
@@ -513,7 +515,7 @@
}
@Test
- public void testUpdateScanResultWithCarrierInfo() {
+ public void testSetScanResultWithCarrierInfo() {
String ssid = "ssid";
AccessPoint ap = new TestAccessPointBuilder(mContext).setSsid(ssid).build();
assertThat(ap.isCarrierAp()).isEqualTo(false);
@@ -529,8 +531,9 @@
scanResult.isCarrierAp = true;
scanResult.carrierApEapType = carrierApEapType;
scanResult.carrierName = carrierName;
- assertThat(ap.update(scanResult, true /* evictOldScanresults */)).isTrue();
+
+ ap.setScanResults(Collections.singletonList(scanResult));
assertThat(ap.isCarrierAp()).isEqualTo(true);
assertThat(ap.getCarrierApEapType()).isEqualTo(carrierApEapType);
assertThat(ap.getCarrierName()).isEqualTo(carrierName);
@@ -552,7 +555,9 @@
private AccessPoint createAccessPointWithScanResultCache() {
Bundle bundle = new Bundle();
- bundle.putParcelableArrayList(AccessPoint.KEY_SCANRESULTCACHE, SCAN_RESULTS);
+ bundle.putParcelableArray(
+ AccessPoint.KEY_SCANRESULTS,
+ SCAN_RESULTS.toArray(new Parcelable[SCAN_RESULTS.size()]));
return new AccessPoint(mContext, bundle);
}
@@ -903,7 +908,7 @@
.setActive(true)
.setNetworkId(networkId)
.setSsid(TEST_SSID)
- .setScanResultCache(scanResults)
+ .setScanResults(scanResults)
.setWifiInfo(info)
.build();
@@ -990,7 +995,7 @@
.setActive(true)
.setScoredNetworkCache(
new ArrayList(Arrays.asList(recentScore)))
- .setScanResultCache(SCAN_RESULTS)
+ .setScanResults(SCAN_RESULTS)
.build();
when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
@@ -1018,7 +1023,7 @@
.setActive(true)
.setScoredNetworkCache(
new ArrayList(Arrays.asList(recentScore)))
- .setScanResultCache(SCAN_RESULTS)
+ .setScanResults(SCAN_RESULTS)
.build();
int newSpeed = Speed.MODERATE;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 6615b8c..b36dda9 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -57,9 +58,9 @@
import android.os.SystemClock;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.FlakyTest;
import org.junit.After;
import org.junit.Before;
@@ -76,7 +77,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -399,7 +402,8 @@
WifiTracker tracker = new WifiTracker(
InstrumentationRegistry.getTargetContext(), null, true, true);
- AccessPoint result = tracker.getCachedOrCreate(scanResult, new ArrayList<AccessPoint>());
+ AccessPoint result = tracker.getCachedOrCreate(
+ Collections.singletonList(scanResult), new ArrayList<AccessPoint>());
assertTrue(result.mAccessPointListener != null);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/ShadowSuggestionController.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/ShadowSuggestionController.java
new file mode 100644
index 0000000..61bc83b
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/ShadowSuggestionController.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import android.service.settings.suggestions.Suggestion;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.List;
+
+@Implements(SuggestionController.class)
+public class ShadowSuggestionController {
+
+ public static boolean sStartCalled;
+ public static boolean sStopCalled;
+ public static boolean sGetSuggestionCalled;
+
+ public static List<Suggestion> sSuggestions;
+
+ public static void reset() {
+ sStartCalled = false;
+ sStopCalled = false;
+ sGetSuggestionCalled = false;
+ sSuggestions = null;
+ }
+
+ @Implementation
+ public void start() {
+ sStartCalled = true;
+ }
+
+ @Implementation
+ public void stop() {
+ sStopCalled = true;
+ }
+
+ public static void setSuggestion(List<Suggestion> suggestions) {
+ sSuggestions = suggestions;
+ }
+
+ @Implementation
+ public List<Suggestion> getSuggestions() {
+ sGetSuggestionCalled = true;
+ return sSuggestions;
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
new file mode 100644
index 0000000..ed1c405
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import static android.arch.lifecycle.Lifecycle.Event.ON_START;
+import static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.LoaderManager;
+import android.arch.lifecycle.LifecycleOwner;
+import android.content.ComponentName;
+import android.content.Context;
+
+import com.android.settingslib.TestConfig;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+ shadows = {
+ ShadowSuggestionController.class
+ })
+public class SuggestionControllerMixinTest {
+
+ @Mock
+ private SuggestionControllerMixin.SuggestionControllerHost mHost;
+
+ private Context mContext;
+ private LifecycleOwner mLifecycleOwner;
+ private Lifecycle mLifecycle;
+ private SuggestionControllerMixin mMixin;
+ private ComponentName mComponentName;
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+ mComponentName = new ComponentName(
+ "com.android.settings.intelligence",
+ "com.android.settings.intelligence.suggestions.SuggestionService");
+ }
+
+ @After
+ public void tearDown() {
+ ShadowSuggestionController.reset();
+ }
+
+ @Test
+ public void goThroughLifecycle_onStartStop_shouldStartStopController() {
+ mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle, mComponentName);
+
+ mLifecycle.handleLifecycleEvent(ON_START);
+ assertThat(ShadowSuggestionController.sStartCalled).isTrue();
+
+ mLifecycle.handleLifecycleEvent(ON_STOP);
+ assertThat(ShadowSuggestionController.sStopCalled).isTrue();
+ }
+
+ @Test
+ public void onServiceConnected_shouldGetSuggestion() {
+ final LoaderManager loaderManager = mock(LoaderManager.class);
+ when(mHost.getLoaderManager()).thenReturn(loaderManager);
+
+ mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle, mComponentName);
+ mMixin.onServiceConnected();
+
+ verify(loaderManager).restartLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS,
+ null /* args */, mMixin /* callback */);
+ }
+
+ @Test
+ public void onServiceConnected_hostNotAttached_shouldDoNothing() {
+ when(mHost.getLoaderManager()).thenReturn(null);
+
+ mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle, mComponentName);
+ mMixin.onServiceConnected();
+
+ verify(mHost).getLoaderManager();
+ }
+
+ @Test
+ public void onServiceDisconnected_hostNotAttached_shouldDoNothing() {
+ when(mHost.getLoaderManager()).thenReturn(null);
+
+ mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle, mComponentName);
+ mMixin.onServiceDisconnected();
+
+ verify(mHost).getLoaderManager();
+ }
+
+ @Test
+ public void doneLoadingg_shouldSetSuggestionLoaded() {
+ mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle, mComponentName);
+
+ mMixin.onLoadFinished(mock(SuggestionLoader.class), null);
+
+ assertThat(mMixin.isSuggestionLoaded()).isTrue();
+
+ mMixin.onLoaderReset(mock(SuggestionLoader.class));
+
+ assertThat(mMixin.isSuggestionLoaded()).isFalse();
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
index a4c821f..3fee16b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
@@ -61,34 +61,6 @@
}
@Test
- public void generatePreferenceKey_returnsSsidPlusSecurity() {
- String ssid = "ssid";
- String bssid = "00:00:00:00:00:00";
- int security = AccessPoint.SECURITY_WEP;
- String expectedKey = ssid + ',' + security;
-
- TestAccessPointBuilder builder = new TestAccessPointBuilder(mContext);
- builder.setBssid(bssid).setSsid(ssid).setSecurity(security);
-
- assertThat(AccessPointPreference.generatePreferenceKey(builder.build()))
- .isEqualTo(expectedKey);
- }
-
- @Test
- public void generatePreferenceKey_emptySsidReturnsBssidPlusSecurity() {
- String ssid = "";
- String bssid = "00:00:00:00:00:00";
- int security = AccessPoint.SECURITY_WEP;
- String expectedKey = bssid + ',' + security;
-
- TestAccessPointBuilder builder = new TestAccessPointBuilder(mContext);
- builder.setBssid(bssid).setSsid(ssid).setSecurity(security);
-
- assertThat(AccessPointPreference.generatePreferenceKey(builder.build()))
- .isEqualTo(expectedKey);
- }
-
- @Test
public void refresh_openNetwork_updateContentDescription() {
final String ssid = "ssid";
final String summary = "connected";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
index c5795d3..9310b73 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
@@ -29,6 +29,7 @@
import android.net.wifi.ScanResult;
import android.net.wifi.WifiNetworkScoreCache;
import android.os.Bundle;
+import android.os.Parcelable;
import android.os.SystemClock;
import android.text.format.DateUtils;
@@ -72,7 +73,8 @@
Bundle bundle = new Bundle();
ArrayList<ScanResult> scanResults = buildScanResultCache();
- bundle.putParcelableArrayList(AccessPoint.KEY_SCANRESULTCACHE, scanResults);
+ bundle.putParcelableArray(AccessPoint.KEY_SCANRESULTS,
+ scanResults.toArray(new Parcelable[scanResults.size()]));
AccessPoint ap = new AccessPoint(mContext, bundle);
when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index fd4d296..9bc2d75 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -12,8 +12,6 @@
android:icon="@mipmap/ic_launcher_settings"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
- <uses-library android:name="android.test.runner" />
-
<provider android:name="SettingsProvider"
android:authorities="settings"
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 7428149..1dc8e46 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -87,7 +87,6 @@
private static final HashSet<String> mValidTables = new HashSet<String>();
- private static final String DATABASE_JOURNAL_SUFFIX = "-journal";
private static final String DATABASE_BACKUP_SUFFIX = "-backup";
private static final String TABLE_SYSTEM = "system";
@@ -148,12 +147,7 @@
}
File databaseFile = mContext.getDatabasePath(getDatabaseName());
if (databaseFile.exists()) {
- databaseFile.delete();
- }
- File databaseJournalFile = mContext.getDatabasePath(getDatabaseName()
- + DATABASE_JOURNAL_SUFFIX);
- if (databaseJournalFile.exists()) {
- databaseJournalFile.delete();
+ SQLiteDatabase.deleteDatabase(databaseFile);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 6970c86..b286f89 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -103,21 +103,6 @@
Settings.Global.THEATER_MODE_ON,
GlobalSettingsProto.THEATER_MODE_ON);
dumpSetting(s, p,
- Settings.Global.RADIO_BLUETOOTH,
- GlobalSettingsProto.RADIO_BLUETOOTH);
- dumpSetting(s, p,
- Settings.Global.RADIO_WIFI,
- GlobalSettingsProto.RADIO_WIFI);
- dumpSetting(s, p,
- Settings.Global.RADIO_WIMAX,
- GlobalSettingsProto.RADIO_WIMAX);
- dumpSetting(s, p,
- Settings.Global.RADIO_CELL,
- GlobalSettingsProto.RADIO_CELL);
- dumpSetting(s, p,
- Settings.Global.RADIO_NFC,
- GlobalSettingsProto.RADIO_NFC);
- dumpSetting(s, p,
Settings.Global.AIRPLANE_MODE_RADIOS,
GlobalSettingsProto.AIRPLANE_MODE_RADIOS);
dumpSetting(s, p,
@@ -592,6 +577,9 @@
Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED,
GlobalSettingsProto.WIFI_VERBOSE_LOGGING_ENABLED);
dumpSetting(s, p,
+ Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED,
+ GlobalSettingsProto.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED);
+ dumpSetting(s, p,
Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
GlobalSettingsProto.WIFI_MAX_DHCP_RETRY_COUNT);
dumpSetting(s, p,
@@ -1067,6 +1055,9 @@
Settings.Global.STORAGE_SETTINGS_CLOBBER_THRESHOLD,
GlobalSettingsProto.STORAGE_SETTINGS_CLOBBER_THRESHOLD);
dumpSetting(s, p,
+ Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED,
+ GlobalSettingsProto.CHAINED_BATTERY_ATTRIBUTION_ENABLED);
+ dumpSetting(s, p,
Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION,
GlobalSettingsProto.MULTI_SIM_VOICE_CALL_SUBSCRIPTION);
dumpSetting(s, p,
@@ -1130,20 +1121,13 @@
Settings.Global.SHOW_FIRST_CRASH_DIALOG,
GlobalSettingsProto.SHOW_FIRST_CRASH_DIALOG);
dumpSetting(s, p,
- Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED,
- GlobalSettingsProto.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED);
- dumpSetting(s, p,
Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
GlobalSettingsProto.SHOW_RESTART_IN_CRASH_DIALOG);
dumpSetting(s, p,
Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG,
GlobalSettingsProto.SHOW_MUTE_IN_CRASH_DIALOG);
- dumpSetting(s, p,
- Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED,
- GlobalSettingsProto.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED);
- dumpSetting(s, p,
- Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED,
- GlobalSettingsProto.CHAINED_BATTERY_ATTRIBUTION_ENABLED);
+
+ // Please insert new settings using the same order as in Settings.Global.
}
/** Dump a single {@link SettingsState.Setting} to a proto buf */
@@ -1771,6 +1755,8 @@
dumpSetting(s, p,
Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
SecureSettingsProto.BLUETOOTH_ON_WHILE_DRIVING);
+
+ // Please insert new settings using the same order as in Settings.Secure.
}
private static void dumpProtoSystemSettingsLocked(
@@ -2029,5 +2015,7 @@
SystemSettingsProto.WHEN_TO_MAKE_WIFI_CALLS);
// The rest of the settings were moved to Settings.Secure, and are thus excluded here since
// they're deprecated from Settings.System.
+
+ // Please insert new settings using the same order as in Settings.System.
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index b7d6da4..d1459bb 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3015,7 +3015,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 151;
+ private static final int SETTINGS_VERSION = 152;
private final int mUserId;
@@ -3620,6 +3620,19 @@
currentVersion = 151;
}
+ if (currentVersion == 151) {
+ // Version 152: Reset wifi wake available for upgrading users
+ final SettingsState globalSettings = getGlobalSettingsLocked();
+ final int defaultValue = getContext().getResources().getInteger(
+ com.android.internal.R.integer.config_wifi_wakeup_available);
+ globalSettings.insertSettingLocked(
+ Settings.Global.WIFI_WAKEUP_AVAILABLE,
+ String.valueOf(defaultValue),
+ null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+
+ currentVersion = 152;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index a8a67ab..f158a65 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -166,6 +166,9 @@
@GuardedBy("mLock")
private final File mStatePersistFile;
+ @GuardedBy("mLock")
+ private final String mStatePersistTag;
+
private final Setting mNullSetting = new Setting(null, null, false, null, null) {
@Override
public boolean isNull() {
@@ -250,6 +253,7 @@
mContext = context;
mLock = lock;
mStatePersistFile = file;
+ mStatePersistTag = "settings-" + getTypeFromKey(key) + "-" + getUserIdFromKey(key);
mKey = key;
mHandler = new MyHandler(looper);
if (maxBytesPerAppPackage == MAX_BYTES_PER_APP_PACKAGE_LIMITED) {
@@ -634,7 +638,7 @@
Slog.i(LOG_TAG, "[PERSIST START]");
}
- AtomicFile destination = new AtomicFile(mStatePersistFile);
+ AtomicFile destination = new AtomicFile(mStatePersistFile, mStatePersistTag);
FileOutputStream out = null;
try {
out = destination.startWrite();
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 79299aa..64b2ae6 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -44,7 +44,6 @@
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.MANAGE_USB" />
<uses-permission android:name="android.permission.USE_RESERVED_DISK" />
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!-- System tool permissions granted to the shell. -->
<uses-permission android:name="android.permission.REAL_GET_TASKS" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 251ae2d..2bcf4ef 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -48,8 +48,8 @@
android-slices-core \
android-slices-view \
android-slices-builders \
- apptoolkit-arch-core-runtime \
- apptoolkit-lifecycle-extensions \
+ android-arch-core-runtime \
+ android-arch-lifecycle-extensions \
LOCAL_STATIC_JAVA_LIBRARIES := \
SystemUI-tags \
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 1fc36be..9613a6a 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -90,7 +90,6 @@
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
- <uses-permission android:name="android.permission.START_ACTIVITY_AS_CALLER" />
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
@@ -560,22 +559,6 @@
</intent-filter>
</activity>
- <activity android:name=".chooser.ChooserActivity"
- android:theme="@*android:style/Theme.NoDisplay"
- android:finishOnCloseSystemDialogs="true"
- android:excludeFromRecents="true"
- android:documentLaunchMode="never"
- android:relinquishTaskIdentity="true"
- android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
- android:process=":ui"
- android:visibleToInstantApps="true">
- <intent-filter>
- <action android:name="android.intent.action.CHOOSER_UI" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.VOICE" />
- </intent-filter>
- </activity>
-
<!-- Doze with notifications, run in main sysui process for every user -->
<service
android:name=".doze.DozeService"
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
index 32eb5d5..4b3afdc 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
@@ -99,6 +99,9 @@
public ComponentName effectsSuppressor;
public String effectsSuppressorName;
public int activeStream = NO_ACTIVE_STREAM;
+ public boolean disallowAlarms;
+ public boolean disallowMedia;
+ public boolean disallowRinger;
public State copy() {
final State rt = new State();
@@ -113,6 +116,9 @@
}
rt.effectsSuppressorName = effectsSuppressorName;
rt.activeStream = activeStream;
+ rt.disallowAlarms = disallowAlarms;
+ rt.disallowMedia = disallowMedia;
+ rt.disallowRinger = disallowRinger;
return rt;
}
@@ -142,6 +148,9 @@
sep(sb, indent); sb.append("effectsSuppressor:").append(effectsSuppressor);
sep(sb, indent); sb.append("effectsSuppressorName:").append(effectsSuppressorName);
sep(sb, indent); sb.append("activeStream:").append(activeStream);
+ sep(sb, indent); sb.append("disallowAlarms:").append(disallowAlarms);
+ sep(sb, indent); sb.append("disallowMedia:").append(disallowMedia);
+ sep(sb, indent); sb.append("disallowRinger:").append(disallowRinger);
if (indent > 0) sep(sb, indent);
return sb.append('}').toString();
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
index 18d27bb..53f7e44 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
@@ -26,14 +26,26 @@
@DependsOn(target = QSIconView.class)
@DependsOn(target = QSTile.class)
public abstract class QSTileView extends LinearLayout {
- public static final int VERSION = 1;
+ public static final int VERSION = 2;
public QSTileView(Context context) {
super(context);
}
public abstract View updateAccessibilityOrder(View previousView);
+
+ /**
+ * Returns a {@link QSIconView} containing only the icon for this tile. Use
+ * {@link #getIconWithBackground()} to retrieve the entire tile (background & peripherals
+ * included).
+ */
public abstract QSIconView getIcon();
+
+ /**
+ * Returns a {@link View} containing the icon for this tile along with the accompanying
+ * background circle/peripherals. To retrieve only the inner icon, use {@link #getIcon()}.
+ */
+ public abstract View getIconWithBackground();
public abstract void init(QSTile tile);
public abstract void onStateChanged(State state);
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index eda8c69..faa2c17 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -31,6 +31,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/widget_vertical_padding"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/keyguard_clock_container"
@@ -63,7 +64,6 @@
<include layout="@layout/keyguard_status_area"
android:id="@+id/keyguard_status_area"
android:layout_marginTop="20dp"
- android:layout_marginBottom="@dimen/widget_vertical_padding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/clock_separator" />
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 5aca7f9..28a0935 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -75,7 +75,7 @@
<dimen name="password_char_padding">8dp</dimen>
<!-- The vertical margin between the date and the owner info. -->
- <dimen name="date_owner_info_margin">6dp</dimen>
+ <dimen name="date_owner_info_margin">2dp</dimen>
<!-- The translation for disappearing security views after having solved them. -->
<dimen name="disappear_y_translation">-32dp</dimen>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 3a41681..8a48e7b 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -124,6 +124,10 @@
<string name="keyboardview_keycode_delete">Delete</string>
<!-- Description of the button used to disable current carrier when the device supported embedded SIM. [CHAR LIMIT=30] -->
<string name="disable_carrier_button_text">Disable eSIM</string>
+ <!-- Title of Error message when disabling current carrier failed for the device supported embedded SIM. [CHAR LIMIT=80] -->
+ <string name="error_disable_esim_title">Can\u2019t disable eSIM</string>
+ <!-- Description of Error message when disabling current carrier failed for the device supported embedded SIM. [CHAR LIMIT=80] -->
+ <string name="error_disable_esim_msg">The eSIM can\u2019t be disabled due to an error.</string>
<!-- Description of the Enter button in a KeyboardView. [CHAR LIMIT=NONE] -->
<string name="keyboardview_keycode_enter">Enter</string>
@@ -146,8 +150,8 @@
<string name="kg_sim_pin_instructions">Enter SIM PIN.</string>
<!-- Instructions for using the SIM PIN unlock screen when there's more than one SIM -->
<string name="kg_sim_pin_instructions_multi">Enter SIM PIN for \"<xliff:g id="carrier" example="CARD 1">%1$s</xliff:g>\".</string>
- <!-- Instructions for disabling eSIM carrier to unlock the phone with embedded SIM -->
- <string name="kg_sim_lock_instructions_esim">Disable eSIM to use device without mobile service.</string>
+ <!-- Instructions for disabling eSIM carrier to unlock the phone with embedded SIM. This message follows the original SIM PIN/PUK message of device without embedded SIM. -->
+ <string name="kg_sim_lock_esim_instructions"><xliff:g id="previous_msg" example="Enter SIM PIN.">%1$s</xliff:g> Disable eSIM to use device without mobile service.</string>
<!-- Instructions for using the PIN unlock screen -->
<string name="kg_pin_instructions">Enter PIN</string>
<!-- Instructions for using the password unlock screen -->
diff --git a/libs/androidfw/tests/data/basic/res/layout/layout.xml b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
similarity index 62%
rename from libs/androidfw/tests/data/basic/res/layout/layout.xml
rename to packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
index 045ede4..509cd1f 100644
--- a/libs/androidfw/tests/data/basic/res/layout/layout.xml
+++ b/packages/SystemUI/res/drawable/qs_footer_drag_handle.xml
@@ -13,13 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<Button xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/ok"
- android:layout_width="0sp"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:layout_marginStart="2dip"
- android:layout_marginEnd="2dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textStyle="bold"
- android:text="@android:string/ok" />
\ No newline at end of file
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+ <solid
+ android:color="#e5e5e5" />
+ <corners android:radius="2dp" />
+</shape>
diff --git a/packages/SystemUI/res/layout/back.xml b/packages/SystemUI/res/layout/back.xml
index 43bec91..6843db9 100644
--- a/packages/SystemUI/res/layout/back.xml
+++ b/packages/SystemUI/res/layout/back.xml
@@ -24,8 +24,8 @@
systemui:keyCode="4"
android:scaleType="fitCenter"
android:contentDescription="@string/accessibility_back"
- android:paddingTop="15dp"
- android:paddingBottom="15dp"
+ android:paddingTop="@dimen/home_padding"
+ android:paddingBottom="@dimen/home_padding"
android:paddingStart="@dimen/navigation_key_padding"
android:paddingEnd="@dimen/navigation_key_padding"
/>
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index 7b30d6a..cd1be15 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -40,7 +40,7 @@
<LinearLayout android:id="@+id/system_icons_super_container"
android:layout_width="wrap_content"
- android:layout_height="@dimen/status_bar_header_height"
+ android:layout_height="@*android:dimen/quick_qs_total_height"
android:layout_toStartOf="@id/multi_user_switch"
android:layout_alignWithParentIfMissing="true"
android:layout_marginStart="@dimen/system_icons_super_container_margin_start"
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 9f6a946..997fe6d 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -32,80 +32,108 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
+ android:layout_height="match_parent"
+ android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
- android:gravity="end">
+ android:gravity="end" >
- <com.android.keyguard.CarrierText
- android:id="@+id/qs_carrier_text"
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" >
+ <!-- Add an extra 8dp margin before carrier text without shifting it right -->
+ <android.widget.Space
+ android:layout_width="8dp"
+ android:layout_height="match_parent" />
+
+ <com.android.keyguard.CarrierText
+ android:id="@+id/qs_carrier_text"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="center_vertical|start"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textDirection="locale"
+ android:singleLine="true" />
+ </LinearLayout>
+
+ <FrameLayout
+ android:layout_width="24dp"
+ android:layout_height="match_parent" >
+ <View
+ android:id="@+id/qs_drag_handle_view"
+ android:layout_width="match_parent"
+ android:layout_height="4dp"
+ android:layout_marginTop="28dp"
+ android:background="@drawable/qs_footer_drag_handle" />
+ </FrameLayout>
+
+ <LinearLayout
+ android:id="@+id/qs_footer_actions_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
- android:gravity="center_vertical|start"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary"
- android:textDirection="locale"
- android:singleLine="true" />
-
- <com.android.systemui.statusbar.phone.MultiUserSwitch
- android:id="@+id/multi_user_switch"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_alignParentEnd="true"
- android:background="@drawable/ripple_drawable"
- android:focusable="true">
-
- <ImageView
- android:id="@+id/multi_user_avatar"
- android:layout_width="@dimen/multi_user_avatar_expanded_size"
- android:layout_height="@dimen/multi_user_avatar_expanded_size"
- android:layout_gravity="center"
- android:scaleType="centerInside"/>
- </com.android.systemui.statusbar.phone.MultiUserSwitch>
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@android:id/edit"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:clickable="true"
- android:clipToPadding="false"
- android:contentDescription="@string/accessibility_quick_settings_edit"
- android:focusable="true"
- android:padding="16dp"
- android:src="@drawable/ic_mode_edit"
- android:tint="?android:attr/colorForeground"/>
-
- <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
- android:id="@+id/settings_button_container"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:clipChildren="false"
- android:clipToPadding="false">
-
- <com.android.systemui.statusbar.phone.SettingsButton
- android:id="@+id/settings_button"
- style="@android:style/Widget.Material.Button.Borderless"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:gravity="end" >
+ <com.android.systemui.statusbar.phone.MultiUserSwitch
+ android:id="@+id/multi_user_switch"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_alignParentEnd="true"
android:background="@drawable/ripple_drawable"
- android:contentDescription="@string/accessibility_quick_settings_settings"
- android:src="@drawable/ic_settings_16dp"
- android:tint="?android:attr/colorForeground"/>
+ android:focusable="true">
+
+ <ImageView
+ android:id="@+id/multi_user_avatar"
+ android:layout_width="@dimen/multi_user_avatar_expanded_size"
+ android:layout_height="@dimen/multi_user_avatar_expanded_size"
+ android:layout_gravity="center"
+ android:scaleType="centerInside"/>
+ </com.android.systemui.statusbar.phone.MultiUserSwitch>
<com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/tuner_icon"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="36dp"
- android:paddingEnd="4dp"
- android:src="@drawable/tuner"
- android:tint="?android:attr/textColorTertiary"
- android:visibility="invisible"/>
+ android:id="@android:id/edit"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:clipToPadding="false"
+ android:contentDescription="@string/accessibility_quick_settings_edit"
+ android:focusable="true"
+ android:padding="16dp"
+ android:src="@drawable/ic_mode_edit"
+ android:tint="?android:attr/colorForeground"/>
- </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+ <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+ android:id="@+id/settings_button_container"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:clipChildren="false"
+ android:clipToPadding="false">
+
+ <com.android.systemui.statusbar.phone.SettingsButton
+ android:id="@+id/settings_button"
+ style="@android:style/Widget.Material.Button.Borderless"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/ripple_drawable"
+ android:contentDescription="@string/accessibility_quick_settings_settings"
+ android:src="@drawable/ic_settings_16dp"
+ android:tint="?android:attr/colorForeground"/>
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/tuner_icon"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingStart="36dp"
+ android:paddingEnd="4dp"
+ android:src="@drawable/tuner"
+ android:tint="?android:attr/textColorTertiary"
+ android:visibility="invisible"/>
+
+ </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+ </LinearLayout>
</LinearLayout>
</com.android.systemui.qs.QSFooterImpl>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 5bcb7fd..1dab761 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -33,7 +33,7 @@
<View
android:id="@+id/quick_settings_status_bar_background"
android:layout_width="match_parent"
- android:layout_height="@dimen/qs_header_system_icons_area_height"
+ android:layout_height="@*android:dimen/quick_qs_offset_height"
android:clipToPadding="false"
android:clipChildren="false"
android:background="#ff000000" />
@@ -43,7 +43,7 @@
android:id="@+id/quick_settings_gradient_view"
android:layout_width="match_parent"
android:layout_height="126dp"
- android:layout_marginTop="@dimen/qs_header_system_icons_area_height"
+ android:layout_marginTop="@*android:dimen/quick_qs_offset_height"
android:clipToPadding="false"
android:clipChildren="false"
android:background="@drawable/qs_bg_gradient" />
@@ -51,7 +51,7 @@
<com.android.systemui.qs.QSPanel
android:id="@+id/quick_settings_panel"
- android:layout_marginTop="@dimen/qs_header_system_icons_area_height"
+ android:layout_marginTop="@*android:dimen/quick_qs_offset_height"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="48dp"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index dacc3f9..cc79d0d 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -20,7 +20,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/header"
android:layout_width="match_parent"
- android:layout_height="@dimen/status_bar_header_height"
+ android:layout_height="@*android:dimen/quick_qs_total_height"
android:layout_gravity="@integer/notification_panel_layout_gravity"
android:baselineAligned="false"
android:clickable="false"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index 2c69501..f38129f 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -19,7 +19,7 @@
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/quick_status_bar_system_icons"
android:layout_width="match_parent"
- android:layout_height="@dimen/qs_header_system_icons_area_height"
+ android:layout_height="@*android:dimen/quick_qs_offset_height"
android:layout_alignParentEnd="true"
android:clipChildren="false"
android:clipToPadding="false"
diff --git a/packages/SystemUI/res/layout/recent_apps.xml b/packages/SystemUI/res/layout/recent_apps.xml
index c84d280..6b08cea 100644
--- a/packages/SystemUI/res/layout/recent_apps.xml
+++ b/packages/SystemUI/res/layout/recent_apps.xml
@@ -23,8 +23,8 @@
android:layout_weight="0"
android:scaleType="fitCenter"
android:contentDescription="@string/accessibility_recent"
- android:paddingTop="15dp"
- android:paddingBottom="15dp"
+ android:paddingTop="@dimen/home_padding"
+ android:paddingBottom="@dimen/home_padding"
android:paddingStart="@dimen/navigation_key_padding"
android:paddingEnd="@dimen/navigation_key_padding"
/>
diff --git a/packages/SystemUI/res/layout/rounded_corners.xml b/packages/SystemUI/res/layout/rounded_corners.xml
index d1ef5d6..734c877 100644
--- a/packages/SystemUI/res/layout/rounded_corners.xml
+++ b/packages/SystemUI/res/layout/rounded_corners.xml
@@ -22,7 +22,7 @@
android:id="@+id/left"
android:layout_width="12dp"
android:layout_height="12dp"
- android:layout_gravity="left"
+ android:layout_gravity="left|top"
android:tint="#ff000000"
android:src="@drawable/rounded" />
<ImageView
@@ -30,6 +30,6 @@
android:layout_width="12dp"
android:layout_height="12dp"
android:tint="#ff000000"
- android:layout_gravity="right"
+ android:layout_gravity="right|bottom"
android:src="@drawable/rounded" />
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
index c2b1009..a3118b0 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
@@ -84,7 +84,25 @@
android:layout_height="@dimen/screen_pinning_request_button_height"
android:layout_weight="0"
android:paddingStart="@dimen/screen_pinning_request_frame_padding"
- android:paddingEnd="@dimen/screen_pinning_request_frame_padding" >
+ android:paddingEnd="@dimen/screen_pinning_request_frame_padding"
+ android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
+
+ <ImageView
+ android:id="@+id/screen_pinning_home_bg_light"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="matrix"
+ android:src="@drawable/screen_pinning_light_bg_circ" />
+
+ <ImageView
+ android:id="@+id/screen_pinning_home_bg"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingEnd="@dimen/screen_pinning_request_inner_padding"
+ android:paddingStart="@dimen/screen_pinning_request_inner_padding"
+ android:paddingTop="@dimen/screen_pinning_request_inner_padding"
+ android:scaleType="matrix"
+ android:src="@drawable/screen_pinning_bg_circ" />
<ImageView
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 117cd14..53dff05 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -59,6 +59,7 @@
android:gravity="center"
android:layout_gravity="end"
android:translationZ="8dp"
+ android:clickable="true"
android:orientation="vertical" >
<TextView
@@ -76,7 +77,7 @@
android:id="@+id/ringer_icon"
style="@style/VolumeButtons"
android:background="?android:selectableItemBackgroundBorderless"
- android:layout_width="@dimen/volume_button_size"
+ android:layout_width="@dimen/volume_dialog_panel_width"
android:layout_height="@dimen/volume_button_size"
android:tint="?android:attr/colorAccent"
android:soundEffectsEnabled="false" />
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index 1d1f95b..a9e5adf 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -61,7 +61,9 @@
android:layout_width="24dp"
android:layout_height="24dp"
android:background="?android:selectableItemBackgroundBorderless"
+ android:contentDescription="@string/accessibility_output_chooser"
style="@style/VolumeButtons"
+ android:clickable="false"
android:layout_centerVertical="true"
android:src="@drawable/ic_swap"
android:soundEffectsEnabled="false" />
@@ -69,7 +71,7 @@
</LinearLayout>
<FrameLayout
android:id="@+id/volume_row_slider_frame"
- android:padding="10dp"
+ android:padding="0dp"
android:layout_width="@dimen/volume_dialog_panel_width"
android:layout_height="150dp">
<SeekBar
@@ -79,8 +81,6 @@
android:layout_width="150dp"
android:layout_height="@dimen/volume_dialog_panel_width"
android:layout_gravity="center"
- android:focusable="true"
- android:focusableInTouchMode="true"
android:rotation="270" />
</FrameLayout>
@@ -90,6 +90,7 @@
android:padding="10dp"
android:layout_width="@dimen/volume_button_size"
android:layout_height="@dimen/volume_button_size"
+ android:background="?android:selectableItemBackgroundBorderless"
android:soundEffectsEnabled="false" />
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 8b2ab81..5242029 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Tuis"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Kieslys"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Toeganklikheid"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Draai skerm"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Oorsig"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Deursoek"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"maak kamera oop"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Kies nuwe taakuitleg"</string>
<string name="cancel" msgid="6442560571259935130">"Kanselleer"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Versoenbaarheid-zoem se knoppie."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoem kleiner na groter skerm."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth gekoppel."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Luitoestel stil."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Werkmodus"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Maak <xliff:g id="APP">%s</xliff:g> toe."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwerp."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle onlangse programme is toegemaak."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> toestelle)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth af"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Geen saamgebinde toestelle beskikbaar nie"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batterykrag"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Oudio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Kopstuk"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Invoer"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Helderheid"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Outo-draai"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Outodraai skerm"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Koppel tans …"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"USB-verbinding"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Warmkol"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Kennisgewings"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flitslig"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiele data"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> gebruik"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g>-limiet"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> waarskuwing"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Werkmodus"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Aandbeligting"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Aan by sonsondergang"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Tot sonsopkoms"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is gedeaktiveer"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is geaktiveer"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is in veiligmodus gedeaktiveer."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Vee alles uit"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Trek hier om verdeelde skerm te gebruik"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Verdeel horisontaal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verdeel vertikaal"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Verdeel gepasmaak"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Met kragkennisgewingkontroles kan jy \'n belangrikheidvlak van 0 tot 5 vir \'n program se kennisgewings stel. \n\n"<b>"Vlak 5"</b>" \n- Wys aan die bokant van die kennisgewinglys \n- Laat volskermonderbreking toe \n- Wys altyd opspringkennisgewings \n\n"<b>"Vlak 4"</b>" \n- Verhoed volskermonderbreking \n- Wys altyd opspringkennisgewings \n\n"<b>"Vlak 3"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n\n"<b>"Vlak 2"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n- Moet nooit \'n klank maak of vibreer nie \n\n"<b>"Vlak 1"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n- Moet nooit \'n klank maak of vibreer nie \n- Versteek van sluitskerm en statusbalk \n- Wys aan die onderkant van die kennisgewinglys \n\n"<b>"Vlak 0"</b>" \n- Blokkeer alle kennisgewings van die program af"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Kennisgewings"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Jy sal nie meer hierdie kennisgewings sien nie"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Hou aan om hierdie kennisgewings te wys?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Stop kennisgewings"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Hou aan wys"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Knipbord"</item>
<item msgid="5742013440802239414">"Sleutelkode"</item>
<item msgid="8802889973626281575">"Sleutelbordwisselaar"</item>
- <item msgid="8175437057325747277">"Geen"</item>
+ <item msgid="7095517796293767867">"Rotasievoorstel"</item>
+ <item msgid="8494159969042135235">"Geen"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normaal"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tik vir besonderhede oor battery- en datagebruik"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Skakel mobiele data af?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Instellings kan nie jou antwoord verifieer nie omdat \'n program \'n toestemmingversoek verberg."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Laat <xliff:g id="APP_0">%1$s</xliff:g> toe om <xliff:g id="APP_2">%2$s</xliff:g>-skyfies te wys?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Dit kan inligting van <xliff:g id="APP">%1$s</xliff:g> af lees"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Dit kan handelinge binne <xliff:g id="APP">%1$s</xliff:g> uitvoer"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Laat <xliff:g id="APP">%1$s</xliff:g> toe om skyfies uit enige program te gebruik"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Laat toe"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Weier"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e548cae..f08c71e 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"መነሻ"</string>
<string name="accessibility_menu" msgid="316839303324695949">"ምናሌ"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"ተደራሽነት"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"ማያ ገጹን አዙር"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"አጠቃላይ ዕይታ"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ፈልግ"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ካሜራ"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"ካሜራ ክፈት"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"የአዲስ ተግባር አቀማመጥን ይምረጡ"</string>
<string name="cancel" msgid="6442560571259935130">"ይቅር"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"የተኳኋኝአጉላ አዝራር።"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"አነስተኛውን ማያ ወደ ትልቅ አጉላ።"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ብሉቱዝ ተያይዟል።"</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"የስልክ ጥሪ ፀጥታ።"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"የሥራ ሁነታ"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> አስወግድ።"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ተሰናብቷል::"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ሁሉም የቅርብ ጊዜ ማመልከቻዎች ተሰናብተዋል።"</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ብሉቱዝ (<xliff:g id="NUMBER">%d</xliff:g> መሣሪያዎች)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ብሉቱዝ ጠፍቷል"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"ምንም የተጣመሩ መሣሪያዎች አይገኝም"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ባትሪ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ኦዲዮ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"ማዳመጫ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ግቤት"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ብሩህነት"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"በራስ ሰር አሽከርክር"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"ማያ ገጽን በራስ-አሽከርክር"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"በማገናኘት ላይ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"በማገናኘት ላይ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"መገናኛ ነጥብ"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"ማሳወቂያዎች"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"የባትሪ ብርሃን"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ጥቅም ላይ ውሏል"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ገደብ"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"የ<xliff:g id="DATA_LIMIT">%s</xliff:g> ማስጠንቀቂያ"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"የሥራ ሁነታ"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"የምሽት ብርሃን"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"ጸሐይ ስትጠልቅ ይበራል"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"ጸሐይ እስክትወጣ ድረስ"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> ላይ ይበራል"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"እስከ <xliff:g id="TIME">%s</xliff:g> ድረስ"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"ኤንኤፍሲ"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"ኤንኤፍሲ ተሰናክሏል"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"ኤንኤፍሲ ነቅቷል"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> በጥንቃቄ ሁነታ ውስጥ ታግዷል።"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"ሁሉንም አጽዳ"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"የተከፈለ ማያ ገጽን ለመጠቀም እዚህ ላይ ይጎትቱ"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"አግድም ክፈል"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ቁልቁል ክፈል"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"በብጁ ክፈል"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"በኃይል ማሳወቂያ መቆጣጠሪያዎች አማካኝነት የአንድ መተግበሪያ ማሳወቂያዎች የአስፈላጊነት ደረጃ ከ0 እስከ 5 ድረስ ማዘጋጀት ይችላሉ። \n\n"<b>"ደረጃ 5"</b>" \n- በማሳወቂያ ዝርዝሩ አናት ላይ አሳይ \n- የሙሉ ማያ ገጽ ማቋረጥን ፍቀድ \n- ሁልጊዜ አጮልቀው ይመልከቱ \n\n"<b>"ደረጃ 4"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ከልክል \n- ሁልጊዜ አጮልቀው ይመልከቱ \n\n"<b>"ደረጃ 3"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ከልክል \n- በፍጹም አጮልቀው አይምልከቱ \n\n"<b>"ደረጃ 2"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ይከልክሉ \n- በፍጹም አጮልቀው አይመልከቱ \n- ድምፅ እና ንዝረትን በፍጹም አይኑር \n\n"<b>"ደረጃ 1"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ይከልክሉ \n- በፍጹም አጮልቀው አይመልከቱ \n- ድምፅ ወይም ንዝረትን በፍጹም አያደርጉ \n- ከመቆለፊያ ገጽ እና የሁኔታ አሞሌ ይደብቁ \n- በማሳወቂያ ዝርዝር ግርጌ ላይ አሳይ \n\n"<b>"ደረጃ 0"</b>" \n- ሁሉንም የመተግበሪያው ማሳወቂያዎች ያግዱ"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"ማሳወቂያዎች"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"እነዚህን ማሳወቂያዎችን ከእንግዲህ አይመለከቷቸውም"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"እነዚህን ማሳወቂያዎች ማሳየት ይቀጥሉ?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"ማሳወቂያዎችን አስቁም"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"ማሳየትን ቀጥል"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"የቅንጥብ ሰሌዳ"</item>
<item msgid="5742013440802239414">"የቁልፍ ኮድ"</item>
<item msgid="8802889973626281575">"የቁልፍ ሰሌዳ መቀየሪያ"</item>
- <item msgid="8175437057325747277">"ምንም የለም"</item>
+ <item msgid="7095517796293767867">"የማዞር አስተያየት ጥቆማ"</item>
+ <item msgid="8494159969042135235">"ምንም"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"መደበኛ"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"በባትሪ እና ውሂብ አጠቃቀም ላይ ዝርዝሮችን ለማግኘት መታ ያድርጉ"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"የተንቀሳቃሽ ስልክ ውሂብ ይጥፋ?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"አንድ መተግበሪያ የፍቃድ ጥያቄ እያገደ ስለሆነ ቅንብሮች ጥያቄዎን ማረጋገጥ አይችሉም።"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> የ<xliff:g id="APP_2">%2$s</xliff:g> ቁራጮችን እንዲያሳይ ይፈቀድለት?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- ከ<xliff:g id="APP">%1$s</xliff:g> የመጣ መረጃን ማንበብ ይችላል"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- በ<xliff:g id="APP">%1$s</xliff:g> ውስጥ እርምጃዎችን መውሰድ ይችላል"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> ከማንኛውም መተግበሪያ የመጡ ቁራጮችን እንዲያሳይ ፍቀድለት"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"ፍቀድ"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"ከልክል"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index a2a0f06..1087b99 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -92,6 +92,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"الرئيسية"</string>
<string name="accessibility_menu" msgid="316839303324695949">"القائمة"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"إمكانية الوصول"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"تدوير الشاشة"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"النظرة عامة"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"بحث"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"الكاميرا"</string>
@@ -106,6 +107,12 @@
<string name="camera_label" msgid="7261107956054836961">"فتح الكاميرا"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"تحديد تنسيق جديد للمهمة"</string>
<string name="cancel" msgid="6442560571259935130">"إلغاء"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"زر تكبير/تصغير للتوافق."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"استخدام التكبير/التصغير لتحويل شاشة صغيرة إلى شاشة أكبر"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"تم توصيل البلوتوث."</string>
@@ -182,7 +189,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"رنين صامت."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"وضع العمل"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"إزالة <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"تمت إزالة <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"تم تجاهل كل التطبيقات المستخدمة مؤخرًا."</string>
@@ -283,6 +291,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوتوث (<xliff:g id="NUMBER">%d</xliff:g> من الأجهزة)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"إيقاف البلوتوث"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"لا يتوفر أي أجهزة مقترنة"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"مستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"صوت"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"سماعة الرأس"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"الإدخال"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"السطوع"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"دوران تلقائي"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"التدوير التلقائي للشاشة"</string>
@@ -323,6 +335,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"جارٍ الاتصال..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"النطاق"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"نقطة اتصال"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"الإشعارات"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"الفلاش"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"بيانات الجوّال"</string>
@@ -332,8 +347,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> مستخدَمة"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"قيد <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"تحذير <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"وضع العمل"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"إضاءة ليلية"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"تفعيل عند غروب الشمس"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"حتى شروق الشمس"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"تفعيل الإعداد في <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"حتى <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"الاتصال القريب المدى (NFC)"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"تم تعطيل الاتصال القريب المدى"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"تم تمكين الاتصال القريب المدى"</string>
@@ -346,6 +368,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"تم تعطيل <xliff:g id="APP">%s</xliff:g> في الوضع الآمن."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"مسح الكل"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"اسحب هنا لاستخدام وضع تقسيم الشاشة"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"تقسيم أفقي"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"تقسيم رأسي"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"تقسيم مخصص"</string>
@@ -570,6 +594,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"باستخدام عناصر التحكم في إشعار التشغيل، يمكنك تعيين مستوى الأهمية من 0 إلى 5 لإشعارات التطبيق. \n\n"<b>"المستوى 5"</b>" \n- العرض أعلى قائمة الإشعارات \n- يسمح بمقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 4"</b>" \n- منع مقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 3"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n\n"<b>"المستوى 2"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات واهتزاز \n\n"<b>"المستوى 1"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات أو اهتزاز أبدًا \n- الإخفاء من شاشة التأمين وشريط الحالة \n- العرض أسفل قائمة الإشعارات \n\n"<b>"المستوى 0"</b>" \n- حظر جميع الإشعارات من التطبيق"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"الإشعارات"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"لن تتلقى هذه الإشعارات بعد الآن."</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"هل تريد الاستمرار في تلقي هذه الإشعارات؟"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"إيقاف الإشعارات"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"الاستمرار في تلقّي الإشعارات"</string>
@@ -672,7 +698,8 @@
<item msgid="1545641631806817203">"الحافظة"</item>
<item msgid="5742013440802239414">"رمز المفتاح"</item>
<item msgid="8802889973626281575">"مفتاح تبديل لوحة المفاتيح"</item>
- <item msgid="8175437057325747277">"بدون"</item>
+ <item msgid="7095517796293767867">"اقتراح حول أزرار التنقل"</item>
+ <item msgid="8494159969042135235">"بدون"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"عادي"</item>
@@ -796,4 +823,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"انقر للحصول على تفاصيل حول البطارية واستخدام البيانات"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"هل تريد إيقاف تشغيل بيانات الجوال؟"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"لا يمكن للإعدادات التحقق من ردك لأن هناك تطبيقًا يحجب طلب الإذن."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"هل تريد السماح لتطبيق <xliff:g id="APP_0">%1$s</xliff:g> بعرض شرائح <xliff:g id="APP_2">%2$s</xliff:g>؟"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- يستطيع قراءة المعلومات من <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- يستطيع اتخاذ إجراءات داخل <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"السماح لتطبيق <xliff:g id="APP">%1$s</xliff:g> بعرض شرائح من أي تطبيق"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"سماح"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"رفض"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index e73cc86..17d7718 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Ana səhifə"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menyu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Əlçatımlılıq"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Ekranı fırladın"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"İcmal"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Axtar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"kemaranı açın"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Yeni tapşırıq sxemi seçin"</string>
<string name="cancel" msgid="6442560571259935130">"Ləğv et"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Uyğunluq zoom düyməsi."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Daha böyük ekranda uzaqlaşdır."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth qoşulub."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Zəngvuran səssiz."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"İş rejimi"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> kənarlaşdırın."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> çıxarıldı."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Bütün son tətbiqlər kənarlaşdırıldı."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Cihaz)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth bağlıdır"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Heç bir cütlənmiş cihaz əlçatan deyil"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batareya"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Qulaqlıq"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Giriş"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Parlaqlıq"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Avtodönüş"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Ekran avtodönüşü"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Qoşulur..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Birləşmə"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirişlər"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"İşartı"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobil data"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> işlənib"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> limit"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> xəbərdarlığı"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"İş rejimi"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"İş profili"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Bildiriş və tətbiqlər deaktivdir"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Gecə işığı"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Qürubda aktiv ediləcək"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Şəfəq vaxtına qədər"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> olduqda aktiv ediləcək"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> vaxtına qədər"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC deaktiv edilib"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC aktiv edilib"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> güvənli rejimdə deaktiv edildi."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Hamısını silin"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Ekranı bölmək üçün bura sürüşdürün"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Tətbiqi dəyişmək üçün yuxarı sürüşdürün"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Üfüqi Böl"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Şaquli Böl"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Fərdi Böl"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Enerji bildiriş nəzarəti ilə, tətbiq bildirişləri üçün əhəmiyyət səviyyəsini 0-dan 5-ə kimi ayarlaya bilərsiniz. \n\n"<b>"Səviyyə 5"</b>" \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n- Tam ekran kəsintisinə icazə verin \n- Hər zaman izləyin \n\n"<b>"Səviyyə 4"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Hər zaman izləyin \n\n"<b>"Level 3"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n\n"<b>"Level 2"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n\n"<b>"Səviyyə 1"</b>" \n- Prevent full screen interruption \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n- Ekran kilidi və ya status panelindən gizlədin \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n\n"<b>"Səviyyə 0"</b>" \n- Bütün bildirişləri tətbiqdən blok edin"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirişlər"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Artıq bu bildirişləri görməyəcəkəsiniz"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Bu bildirişlər göstərilməyə davam edilsin?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Bildirişləri dayandırın"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Göstərməyə davam edin"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Mübadilə buferi"</item>
<item msgid="5742013440802239414">"Açar kodu"</item>
<item msgid="8802889973626281575">"Klaviatura dəyişdirici"</item>
- <item msgid="8175437057325747277">"Heç bir"</item>
+ <item msgid="7095517796293767867">"Naviqasiya təklifləri"</item>
+ <item msgid="8494159969042135235">"Yoxdur"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Batareya və data istifadəsi haqqında ətraflı məlumat üçün klikləyin"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Mobil data söndürülsün?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Tətbiq icazə sorğusunu gizlətdiyi üçün Ayarlar cavabınızı doğrulaya bilməz."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> tətbiqinə <xliff:g id="APP_2">%2$s</xliff:g> hissələrini göstərmək üçün icazə verilsin?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- <xliff:g id="APP">%1$s</xliff:g> tətbiqindən məlumat oxuya bilər"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- <xliff:g id="APP">%1$s</xliff:g> daxilində əməliyyatlar edə bilər"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> tətbiqinə istənilən tətbiqdən hissə göstərmək icazəsi verin"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"İcazə verin"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Rədd edin"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 3c203b1..9c188ff 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -89,6 +89,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Početna"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Meni"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Pristupačnost"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rotirajte ekran"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Pregled"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Pretražite"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -103,6 +104,12 @@
<string name="camera_label" msgid="7261107956054836961">"otvori kameru"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Izaberi novi raspored zadataka"</string>
<string name="cancel" msgid="6442560571259935130">"Otkaži"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Dugme Zum kompatibilnosti."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zumiranje sa manjeg na veći ekran."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth je priključen."</string>
@@ -179,7 +186,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Nečujno zvono."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Režim rada"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbacite <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> je odbačena."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Sve nedavno korišćene aplikacije su odbačene."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> uređaja)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth isključen"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nije dostupan nijedan upareni uređaj"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Slušalice"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Unos"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Osvetljenost"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatska rotacija"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatsko rotiranje ekrana"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Povezuje se..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Povezivanje"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obaveštenja"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampa"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilni podaci"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Iskoristili ste <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ograničenje od <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje za <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Režim rada"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noćno svetlo"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Uključuje se po zalasku sunca"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Do izlaska sunca"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je onemogućen"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je omogućen"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacija <xliff:g id="APP">%s</xliff:g> je onemogućena u bezbednom režimu."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Obriši sve"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Prevucite ovde da biste koristili razdeljeni ekran"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podeli horizontalno"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podeli vertikalno"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Prilagođeno deljenje"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Pomoću naprednih kontrola za obaveštenja možete da podesite nivo važnosti od 0. do 5. za obaveštenja aplikacije. \n\n"<b>"5. nivo"</b>" \n– Prikazuju se u vrhu liste obaveštenja \n- Dozvoli prekid režima celog ekrana \n– Uvek zaviruj \n\n"<b>"4. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Uvek zaviruj \n\n"<b>"3. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n\n"<b>"2. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n– Nikada ne proizvodi zvuk ili vibraciju \n\n"<b>"1. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n– Nikada ne proizvodi zvuk ili vibraciju \n– Sakrij na zaključanom ekranu i statusnoj traci \n– Prikazuju se u dnu liste obaveštenja \n\n"<b>"0. nivo"</b>" \n– Blokiraj sva obaveštenja iz aplikacije"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Obaveštenja"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Više nećete videti ova obaveštenja"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Želite li da se ova obaveštenja i dalje prikazuju?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Prestani da prikazuješ obaveštenja"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Nastavi da prikazuješ"</string>
@@ -660,7 +686,8 @@
<item msgid="1545641631806817203">"Memorija"</item>
<item msgid="5742013440802239414">"Kôd tastera"</item>
<item msgid="8802889973626281575">"Prebacivač za tastaturu"</item>
- <item msgid="8175437057325747277">"Ništa"</item>
+ <item msgid="7095517796293767867">"Predlog za rotaciju"</item>
+ <item msgid="8494159969042135235">"Ništa"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normalni"</item>
@@ -784,4 +811,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Dodirnite za detalje o bateriji i potrošnji podataka"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Želite da onemogućite mobilne podatke?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Podešavanja ne mogu da verifikuju vaš odgovor jer aplikacija skriva zahtev za dozvolu."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Želite li da dozvolite aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> da prikazuje isečke iz aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Može da čita podatke iz aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Može da obavlja radnje u aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Dozvolite aplikaciji <xliff:g id="APP">%1$s</xliff:g> da prikazuje isečke iz bilo koje aplikacije"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Dozvoli"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Odbij"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 41ce823..6115de3 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -80,7 +80,7 @@
<string name="screenshot_saved_text" msgid="7574667448002050363">"Дакраніцеся, каб прагледзець здымак экрана"</string>
<string name="screenshot_failed_title" msgid="9096484883063264803">"Не атрымалася зрабіць здымак экрана"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Падчас захавання здымка экрана адбылася памылка"</string>
- <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Немагчыма захаваць здымак экрана, бо мала месца ў сховішчу"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Немагчыма захаваць здымак экрана, бо мала месца ў сховішчы"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Парам. перадачы файлаў па USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Падлучыць як медыяпрайгравальнік (ССП)"</string>
@@ -90,6 +90,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"На Галоўную старонку"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Меню"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Спецыяльныя магчымасці"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Павярнуць экран"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Агляд"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Пошук"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
@@ -104,6 +105,12 @@
<string name="camera_label" msgid="7261107956054836961">"адкрыць камеру"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Выберыце новы макет заданняў"</string>
<string name="cancel" msgid="6442560571259935130">"Скасаваць"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка сумяшчальнасці маштаба."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Маштабаванне малых элементаў для большага экрана."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-сувязь."</string>
@@ -182,7 +189,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Маўклівы выклік."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Рэжым працы"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Выдаліць <xliff:g id="APP">%s</xliff:g> са спіса апошніх."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> выдалены."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Усе апошнія праграмы адхілены."</string>
@@ -281,6 +289,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (прылады: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth выключаны"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Няма даступных спалучаных прылад"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Узровень зараду: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Гук"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Гарнітура"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Увод"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яркасць"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Аўтапаварот"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Аўтаматычны паварот экрана"</string>
@@ -321,6 +333,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Падлучэнне..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Мадэм"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Кропка доступу"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Апавяшчэнні"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ліхтарык"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мабільная перадача даных"</string>
@@ -330,8 +345,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Выкарыстана <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ліміт <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Папярэджанне: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Рэжым працы"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Начная падсветка"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Уключаць увечары"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Да ўсходу сонца"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Уключыць у <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Да <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC адключаны"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC уключаны"</string>
@@ -344,6 +366,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> адключана ў бяспечным рэжыме."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Ачысціць усё"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Перацягніце сюды, каб перайсці ў рэжым падзеленага экрана"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Падзяліць гарызантальна"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Падзяліць вертыкальна"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Падзяліць іншым чынам"</string>
@@ -567,12 +591,14 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Выключана"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"З дапамогай пашыранага кіравання апавяшчэннямі вы можаце задаваць узровень важнасці апавяшчэнняў праграмы ад 0 да 5. \n\n"<b>"Узровень 5"</b>" \n- Паказваць уверсе спіса апавяшчэнняў \n- Дазваляць перапыняць рэжым поўнага экрана \n- Заўсёды дазваляць кароткі паказ \n\n"<b>"Узровень 4"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Заўсёды дазваляць кароткі паказ \n\n"<b>"Узровень 3"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n\n"<b>"Узровень 2"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n- Ніколі не прайграваць гук і не вібрыраваць \n\n"<b>"Узровень 1"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n- Ніколі не прайграваць гук і не вібрыраваць \n- Хаваць з экрана блакіроўкі і панэлі стану \n- Паказваць унізе спіса апавяшчэнняў \n\n"<b>"Узровень 0"</b>" \n- Блакіраваць усе апавяшчэнні ад праграмы"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Апавяшчэнні"</string>
- <string name="notification_channel_disabled" msgid="344536703863700565">"Вы больш не будзеце бачыць гэты апавяшчэнні"</string>
+ <string name="notification_channel_disabled" msgid="344536703863700565">"Вы больш не будзеце бачыць гэтыя апавяшчэнні"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Працягваць паказваць гэтыя апавяшчэнні?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Спыніць апавяшчэнні"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Працягваць паказваць"</string>
<string name="inline_keep_showing_app" msgid="1723113469580031041">"Працягваць паказваць апавяшчэнні гэтай праграмы?"</string>
- <string name="notification_unblockable_desc" msgid="1037434112919403708">"Немагчыма адключыць гэты апавяшчэнні"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"Немагчыма адключыць гэтыя апавяшчэнні"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Кіраванне апавяшчэннямі для <xliff:g id="APP_NAME">%1$s</xliff:g> адкрыта"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Кіраванне апавяшчэннямі для <xliff:g id="APP_NAME">%1$s</xliff:g> закрыта"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Дазволіць апавяшчэнні з гэтага канала"</string>
@@ -666,7 +692,8 @@
<item msgid="1545641631806817203">"Буфер абмену"</item>
<item msgid="5742013440802239414">"Код клавішы"</item>
<item msgid="8802889973626281575">"Пераключальнік клавіятуры"</item>
- <item msgid="8175437057325747277">"Няма"</item>
+ <item msgid="7095517796293767867">"Паварот"</item>
+ <item msgid="8494159969042135235">"Няма"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Звычайная"</item>
@@ -790,4 +817,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Дакраніцеся, каб даведацца пра выкарыстанне трафіка і акумулятара"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Выключыць мабільную перадачу даных?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Праграма хавае запыт на дазвол, таму ваш адказ немагчыма спраўдзіць у Наладах."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Дазволіць праграме <xliff:g id="APP_0">%1$s</xliff:g> паказваць зрэзы праграмы <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Можа счытваць інфармацыю з праграмы <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Можа выконваць дзеянні ў праграме <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Дазволіць праграме <xliff:g id="APP">%1$s</xliff:g> паказваць зрэзы з усіх праграм"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Дазволіць"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Адмовіць"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index fbdf93c..2a5ee20 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Начало"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Меню"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Достъпност"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Завъртане на екрана"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Общ преглед"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Търсене"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"отваряне на камерата"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Избиране на ново оформление за задачите"</string>
<string name="cancel" msgid="6442560571259935130">"Отказ"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Бутон за промяна на мащаба с цел съвместимост."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Промяна на мащаба на екрана от по-малък до по-голям."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth е включен."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Звънът е заглушен."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Работен режим"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отхвърляне на <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложението <xliff:g id="APP">%s</xliff:g> е отхвърлено."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Всички скорошни приложения са отхвърлени."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> устройства)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth е изключен"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Няма налични сдвоени устройства"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Аудио"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Слушалки"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Вход"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яркост"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоматична ориентация"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Автоматично завъртане на екрана"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Установява се връзка..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Тетъринг"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка за достъп"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Известия"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Фенерче"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилни данни"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Използвано: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ограничение от <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Работен режим"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Нощно осветление"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Ще се вкл. по залез"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"До изгрев"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ще се включи в <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"КБП"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"КБП е деактивирана"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"КБП е активирана"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Приложението <xliff:g id="APP">%s</xliff:g> е деактивирано в безопасния режим."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Изчистване на всичко"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Преместете тук с плъзгане, за да използвате режим за разделен екран"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Хоризонтално разделяне"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Вертикално разделяне"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Персонализирано разделяне"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"С помощта на контролите за известията можете да зададете ниво на важност от 0 до 5 за известията от дадено приложение. \n\n"<b>"Ниво 5"</b>" \n– Показване най-горе в списъка с известия. \n– Разрешаване на прекъсването на цял екран. \n– Известията винаги се показват мимолетно. \n\n"<b>"Ниво 4"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията винаги се показват мимолетно. \n\n"<b>"Ниво 3"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n\n"<b>"Ниво 2"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n– Без издаване на звуков сигнал и вибриране. \n\n"<b>"Ниво 1"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n– Без издаване на звуков сигнал и вибриране. \n– Скриване от заключения екран и лентата на състоянието. \n– Показване най-долу в списъка с известия. \n\n"<b>"Ниво 0"</b>" \n– Блокиране на всички известия от приложението."</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Известия"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Вече няма да виждате тези известия"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Тези известия да продължат ли да се показват?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Спиране на известията"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Да продължат да се показват"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Буферна памет"</item>
<item msgid="5742013440802239414">"Клавишен код"</item>
<item msgid="8802889973626281575">"Превключвател на клавиатурата"</item>
- <item msgid="8175437057325747277">"Няма"</item>
+ <item msgid="7095517796293767867">"Предложение за завъртане"</item>
+ <item msgid="8494159969042135235">"Без"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Нормално"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Докоснете за информация относно използването на батерията и преноса на данни"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Да се изключат ли мобилните данни?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"От Настройки не може да се получи потвърждение за отговора ви, защото заявката за разрешение се прикрива от приложение."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Искате ли да разрешите на <xliff:g id="APP_0">%1$s</xliff:g> да показва части от <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Може да чете информация от <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Може да предприема действия в/ъв <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Разрешаване на <xliff:g id="APP">%1$s</xliff:g> да показва части от което и да е приложение"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Разрешаване"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Отказ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index a8e0c2b..4cbb5ed 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -33,13 +33,10 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"চলতে-থাকা"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"বিজ্ঞপ্তিগুলি"</string>
<string name="battery_low_title" msgid="6456385927409742437">"ব্যাটারি কম"</string>
- <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
- <skip />
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"চার্জ কম। ব্যাটারি সেভার চালু করুন"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে"</string>
- <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
- <skip />
- <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
- <skip />
+ <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকি আছে, বর্তমান ব্যবহারের ভিত্তিতে আর <xliff:g id="TIME">%s</xliff:g> চলবে"</string>
+ <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকি আছে, আর <xliff:g id="TIME">%s</xliff:g> চলবে"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে। ব্যাটারি সেভার চালু আছে।"</string>
<string name="invalid_charger" msgid="4549105996740522523">"USB চার্জিং সমর্থিত নয়৷\nকেবলমাত্র সরবহারকৃত চার্জার ব্যবহার করুন৷"</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"USB চার্জিং সমর্থিত নয়।"</string>
@@ -73,22 +70,15 @@
<string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ব্যবহারকারী এখন এই ডিভাইসে সাইন-ইন করেছেন তাই USB ডিবাগিং চালু করা যাবে না। এই বৈশিষ্ট্যটি ব্যবহার করতে, প্রাথমিক ব্যবহারকারীতে পাল্টে নিন।"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"স্ক্রীণ পূরণ করতে জুম করুন"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"ফুল স্ক্রিন করুন"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"স্ক্রিনশট নিন"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
- <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
- <skip />
- <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
- <skip />
- <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
- <skip />
- <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
- <skip />
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"স্ক্রিনশট সেভ করা হচ্ছে"</string>
+ <string name="screenshot_saved_title" msgid="5637073968117370753">"স্ক্রিনশট সেভ করা হয়েছে"</string>
+ <string name="screenshot_saved_text" msgid="7574667448002050363">"স্ক্রিনশটটি দেখতে ট্যাপ করুন"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"স্ক্রিনশট নেওয়া যায়নি"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"স্ক্রিনশট সেভ করার সময় সমস্যা হয়েছে"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"বেশি জায়গা নেই তাই স্ক্রিনশটটি সেভ করা যাবে না৷"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ফাইল স্থানান্তরের বিকল্পগুলি"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"একটি মিডিয়া প্লেয়ার হিসেবে মাউন্ট করুন (MTP)"</string>
@@ -98,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"হোম"</string>
<string name="accessibility_menu" msgid="316839303324695949">"মেনু"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"অ্যাক্সেসযোগ্যতা"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"স্ক্রিন ঘোরান"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"এক নজরে"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"খুঁজুন"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ক্যামেরা"</string>
@@ -112,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"ক্যামেরা খুলুন"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"নতুন কার্য লেআউট বেছে নিন"</string>
<string name="cancel" msgid="6442560571259935130">"বাতিল করুন"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"সামঞ্জস্যের জুম বোতাম৷"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ছোট থেকে বৃহৎ স্ক্রীণে জুম করুন৷"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ব্লুটুথ সংযুক্ত হয়েছে৷"</string>
@@ -188,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"রিং বাজানো বন্ধ করুন৷"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"কাজের মোড"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> খারিজ করুন।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> খারিজ করা হয়েছে৷"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"সমস্ত সাম্প্রতিক অ্যাপ্লিকেশন খারিজ করা হয়েছে।"</string>
@@ -285,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ব্লুটুথ (<xliff:g id="NUMBER">%d</xliff:g> টি ডিভাইস)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ব্লুটুথ বন্ধ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"চেনা কোনও ডিভাইস নেই"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"অডিও"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"হেডসেট"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ইনপুট"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"উজ্জ্বলতা"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"স্বতঃ ঘূর্ণায়মান"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"স্বতঃ-ঘূর্ণায়মান স্ক্রিন"</string>
@@ -325,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"সংযুক্ত হচ্ছে..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"টেদারিং"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"হটস্পট"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"বিজ্ঞপ্তিগুলি"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ফ্ল্যাশলাইট"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"মোবাইল ডেটা"</string>
@@ -334,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ব্যবহৃত হয়েছে"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"সীমা <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> সতর্কতা"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"কাজের মোড"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"নাইট লাইট"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"সূর্যাস্তে চালু হবে"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"সূর্যোদয় পর্যন্ত"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> এ চালু হবে"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> পর্যন্ত"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC অক্ষম করা আছে"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC সক্ষম করা আছে"</string>
@@ -348,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"নিরাপদ মোডে <xliff:g id="APP">%s</xliff:g> অক্ষম করা হয়েছে৷"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"সবকিছু সাফ করুন"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"বিভক্ত স্ক্রীন ব্যবহার করতে এখানে টেনে আনুন"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"অনুভূমিক স্প্লিট"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"উল্লম্ব স্প্লিট"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"কাস্টম স্প্লিট করুন"</string>
@@ -571,27 +585,21 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"বন্ধ আছে"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"পাওয়ার বিজ্ঞপ্তির নিয়ন্ত্রণগুলি ব্যহবার করে, আপনি কোনও অ্যাপ্লিকেশনের বিজ্ঞপ্তির জন্য ০ থেকে ৫ পর্যন্ত একটি গুরুত্বের লেভেলকে সেট করতে পারবেন৷ \n\n"<b>"লেভেল ৫"</b>" \n- বিজ্ঞপ্তি তালিকার শীর্ষে দেখায় \n- পূর্ণ স্ক্রিনের বাধাকে অনুমতি দেয় \n- সর্বদা স্ক্রিনে উপস্থিত হয় \n\n"<b>"লেভেল ৪"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- সর্বদা স্ক্রিনে উপস্থিত হয় \n\n"<b>"লেভেল ৩"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n\n"<b>"লেভেল ২"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n- কখনওই শব্দ এবং কম্পন করে না \n\n"<b>"লেভেল ১"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n- কখনওই শব্দ এবং কম্পন করে না \n- লক স্ক্রিন এবং স্ট্যাটাস বার থেকে লুকায় \n- বিজ্ঞপ্তি তালিকার নীচের দিকে দেখায় \n\n"<b>"লেভেল ০"</b>" \n- অ্যাপ্লিকেশন থেকে সমস্ত বিজ্ঞপ্তিকে অবরূদ্ধ করে"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"বিজ্ঞপ্তি"</string>
- <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+ <string name="notification_channel_disabled" msgid="344536703863700565">"এই বিজ্ঞপ্তিগুলি আপনাকে আর দেখানো হবে না"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
<skip />
- <!-- no translation found for inline_keep_showing (8945102997083836858) -->
- <skip />
- <!-- no translation found for inline_stop_button (4172980096860941033) -->
- <skip />
- <!-- no translation found for inline_keep_button (6665940297019018232) -->
- <skip />
- <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
- <skip />
- <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
- <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"এই বিজ্ঞপ্তিগুলি পরেও দেখে যেতে চান?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"বিজ্ঞপ্তি বন্ধ করুন"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"দেখতে থাকুন"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"এই অ্যাপের বিজ্ঞপ্তি পরেও দেখে যেতে চান?"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"এই বিজ্ঞপ্তিগুলি বন্ধ করা যাবে না"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> খোলা থাকলে বিজ্ঞপ্তি নিয়ন্ত্রণ"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> বন্ধ থাকলে বিজ্ঞপ্তি নিয়ন্ত্রণ"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"এই চ্যানেল থেকে বিজ্ঞপ্তি আসতে দেয়"</string>
<string name="notification_more_settings" msgid="816306283396553571">"আরও সেটিংস"</string>
- <!-- no translation found for notification_app_settings (420348114670768449) -->
- <skip />
+ <string name="notification_app_settings" msgid="420348114670768449">"কাস্টমাইজ করুন"</string>
<string name="notification_done" msgid="5279426047273930175">"সম্পন্ন"</string>
- <!-- no translation found for inline_undo (558916737624706010) -->
- <skip />
+ <string name="inline_undo" msgid="558916737624706010">"আগের অবস্থায় ফিরে যান"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"বিজ্ঞপ্তির নিয়ন্ত্রণগুলি"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"বিজ্ঞপ্তি মনে করিয়ে দেওয়ার বিকল্পগুলি"</string>
@@ -674,7 +682,8 @@
<item msgid="1545641631806817203">"ক্লিপবোর্ড"</item>
<item msgid="5742013440802239414">"কীকোড"</item>
<item msgid="8802889973626281575">"কিবোর্ড স্যুইচার"</item>
- <item msgid="8175437057325747277">"কোনো কিছুই নয়"</item>
+ <item msgid="7095517796293767867">"ঘুরিয়ে দেখার বিষয়ে প্রস্তাবনা"</item>
+ <item msgid="8494159969042135235">"কোনওটিই নয়"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"সাধারণ"</item>
@@ -798,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"ব্যাটারি এবং ডেটার ব্যবহারের বিশদ বিবরণের জন্য ট্যাপ করুন"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"মোবাইল ডেটা বন্ধ করবেন?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"একটি অ্যাপ কোনও অনুমোদনের অনুরোধকে ঢেকে দিচ্ছে, তাই সেটিংস থেকে আপনার প্রতিক্রিয়া যাচাই করা যাচ্ছে না।"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> অ্যাপটিকে <xliff:g id="APP_2">%2$s</xliff:g> এর অংশ দেখানোর অনুমতি দেবেন?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- এটি <xliff:g id="APP">%1$s</xliff:g> এর তথ্য অ্যাক্সেস করতে পারবে"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- এটি <xliff:g id="APP">%1$s</xliff:g> এর মধ্যে কাজ করতে পারবে"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> অ্যাপটিকে যেকোনও অ্যাপের অংশ দেখাতে দিন"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"অনুমতি দিন"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"খারিজ করুন"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 69b8fbe..7f8d001 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -74,7 +74,7 @@
<string name="global_action_screenshot" msgid="8329831278085426283">"Snimak ekrana"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"Spašavanje snimka ekrana..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"Spašavanje snimka ekrana..."</string>
- <string name="screenshot_saving_text" msgid="2545047868936087248">"Snimak ekrana se čuva"</string>
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"Snimak ekrana se pohranjuje"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"Snimak ekrana je sačuvan"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"Dodirnite za prikaz snimka ekrana"</string>
<string name="screenshot_failed_title" msgid="9096484883063264803">"Pravljenje snimka ekrana nije uspjelo"</string>
@@ -89,6 +89,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Dugme za početnu stranicu"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Dugme Meni"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Pristupačnost"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rotiraj ekran"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Pregled"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Traži"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -103,6 +104,12 @@
<string name="camera_label" msgid="7261107956054836961">"otvori kameru"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Odaberite novi raspored zadataka"</string>
<string name="cancel" msgid="6442560571259935130">"Otkaži"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Dugme za uvećavanje u slučaju nekompatibilnosti."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Uvećani prikaz manjeg ekrana na većem ekranu."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth je povezan."</string>
@@ -179,7 +186,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Zvuk zvona nečujan."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Poslovni režim"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbaci aplikaciju <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> uklonjena."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Sve nedavno korištene aplikacije su odbačene."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (broj uređaja: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth isključen."</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nema dostupnih uparenih uređaja"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> baterije"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Zvuk"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Slušalice"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Ulaz"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Osvjetljenje"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatsko rotiranje"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatsko rotiranje ekrana"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Povezivanje..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Dijeljenje veze"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Pristupna tačka"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obavještenja"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svjetiljka"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Prijenos podataka na mobilnoj mreži"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Iskorišteno <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ograničenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Poslovni režim"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noćno svjetlo"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Uključuje se u suton"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Do svitanja"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je onemogućen"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je omogućen"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> je onemogućena u sigurnom načinu rada."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Obriši sve"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Povucite ovdje za korištenje podijeljenog ekrana"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podjela po horizontali"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podjela po vertikali"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Prilagođena podjela"</string>
@@ -566,6 +590,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Uz kontrolu obavještenja o napajanju, možete postaviti nivo značaja obavještenja iz aplikacije, i to od nivoa 0 do 5. \n\n"<b>"Nivo 5"</b>" \n- Prikaži na vrhu liste obavještenja \n- Dopusti prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nvio 4"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nivo 3"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n\n"<b>"Nivo 2"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n\n"<b>"Nivo 1"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikada ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n- Sakrij sa ekrana za zaključavanje i statusne trake \n- Prikaži na dnu liste obavještenja \n\n"<b>"Nivo 0"</b>" \n- Blokiraj sva obavještenja iz aplikacije"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Obavještenja"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Nećete više vidjeti ova obavještenja"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Nastaviti prikazivanje ovih obavještenja?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Zaustavi obavještenja"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Nastavi prikazivanje"</string>
@@ -662,7 +688,8 @@
<item msgid="1545641631806817203">"Međumemorija"</item>
<item msgid="5742013440802239414">"Kôd tipke"</item>
<item msgid="8802889973626281575">"Prebacivač tastatura"</item>
- <item msgid="8175437057325747277">"Ništa"</item>
+ <item msgid="7095517796293767867">"Prijedlog rotacije"</item>
+ <item msgid="8494159969042135235">"Nema"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normalna"</item>
@@ -786,4 +813,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Želite li isključiti prijenos podataka na mobilnoj mreži?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Postavke ne mogu potvrditi vaš odgovor jer aplikacija zaklanja zahtjev za odobrenje."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Dozvoliti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> prikazivanje isječaka aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Može čitati informacije iz aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Može poduzeti radnje unutar aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Dozvoli aplikaciji <xliff:g id="APP">%1$s</xliff:g> prikazivanje isječaka iz svake aplikacije"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Dozvoli"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Odbij"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index d61d15e..8d61a9a 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Pàgina d\'inici"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menú"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accessibilitat"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Gira la pantalla"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Aplicacions recents"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Cerca"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Càmera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"obre la càmera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Selecciona el disseny de la tasca nova"</string>
<string name="cancel" msgid="6442560571259935130">"Cancel·la"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botó de zoom de compatibilitat."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Amplia menys com més gran sigui la pantalla."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connectat."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Mode silenci."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Mode de feina"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignora <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"S\'ha omès <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"S\'han descartat totes les aplicacions recents."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositius)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivat"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"No hi ha dispositius vinculats disponibles"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de bateria"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Àudio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Auriculars"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Entrada"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brillantor"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Gira automàticament"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Gira la pantalla automàticament"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"S\'està connectant..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Compartició de xarxa"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Punt d\'accés Wi-Fi"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificacions"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Llanterna"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dades mòbils"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Utilitzats: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Límit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertiment: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Mode de feina"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Llum nocturna"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"A la posta de sol"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Fins a l\'alba"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"S\'activarà a les <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Fins a les <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"L\'NFC està desactivada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"L\'NFC està activada"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"En mode segur, l\'aplicació <xliff:g id="APP">%s</xliff:g> està desactivada."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Esborra-ho tot"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Arrossega-ho aquí per utilitzar la pantalla dividida"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisió horitzontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisió vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisió personalitzada"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Amb els controls de notificació millorats, pots establir un nivell d\'importància d\'entre 0 i 5 per a les notificacions d\'una aplicació. \n\n"<b>"Nivell 5"</b>" \n- Mostra les notificacions a la part superior de la llista \n- Permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n"<b>"Nivell 4"</b>" \n- No permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n"<b>"Nivell 3"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n\n"<b>"Nivell 2"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- Les notificacions no poden emetre sons ni vibracions \n\n"<b>"Nivell 1"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- No activa mai el so ni la vibració \n- Amaga les notificacions de la pantalla de bloqueig i de la barra d\'estat \n- Mostra les notificacions a la part inferior de la llista \n\n"<b>"Nivell 0"</b>" \n- Bloqueja totes les notificacions de l\'aplicació"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notificacions"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Ja no veuràs aquestes notificacions"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Vols continuar rebent aquestes notificacions?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Deixa d\'enviar notificacions"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Continua rebent"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Porta-retalls"</item>
<item msgid="5742013440802239414">"Codi de tecla"</item>
<item msgid="8802889973626281575">"Commutador del teclat"</item>
- <item msgid="8175437057325747277">"Cap"</item>
+ <item msgid="7095517796293767867">"Suggeriment de rotació"</item>
+ <item msgid="8494159969042135235">"Cap"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Toca per obtenir informació sobre l\'ús de dades i de bateria"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vols desactivar les dades mòbils?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Com que hi ha una aplicació que oculta una sol·licitud de permís, no es pot verificar la teva resposta des de la configuració."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Vols permetre que <xliff:g id="APP_0">%1$s</xliff:g> mostri porcions de l\'aplicació <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Pot llegir informació de l\'aplicació <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Pot dur a terme accions dins de l\'aplicació <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Permet que <xliff:g id="APP">%1$s</xliff:g> mostri porcions de qualsevol aplicació"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Permet"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Denega"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index bb0d362..3c3e1d4 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -90,6 +90,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Domů"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Přístupnost"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Otočení obrazovky"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Přehled"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Hledat"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotoaparát"</string>
@@ -104,6 +105,12 @@
<string name="camera_label" msgid="7261107956054836961">"spustit fotoaparát"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Vybrat nové rozvržení úkolů"</string>
<string name="cancel" msgid="6442560571259935130">"Zrušit"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačítko úpravy velikosti z důvodu kompatibility"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zvětšit menší obrázek na větší obrazovku."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Rozhraní Bluetooth je připojeno."</string>
@@ -182,7 +189,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Tiché vyzvánění."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Pracovní režim"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zavřít aplikaci <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikace <xliff:g id="APP">%s</xliff:g> byla odebrána."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všechny naposledy použité aplikace byly odstraněny."</string>
@@ -281,6 +289,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> zařízení)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Rozhraní Bluetooth je vypnuto"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nejsou dostupná žádná spárovaná zařízení"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Zvuk"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Náhlavní souprava"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Vstup"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Jas"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatické otáčení"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatické otočení obrazovky"</string>
@@ -321,6 +333,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Připojování..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Sdílené připojení"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Oznámení"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svítilna"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilní data"</string>
@@ -330,8 +345,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Využito: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozornění při <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Pracovní režim"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noční režim"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Zapnout při soumraku"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Do svítání"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Zapnout v <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je vypnuto"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je zapnuto"</string>
@@ -344,6 +366,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikace <xliff:g id="APP">%s</xliff:g> je v nouzovém režimu zakázána."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Vymazat vše"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Rozdělenou obrazovku můžete použít přetažením zde"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vodorovné rozdělení"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikální rozdělení"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Vlastní rozdělení"</string>
@@ -568,6 +592,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Rozšířené ovládací prvky oznámení umožňují nastavit úroveň důležitosti oznámení aplikace od 0 do 5. \n\n"<b>"Úroveň 5"</b>" \n– Zobrazit na začátku seznamu oznámení \n– Povolit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n"<b>"Úroveň 4"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n"<b>"Úroveň 3"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n\n"<b>"Úroveň 2"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat žádný zvukový signál ani nevibrovat \n\n"<b>"Úroveň 1"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat zvukový signál ani nevibrovat \n– Skrýt z obrazovky uzamčení a stavového řádku \n– Zobrazovat na konci seznamu oznámení \n\n"<b>";Úroveň 0"</b>" \n– Blokovat všechna oznámení z aplikace"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Oznámení"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Tato oznámení již nebudete dostávat"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Mají se tato oznámení nadále zobrazovat?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Přestat zobrazovat oznámení"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Nadále zobrazovat"</string>
@@ -666,7 +692,8 @@
<item msgid="1545641631806817203">"Schránka"</item>
<item msgid="5742013440802239414">"Klávesa"</item>
<item msgid="8802889973626281575">"Přepínač klávesnice"</item>
- <item msgid="8175437057325747277">"Žádné"</item>
+ <item msgid="7095517796293767867">"Doporučené otočení"</item>
+ <item msgid="8494159969042135235">"Žádné"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normální"</item>
@@ -790,4 +817,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Klepnutím zobrazíte podrobnosti o využití baterie a dat"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vypnout mobilní data?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Žádost o oprávnění je blokována jinou aplikací. Nastavení proto vaši odpověď nemůže ověřit."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Povolit aplikaci <xliff:g id="APP_0">%1$s</xliff:g> zobrazovat ukázky z aplikace <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Může číst informace z aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Může provádět akce v aplikaci <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Povolit aplikaci <xliff:g id="APP">%1$s</xliff:g> zobrazovat ukázky z libovolné aplikace"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Povolit"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Zamítnout"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index e2ff065..39895acb 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Startskærm"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Hjælpefunktioner"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Roter skærmen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Oversigt"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Søg"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"åbn kamera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Vælg nyt opgavelayout"</string>
<string name="cancel" msgid="6442560571259935130">"Annuller"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knap for kompatibilitetszoom."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom mindre til større skærm."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tilsluttet."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Lydløs."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Arbejdstilstand"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Afvis <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> er annulleret."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle de seneste applikationer er lukket."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheder)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth slået fra"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Der er ingen tilgængelige parrede enheder"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batteri"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Lyd"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Input"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Lysstyrke"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Roter automatisk"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Roter skærmen automatisk"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Opretter forbindelse…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Netdeling"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Underretninger"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lommelygte"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> brugt"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Grænse: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advarsel ved <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Arbejdstilstand"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nattelys"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Tænd ved solnedgang"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Indtil solopgang"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Tænd kl. <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Indtil kl. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC er deaktiveret"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC er aktiveret"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> er deaktiveret i sikker tilstand."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Ryd alle"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Træk hertil for at bruge delt skærm"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Opdel vandret"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Opdel lodret"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Opdel brugerdefineret"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Med kontrolelementer til underretninger om strøm kan du konfigurere et vigtighedsniveau fra 0 til 5 for en apps underretninger. \n\n"<b>"Niveau 5"</b>\n"- Vis øverst på listen over underretninger \n- Tillad afbrydelse af fuld skærm \n- Se altid smugkig \n\n"<b>"Niveau 4"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se altid smugkig \n\n"<b>"Niveau 3"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se aldrig smugkig \n\n"<b>"Niveau 2"</b>\n"- Ingen afbrydelse af fuld skærm \n Se aldrig smugkig \n- Ingen lyd og vibration \n\n"<b>"Niveau 1"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se aldrig smugkig \n- Ingen lyd eller vibration \n- Skjul fra låseskærm og statusbjælke \n- Vis nederst på listen over underretninger \n\n"<b>"Niveau 0"</b>\n"- Bloker alle underretninger fra appen."</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Underretninger"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Du får ikke længere vist disse underretninger"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Vil du fortsætte med at se disse underretninger?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Stop underretninger"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Fortsæt med at vise underretninger"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Udklipsholder"</item>
<item msgid="5742013440802239414">"Tastekode"</item>
<item msgid="8802889973626281575">"Tastaturskifter"</item>
- <item msgid="8175437057325747277">"Ingen"</item>
+ <item msgid="7095517796293767867">"Rotationsforslag"</item>
+ <item msgid="8494159969042135235">"Ingen"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tryk for at se oplysninger om batteri- og dataforbrug"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vil du deaktivere mobildata?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Indstillinger kan ikke bekræfte dit svar, da en app dækker for en anmodning om tilladelse."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Vil du give <xliff:g id="APP_0">%1$s</xliff:g> tilladelse til at vise eksempler fra <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Den kan læse oplysninger fra <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Den kan foretage handlinger i <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Tillad, at <xliff:g id="APP">%1$s</xliff:g> viser eksempler fra enhver app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Tillad"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Afvis"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 53bf7d8..dd258e1 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Startbildschirm"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menü"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Bedienungshilfen"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Bildschirm drehen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Übersicht"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Suchen"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"Kamera öffnen"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Neues Aufgabenlayout auswählen"</string>
<string name="cancel" msgid="6442560571259935130">"Abbrechen"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Schaltfläche für Kompatibilitätszoom"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom auf einen größeren Bildschirm"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Mit Bluetooth verbunden"</string>
@@ -182,7 +189,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Klingelton lautlos"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Arbeitsmodus"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> beenden"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> entfernt"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle kürzlich verwendeten Apps wurden entfernt."</string>
@@ -279,6 +287,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Geräte)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth aus"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Keine gekoppelten Geräte verfügbar"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Eingabe"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Helligkeit"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatisch drehen"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Bildschirm automatisch drehen"</string>
@@ -319,6 +331,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Verbindung wird hergestellt…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Benachrichtigungen"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taschenlampe"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile Daten"</string>
@@ -328,8 +343,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> verwendet"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> Datenlimit"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Warnung für <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Arbeitsmodus"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nachtlicht"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"An bei Sonnenuntergang"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Bis Sonnenaufgang"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"An um <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Bis <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ist deaktiviert"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ist aktiviert"</string>
@@ -342,6 +364,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ist im abgesicherten Modus deaktiviert."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Alle schließen"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Hierher ziehen, um den Bildschirm zu teilen"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Geteilte Schaltfläche – horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Geteilte Schaltfläche – vertikal"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Geteilte Schaltfläche – benutzerdefiniert"</string>
@@ -566,6 +590,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Mit den erweiterten Benachrichtigungseinstellungen kannst du für App-Benachrichtigungen eine Wichtigkeitsstufe von 0 bis 5 festlegen. \n\n"<b>"Stufe 5"</b>" \n- Auf der Benachrichtigungsleiste ganz oben anzeigen \n- Vollbildunterbrechung zulassen \n- Immer kurz einblenden \n\n"<b>"Stufe 4"</b>" \n- Keine Vollbildunterbrechung \n- Immer kurz einblenden \n\n"<b>"Stufe 3"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n\n"<b>"Stufe 2"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n- Weder Ton noch Vibration \n\n"<b>"Stufe 1"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n- Weder Ton noch Vibration \n- Auf Sperrbildschirm und Statusleiste verbergen \n- Auf der Benachrichtigungsleiste ganz unten anzeigen \n\n"<b>"Stufe 0"</b>" \n- Alle Benachrichtigungen der App sperren"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Benachrichtigungen"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Du erhältst diese Benachrichtigungen nicht mehr"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Diese Benachrichtigungen weiterhin anzeigen?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Benachrichtigungen nicht mehr anzeigen"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Weiterhin anzeigen"</string>
@@ -660,7 +686,8 @@
<item msgid="1545641631806817203">"Zwischenablage"</item>
<item msgid="5742013440802239414">"Keycode"</item>
<item msgid="8802889973626281575">"Tastaturwechsler"</item>
- <item msgid="8175437057325747277">"Keine"</item>
+ <item msgid="7095517796293767867">"Drehvorschlag"</item>
+ <item msgid="8494159969042135235">"Keine"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Mittig"</item>
@@ -784,4 +811,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Für Details zur Akku- und Datennutzung tippen"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Mobile Daten deaktivieren?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Deine Eingabe wird von \"Einstellungen\" nicht erkannt, weil die Berechtigungsanfrage von einer App verdeckt wird."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> erlauben, Teile von <xliff:g id="APP_2">%2$s</xliff:g> anzuzeigen?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Darf Informationen aus <xliff:g id="APP">%1$s</xliff:g> lesen"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Darf Aktionen in <xliff:g id="APP">%1$s</xliff:g> ausführen"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> darf Teile aus jeder beliebigen App anzeigen"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Zulassen"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Ablehnen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 663191c..8c30521 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Αρχική οθόνη"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Μενού"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Προσβασιμότητα"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Περιστροφή οθόνης"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Επισκόπηση"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Αναζήτηση"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Φωτογραφική μηχανή"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"άνοιγμα φωτογραφικής μηχανής"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Επιλέξτε τη νέα διάταξη εργασίας"</string>
<string name="cancel" msgid="6442560571259935130">"Ακύρωση"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Κουμπί εστίασης συμβατότητας."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Ζουμ από μικρότερη σε μεγαλύτερη οθόνη."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Το Bluetooth είναι συνδεδεμένο."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ειδοποίηση ήχου στο αθόρυβο."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Λειτουργία εργασίας"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Παράβλεψη <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Απορρίφθηκαν <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Έγινε παράβλεψη όλων των πρόσφατων εφαρμογών."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> συσκευές)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Απενεργοποιημένο Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Δεν υπάρχουν διαθέσιμες συσκευές σε σύζευξη"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Ήχος"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Ακουστικά"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Είσοδος"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Φωτεινότητα"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Αυτόματη περιστροφή"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Αυτόματη περιστροφή οθόνης"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Σύνδεση…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Πρόσδεση"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Σημείο πρόσβασης Wi-Fi"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ειδοποιήσεις"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Φακός"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Δεδομένα κινητής τηλεφωνίας"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Χρησιμοποιούνται <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Όριο <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Προειδοποίηση για <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Λειτουργία εργασίας"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Νυχτερινός φωτισμός"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Κατά τη δύση"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Μέχρι την ανατολή"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ενεργοποίηση στις <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Έως τις <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Το NFC είναι απενεργοποιημένο"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Το NFC είναι ενεργοποιημένο"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Η εφαρμογή <xliff:g id="APP">%s</xliff:g> έχει απενεργοποιηθεί στην ασφαλή λειτουργία."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Διαγραφή όλων"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Σύρετε εδώ για να χρησιμοποιήσετε τον διαχωρισμό οθόνης"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Οριζόντιος διαχωρισμός"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Κάθετος διαχωρισμός"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Προσαρμοσμένος διαχωρισμός"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Με τα στοιχεία ελέγχου ειδοποίησης ισχύος, μπορείτε να ορίσετε ένα επίπεδο βαρύτητας από 0 έως 5 για τις ειδοποιήσεις μιας εφαρμογής. \n\n"<b>"Επίπεδο 5"</b>" \n- Εμφάνιση στην κορυφή της λίστας ειδοποιήσεων \n- Να επιτρέπεται η διακοπή πλήρους οθόνης \n- Να γίνεται πάντα σύντομη προβολή \n\n"<b>"Επίπεδο 4"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να γίνεται πάντα σύντομη προβολή \n\n"<b>"Επίπεδο 3"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n\n"<b>"Επίπεδο 2"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n- Να μην χρησιμοποιείται ποτέ ήχος και δόνηση \n\n"<b>"Επίπεδο 1"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n- Να μην χρησιμοποιείται ποτέ ήχος και δόνηση \n- Απόκρυψη από την οθόνη κλειδώματος και τη γραμμή κατάστασης \n- Εμφάνιση στο κάτω μέρος της λίστας ειδοποιήσεων \n\n"<b>"Επίπεδο 0"</b>" \n- Αποκλεισμός όλων των ειδοποιήσεων από την εφαρμογή"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Ειδοποιήσεις"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Δεν θα βλέπετε πλέον αυτές τις ειδοποιήσεις"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Να συνεχίσουν να εμφανίζονται αυτές οι ειδοποιήσεις;"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Διακοπή ειδοποιήσεων"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Συνέχιση εμφάνισης"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Πρόχειρο"</item>
<item msgid="5742013440802239414">"Κωδικός-πλήκτρο"</item>
<item msgid="8802889973626281575">"Εναλλαγή πληκτρολογίων"</item>
- <item msgid="8175437057325747277">"Κανένα"</item>
+ <item msgid="7095517796293767867">"Πρόταση περιστροφής"</item>
+ <item msgid="8494159969042135235">"Κανένα"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Κανονική"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Πατήστε για λεπτομέρειες σχετικά με τη χρήση μπαταρίας και δεδομένων"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Απενεργοποίηση δεδομένων κινητής τηλεφωνίας;"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Επειδή μια εφαρμογή αποκρύπτει ένα αίτημα άδειας, δεν είναι δυνατή η επαλήθευση της απάντησής σας από τις Ρυθμίσεις."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APP_0">%1$s</xliff:g> να εμφανίζει τμήματα της εφαρμογής <xliff:g id="APP_2">%2$s</xliff:g>;"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Μπορεί να διαβάζει πληροφορίες από την εφαρμογή <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Μπορεί να εκτελεί ενέργειες εντός της εφαρμογής <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> να εμφανίζει τμήματα από οποιαδήποτε εφαρμογή"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Επιτρέπεται"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Δεν επιτρέπεται"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index ab759ed..3f6d5e5 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Home"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accessibility"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rotate screen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Overview"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Search"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"open camera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
<string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ringer silent."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Work mode"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"No paired devices available"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Input"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Auto-rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Auto-rotate screen"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Connecting..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Torch"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> used"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> limit"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work mode"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Work profile"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Notifications & apps are off"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"On at sunset"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Until sunrise"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Clear all"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Drag here to use split screen"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Swipe up to switch apps"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Clipboard"</item>
<item msgid="5742013440802239414">"Keycode"</item>
<item msgid="8802889973626281575">"Keyboard switcher"</item>
- <item msgid="8175437057325747277">"None"</item>
+ <item msgid="7095517796293767867">"Rotation suggestion"</item>
+ <item msgid="8494159969042135235">"None"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap for details on battery and data usage"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Turn off mobile data?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Allow <xliff:g id="APP">%1$s</xliff:g> to show slices from any app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Allow"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Deny"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 1bd101f..d49c25a 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Home"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accessibility"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rotate screen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Overview"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Search"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"open camera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
<string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ringer silent."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Work mode"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"No paired devices available"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Input"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Auto-rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Auto-rotate screen"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Connecting..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> used"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> limit"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work mode"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Work profile"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Notifications & apps are off"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"On at sunset"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Until sunrise"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Clear all"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Drag here to use split screen"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Swipe up to switch apps"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Clipboard"</item>
<item msgid="5742013440802239414">"Keycode"</item>
<item msgid="8802889973626281575">"Keyboard switcher"</item>
- <item msgid="8175437057325747277">"None"</item>
+ <item msgid="7095517796293767867">"Rotation suggestion"</item>
+ <item msgid="8494159969042135235">"None"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap for details on battery and data usage"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Turn off mobile data?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Allow <xliff:g id="APP">%1$s</xliff:g> to show slices from any app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Allow"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Deny"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index ab759ed..3f6d5e5 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Home"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accessibility"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rotate screen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Overview"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Search"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"open camera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
<string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ringer silent."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Work mode"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"No paired devices available"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Input"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Auto-rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Auto-rotate screen"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Connecting..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Torch"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> used"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> limit"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work mode"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Work profile"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Notifications & apps are off"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"On at sunset"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Until sunrise"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Clear all"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Drag here to use split screen"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Swipe up to switch apps"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Clipboard"</item>
<item msgid="5742013440802239414">"Keycode"</item>
<item msgid="8802889973626281575">"Keyboard switcher"</item>
- <item msgid="8175437057325747277">"None"</item>
+ <item msgid="7095517796293767867">"Rotation suggestion"</item>
+ <item msgid="8494159969042135235">"None"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap for details on battery and data usage"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Turn off mobile data?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Allow <xliff:g id="APP">%1$s</xliff:g> to show slices from any app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Allow"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Deny"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index ab759ed..3f6d5e5 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Home"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accessibility"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rotate screen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Overview"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Search"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"open camera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
<string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ringer silent."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Work mode"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"No paired devices available"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Input"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Auto-rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Auto-rotate screen"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Connecting..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Torch"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> used"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> limit"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work mode"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Work profile"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Notifications & apps are off"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"On at sunset"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Until sunrise"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Clear all"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Drag here to use split screen"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Swipe up to switch apps"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Clipboard"</item>
<item msgid="5742013440802239414">"Keycode"</item>
<item msgid="8802889973626281575">"Keyboard switcher"</item>
- <item msgid="8175437057325747277">"None"</item>
+ <item msgid="7095517796293767867">"Rotation suggestion"</item>
+ <item msgid="8494159969042135235">"None"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap for details on battery and data usage"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Turn off mobile data?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Allow <xliff:g id="APP">%1$s</xliff:g> to show slices from any app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Allow"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Deny"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index ad39146..0571c1f 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Home"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accessibility"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rotate screen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Overview"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Search"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"open camera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
<string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ringer silent."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Work mode"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"No paired devices available"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> battery"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Input"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Auto-rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Auto-rotate screen"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Connecting..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> used"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> limit"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work mode"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Work profile"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Notifications & apps are off"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"On at sunset"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Until sunrise"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Clear all"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Drag here to use split screen"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Swipe up to switch apps"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Custom"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Clipboard"</item>
<item msgid="5742013440802239414">"Keycode"</item>
<item msgid="8802889973626281575">"Keyboard switcher"</item>
- <item msgid="8175437057325747277">"None"</item>
+ <item msgid="7095517796293767867">"Rotation suggestion"</item>
+ <item msgid="8494159969042135235">"None"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap for details on battery and data usage"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Turn off mobile data?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Because an app is obscuring a permission request, Settings can’t verify your response."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Allow <xliff:g id="APP">%1$s</xliff:g> to show slices from any app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Allow"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Deny"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index cdb432b..d02ce1c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Página principal"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menú"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accesibilidad"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Girar pantalla"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Recientes"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Buscar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Cámara"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Selecciona el nuevo diseño de la tarea."</string>
<string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Timbre en silencio"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Modo de trabajo"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rechazar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartada."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se descartaron todas las aplicaciones recientes."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivado"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"No hay dispositivos sincronizados disponibles"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de batería"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Auriculares"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Entrada"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brillo"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotación automática"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Girar la pantalla automáticamente"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Conectando…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Anclaje a red"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datos móviles"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Utilizados: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Límite de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabajo"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz nocturna"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Al atardecer"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Hasta el amanecer"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"A la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Hasta la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"La tecnología NFC está inhabilitada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"La tecnología NFC está habilitada"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> está inhabilitada en modo seguro."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Borrar todo"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Arrastra hasta aquí para usar la pantalla dividida"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Con los controles de activación de notificaciones, puedes establecer un nivel de importancia para las notificaciones de una app. \n\n"<b>"Nivel 5"</b>" \n- Mostrar en la parte superior de la lista de notificaciones. \n- Permitir interrupción en la pantalla completa. \n- Mostrar siempre. \n\n"<b>"Nivel 4"</b>" \n- No permitir interrupción en la pantalla completa. \n- Mostrar siempre. \n\n"<b>"Nivel 3"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n\n"<b>"Nivel 2"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n- No sonar ni vibrar. \n\n"<b>"Nivel 1"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n- No sonar ni vibrar. \n- Ocultar de la pantalla bloqueada y la barra de estado. \n- Mostrar al final de la lista de notificaciones. \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas las notificaciones de la app."</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notificaciones"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Ya no verás estas notificaciones"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"¿Quieres seguir viendo estas notificaciones?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Detener notificaciones"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Seguir viendo"</string>
@@ -658,7 +684,8 @@
<item msgid="1545641631806817203">"Portapapeles"</item>
<item msgid="5742013440802239414">"Clave de código"</item>
<item msgid="8802889973626281575">"Cambio de teclado"</item>
- <item msgid="8175437057325747277">"Ninguno"</item>
+ <item msgid="7095517796293767867">"Sugerencia de rotación"</item>
+ <item msgid="8494159969042135235">"Ninguno"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -782,4 +809,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Presiona para obtener información sobre el uso de datos y de la batería"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"¿Deseas desactivar los datos móviles?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Como una app está bloqueando una solicitud de permiso, Configuración no puede verificar tu respuesta."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"¿Permitir que <xliff:g id="APP_0">%1$s</xliff:g> muestre fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Puede leer información sobre <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Puede realizar acciones en <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Permitir que <xliff:g id="APP">%1$s</xliff:g> muestre fragmentos de cualquier app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Permitir"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Rechazar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index b467b38..5cc6ab6 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Inicio"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menú"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accesibilidad"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Girar la pantalla"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Aplicaciones recientes"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Buscar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Cámara"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Seleccionar diseño de tarea nueva"</string>
<string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Modo silencio"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Modo de trabajo"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Se ha eliminado <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se han ignorado todas las aplicaciones recientes."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivado"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"No hay dispositivos vinculados disponibles"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de batería"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Auriculares"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Entrada"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brillo"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Girar automáticamente"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Girar pantalla automáticamente"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Conectando..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Compartir conexión"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datos móviles"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> usado"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Límite de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabajo"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz nocturna"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Al atardecer"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Hasta el amanecer"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Hora: <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Hasta: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"La conexión NFC está inhabilitada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"La conexión NFC está habilitada"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"La aplicación <xliff:g id="APP">%s</xliff:g> se ha inhabilitado en modo seguro."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Borrar todo"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Arrastra hasta aquí para utilizar la pantalla dividida"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Los controles de energía de las notificaciones permiten establecer un nivel de importancia de 0 a 5 para las notificaciones de las aplicaciones. \n\n"<b>"Nivel 5"</b>" \n- Mostrar en la parte superior de la lista de notificaciones \n- Permitir interrumpir en el modo de pantalla completa \n- Mostrar siempre \n\n"<b>"Nivel 4"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- Mostrar siempre \n\n"<b>"Nivel 3"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- No mostrar nunca \n\n"<b>"Nivel 2"</b>" \n- Evitar interrumpir en el modo de pantalla completa\n- No mostrar nunca \n- No emitir sonido ni vibrar nunca \n\n"<b>"Nivel 1"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- No mostrar nunca \n- No emitir sonido ni vibrar nunca \n- Ocultar de la pantalla de bloqueo y de la barra de estado \n- Mostrar en la parte inferior de la lista de notificaciones \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas las notificaciones de la aplicación"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notificaciones"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"No volverás a ver estas notificaciones"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"¿Quieres seguir viendo estas notificaciones?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Detener las notificaciones"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Seguir mostrando"</string>
@@ -658,7 +684,8 @@
<item msgid="1545641631806817203">"Portapapeles"</item>
<item msgid="5742013440802239414">"Código de teclado"</item>
<item msgid="8802889973626281575">"Cambio de teclado"</item>
- <item msgid="8175437057325747277">"Ninguno"</item>
+ <item msgid="7095517796293767867">"Sugerencia de rotación"</item>
+ <item msgid="8494159969042135235">"Ninguna"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -782,4 +809,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Toca para ver información detallada sobre el uso de datos y de la batería"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"¿Desactivar los datos móviles?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Una aplicación impide ver una solicitud de permiso, por lo que Ajustes no puede verificar tu respuesta."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"¿Quieres permitir que <xliff:g id="APP_0">%1$s</xliff:g> muestre fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Puede leer información de <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Puede realizar acciones en <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Permitir que <xliff:g id="APP">%1$s</xliff:g> muestre fragmentos de cualquier aplicación"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Permitir"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Denegar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 1b8ad65..eac4814 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Kodu"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menüü"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Juurdepääsetavus"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Pöörake ekraani"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Ülevaade"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Otsing"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kaamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"ava kaamera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Uue toimingu paigutuse valimine"</string>
<string name="cancel" msgid="6442560571259935130">"Tühista"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Sobivussuumi nupp."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Suumi suuremale ekraanile vähem."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth on ühendatud."</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Vaikne kõlisti."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Töörežiim"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rakendusest <xliff:g id="APP">%s</xliff:g> loobumine."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Loobusite rakendusest <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kõikidest hiljutistest rakendustest on loobutud"</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> seadet)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth on väljas"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Ühtegi seotud seadet pole saadaval"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> akut"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Heli"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Peakomplekt"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Sisend"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Heledus"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automaatne pööramine"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Pööra ekraani automaatselt"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Ühenduse loomine ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Jagamine"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Kuumkoht"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Märguanded"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taskulamp"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiilne andmeside"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> on kasutatud"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limiit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> hoiatus"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Töörežiim"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Öövalgus"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Sissel. päikeselooj."</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Kuni päikesetõusuni"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Sisselülitam. kell <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Kuni <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC on keelatud"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC on lubatud"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Rakendus <xliff:g id="APP">%s</xliff:g> on turvarežiimis keelatud."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Kustuta kõik"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Jagatud ekraani kasutamiseks lohistage siia"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horisontaalne poolitamine"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikaalne poolitamine"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Kohandatud poolitamine"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Toite märguannete juhtnuppudega saate määrata rakenduse märguannete tähtsuse taseme vahemikus 0–5. \n\n"<b>"5. tase"</b>" \n- Kuva märguannete loendi ülaosas\n- Luba täisekraanil häirimine \n- Kuva alati ekraani servas \n\n"<b>"4. tase"</b>" \n- Keela täisekraanil häirimine \n- Kuva alati ekraani servas \n\n"<b>"3. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n\n"<b>"2. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n- Ära kunagi helise ega vibreeri \n\n"<b>"1. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n- Ära kunagi helise ega vibreeri \n- Peida lukustuskuval ja olekuribal \n- Kuva märguannete loendi allosas \n\n"<b>"Tase 0"</b>" \n- Blokeeri kõik rakenduse märguanded"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Märguanded"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Te ei näe enam neid märguandeid"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Kas soovite nende märguannete kuvamist jätkata?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Peata märguanded"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Jätka kuvamist"</string>
@@ -658,7 +684,8 @@
<item msgid="1545641631806817203">"Lõikelaud"</item>
<item msgid="5742013440802239414">"Võtmekood"</item>
<item msgid="8802889973626281575">"Klaviatuuri vahetaja"</item>
- <item msgid="8175437057325747277">"Mitte ükski"</item>
+ <item msgid="7095517796293767867">"Pööramise soovitus"</item>
+ <item msgid="8494159969042135235">"Puudub"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Tavaline"</item>
@@ -782,4 +809,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Aku ja andmekasutuse üksikasjade nägemiseks puudutage"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Kas lülitada mobiilne andmeside välja?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Seaded ei saa teie vastust kinnitada, sest rakendus varjab loataotlust."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Kas lubada rakendusel <xliff:g id="APP_0">%1$s</xliff:g> näidata rakenduse <xliff:g id="APP_2">%2$s</xliff:g> lõike?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- See saab lugeda teavet rakendusest <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- See saab rakenduses <xliff:g id="APP">%1$s</xliff:g> toiminguid teha"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Luba rakendus <xliff:g id="APP">%1$s</xliff:g>, et kuvada lõike mis tahes rakendusest"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Luba"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Keela"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 1d49b3b..1c46eba 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -78,7 +78,7 @@
<string name="screenshot_saved_text" msgid="7574667448002050363">"Sakatu pantaila-argazkia ikusteko"</string>
<string name="screenshot_failed_title" msgid="9096484883063264803">"Ezin izan da atera pantaila-argazkia"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Arazo bat izan da pantaila-argazkia gordetzean"</string>
- <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Ezin da atera pantaila-argazkia ez delako gelditzen tokirik"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Ezin da gorde pantaila-argazkia ez delako gelditzen tokirik"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB fitxategiak transferitzeko aukerak"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Muntatu multimedia-erreproduzigailu gisa (MTP)"</string>
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Hasiera"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menua"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Erabilerraztasuna"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Biratu pantaila"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Ikuspegi orokorra"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Bilatu"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"ireki kamera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Hautatu zereginen diseinua"</string>
<string name="cancel" msgid="6442560571259935130">"Utzi"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoom-bateragarritasunaren botoia."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Handiagotu pantaila txikia."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetootha konektatuta."</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Tonu-jotzailea isilik."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Lan modua"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Baztertu <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> baztertu da."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Azken aplikazio guztiak baztertu da."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetootha (<xliff:g id="NUMBER">%d</xliff:g> gailu)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetootha desaktibatuta"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Ez dago parekatutako gailurik erabilgarri"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audioa"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Entzungailua"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Sarrera"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Distira"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Biratze automatikoa"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Biratu pantaila automatikoki"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Konektatzen…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Konexioa partekatzea"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Sare publikoa"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Jakinarazpenak"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datu mugikorrak"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> erabilita"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Muga: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Abisua: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Lan modua"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Gaueko argia"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Ilunabarrean"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Ilunabarrera arte"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> arte"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Desgaituta dago NFC"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Gaituta dago NFC"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> desgaituta dago modu seguruan."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Garbitu guztiak"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Arrastatu hau pantaila zatitzeko"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Zatitze horizontala"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Zatitze bertikala"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Zatitze pertsonalizatua"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Bateria-mailaren arabera jakinarazpenak kontrolatzeko aukerekin, 0 eta 5 bitarteko garrantzi-mailetan sailka ditzakezu aplikazioen jakinarazpenak. \n\n"<b>"5. maila"</b>" \n- Erakutsi jakinarazpenen zerrendaren goialdean. \n- Baimendu etetea pantaila osoko moduan zaudenean. \n- Agerrarazi beti jakinarazpenak. \n\n"<b>"4. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Agerrarazi beti jakinarazpenak. \n\n"<b>"3. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n\n"<b>"2. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n- Ez egin soinurik edo dardararik inoiz. \n\n"<b>"1. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n- Ez egin soinurik edo dardararik inoiz. \n- Ezkutatu pantaila blokeatutik eta egoera-barratik. \n- Erakutsi jakinarazpenen zerrendaren behealdean. \n\n"<b>"0. maila"</b>" \n- Blokeatu aplikazioaren jakinarazpen guztiak."</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Jakinarazpenak"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Aurrerantzean ez duzu ikusiko horrelako jakinarazpenik"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Jakinarazpenak erakusten jarraitzea nahi duzu?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Blokeatu jakinarazpenak"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Jarraitu erakusten"</string>
@@ -658,7 +684,8 @@
<item msgid="1545641631806817203">"Arbela"</item>
<item msgid="5742013440802239414">"Tekla-kodea"</item>
<item msgid="8802889973626281575">"Teklatu-aldatzailea"</item>
- <item msgid="8175437057325747277">"Bat ere ez"</item>
+ <item msgid="7095517796293767867">"Biratzeko iradokizuna"</item>
+ <item msgid="8494159969042135235">"Bat ere ez"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normala"</item>
@@ -782,4 +809,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Datu-konexioa desaktibatu nahi duzu?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Aplikazio bat baimen-eskaera oztopatzen ari denez, ezarpenek ezin dute egiaztatu erantzuna."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> aplikazioari <xliff:g id="APP_2">%2$s</xliff:g> aplikazioaren zatiak erakustea baimendu nahi diozu?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- <xliff:g id="APP">%1$s</xliff:g> aplikazioaren informazioa irakur dezake."</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- <xliff:g id="APP">%1$s</xliff:g> aplikazioan ekintzak gauza ditzake."</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Baimendu <xliff:g id="APP">%1$s</xliff:g> aplikazioari edozein aplikazioren zatiak erakustea"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Baimendu"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Ukatu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index e597569..a5543d3 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"صفحهٔ اصلی"</string>
<string name="accessibility_menu" msgid="316839303324695949">"منو"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"دسترسپذیری"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"چرخاندن صفحه"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"نمای کلی"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"جستجو"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"دوربین"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"باز کردن دوربین"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"انتخاب طرحبندی جدید کار"</string>
<string name="cancel" msgid="6442560571259935130">"لغو"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"دکمه بزرگنمایی سازگار."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"بزرگنمایی از صفحههای کوچک تا بزرگ."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"بلوتوث متصل است."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"زنگ بیصدا."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"حالت کار"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"رد کردن <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> نادیده گرفته شد."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"همه برنامههای اخیر رد شدند."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوتوث ( <xliff:g id="NUMBER">%d</xliff:g> دستگاه)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"بلوتوث خاموش"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"هیچ دستگاه مرتبط شدهای موجود نیست"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"شارژ باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"صوت"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"هدست"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ورودی"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"روشنایی"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"چرخش خودکار"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"چرخش خودکار صفحهنمایش"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"در حال اتصال..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"اتصال به اینترنت با تلفن همراه"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"نقطه اتصال"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"اعلانها"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"چراغ قوه"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"داده تلفن همراه"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> استفاده شده"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> محدودیت"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"هشدار <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"حالت کار"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"نور شب"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"غروب روشن میشود"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"تا طلوع"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"ساعت <xliff:g id="TIME">%s</xliff:g> روشن میشود"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"تا <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC غیرفعال است"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC فعال است"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> در حالت ایمن غیرفعال است."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"پاک کردن همه"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"برای استفاده از تقسیم صفحه، به اینجا بکشید"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"تقسیم افقی"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"تقسیم عمودی"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"سفارشی کردن تقسیم"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"با کنترلهای قدرتمند اعلان میتوانید سطح اهمیت اعلانهای هر برنامه را از ۰ تا ۵ تعیین کنید. \n\n"<b>"سطح ۵"</b>" \n- در صدر فهرست اعلانها نشان داده میشود \n- وقفه برای نمایش تمامصفحه مجاز است \n- همیشه اجمالی نشان داده میشود \n\n"<b>"سطح ۴"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- همیشه اجمالی نشان داده میشود \n\n"<b>"سطح ۳"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n\n"<b>"سطح ۲"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n- هیچوقت صدا و لرزش ایجاد نمیکند \n\n"<b>"سطح ۱"</b>" \n- نمایش تمام صفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n- هیچوقت صدا یا لرزش ایجاد نمیکند \n- در قفل صفحه و نوار وضعیت پنهان است \n- در پایین فهرست اعلانها نشان داده میشود \n\n"<b>"سطح ۰"</b>" \n- همه اعلانهای این برنامه مسدود است"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"اعلانها"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"دیگر این اعلانها را نخواهید دید"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"نمایش این اعلانها ادامه یابد؟"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"توقف اعلانها"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"همچنان نشان داده شود"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"بریدهدان"</item>
<item msgid="5742013440802239414">"کد کلید"</item>
<item msgid="8802889973626281575">"تغییردهنده صفحهکلید"</item>
- <item msgid="8175437057325747277">"هیچکدام"</item>
+ <item msgid="7095517796293767867">"پیشنهاد چرخش"</item>
+ <item msgid="8494159969042135235">"هیچکدام"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"معمولی"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"برای جزئیات مربوط به مصرف باتری و داده، ضربه بزنید"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"داده شبکه تلفن همراه خاموش شود؟"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"چون برنامهای درحال ایجاد تداخل در درخواست مجوز است، «تنظیمات» نمیتواند پاسخ شما را تأیید کند."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"به <xliff:g id="APP_0">%1$s</xliff:g> اجازه داده شود تکههای <xliff:g id="APP_2">%2$s</xliff:g> را نشان دهد؟"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- میتواند اطلاعات <xliff:g id="APP">%1$s</xliff:g> را بخواند"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- میتواند در <xliff:g id="APP">%1$s</xliff:g> اقدام انجام دهد"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"به <xliff:g id="APP">%1$s</xliff:g> اجازه داده شود تکههایی از برنامهها نشان دهد"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"مجاز"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"رد کردن"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 59327c6..34072db 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Aloituspainike"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Valikko"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Esteettömyys"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Näytön kääntäminen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Viimeisimmät"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Haku"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"avaa kamera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Valitse uusi tehtävien asettelu"</string>
<string name="cancel" msgid="6442560571259935130">"Peruuta"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Yhteensopivuuszoomaus-painike."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoomaa pienemmältä suuremmalle ruudulle."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth yhdistetty."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Soittoääni: äänetön."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Työtila"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hylätään <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> hylättiin."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kaikki viimeisimmät sovellukset on hylätty."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> laitetta)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth pois käytöstä"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Laitepareja ei ole käytettävissä"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Ääni"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Syöttölaite"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Kirkkaus"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automaattinen kääntö"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Käännä näyttöä automaattisesti."</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Yhdistetään…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Jaettu yhteys"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ilmoitukset"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taskulamppu"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiilidata"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"käytetty <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"kiintiö <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> – varoitus"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Työtila"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Yövalo"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Auringon laskiessa"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Auringonnousuun"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Käyttöön klo <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> saakka"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC on poistettu käytöstä"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC on käytössä"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> on poistettu käytöstä vikasietotilassa."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Tyhjennä kaikki"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Jaa näyttö vetämällä tähän."</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vaakasuuntainen jako"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pystysuuntainen jako"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Muokattu jako"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Ilmoitusten tehohallinnan avulla voit määrittää sovelluksen ilmoituksille tärkeystason väliltä 0–5. \n\n"<b>"Taso 5"</b>" \n– Ilmoitukset näytetään ilmoitusluettelon yläosassa \n– Näkyminen koko näytön tilassa sallitaan \n– Ilmoitukset kurkistavat aina näytölle\n\n"<b>"Taso 4"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ilmoitukset kurkistavat aina näytölle \n\n"<b>"Taso 3"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n\n"<b>"Taso 2"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n– Ei ääniä eikä värinää \n\n"<b>"Taso 1"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n– Ei ääniä eikä värinää \n– Ilmoitukset piilotetaan lukitusnäytöltä ja tilapalkista \n– Ilmoitukset näytetään ilmoitusluettelon alaosassa \n\n"<b>"Taso 0"</b>" \n– Kaikki sovelluksen ilmoitukset estetään"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Ilmoitukset"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Et näe näitä ilmoituksia enää"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Jatketaanko näiden ilmoitusten näyttämistä?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Lopeta ilmoitukset"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Jatka näyttämistä"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Leikepöytä"</item>
<item msgid="5742013440802239414">"Näppäinkoodi"</item>
<item msgid="8802889973626281575">"Näppäimistövalitsin"</item>
- <item msgid="8175437057325747277">"Ei mitään"</item>
+ <item msgid="7095517796293767867">"Kiertoehdotus"</item>
+ <item msgid="8494159969042135235">"Ei mitään"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normaali"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Katso lisätietoja akun ja datan käytöstä napauttamalla"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Poistetaanko mobiilidata käytöstä?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Sovellus peittää käyttöoikeuspyynnön, joten Asetukset ei voi vahvistaa valintaasi."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Saako <xliff:g id="APP_0">%1$s</xliff:g> näyttää osia sovelluksesta <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Se voi lukea tietoja sovelluksesta <xliff:g id="APP">%1$s</xliff:g>."</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Se voi suorittaa toimintoja sovelluksessa <xliff:g id="APP">%1$s</xliff:g>."</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Salli sovelluksen <xliff:g id="APP">%1$s</xliff:g> näyttää osia mistä tahansa sovelluksesta"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Salli"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Estä"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 23a22e6..8f049cd 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Inicio"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menú"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accesibilidade"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Xira a pantalla"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Visión xeral"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Buscar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Cámara"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Seleccionar novo deseño de tarefas"</string>
<string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidade"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilidade co tamaño da pantalla."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Timbre silenciado"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Modo de traballo"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rexeitar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Rexeitouse <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Rexeitáronse todas as aplicacións recentes."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivado"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Non hai dispositivos sincronizados dispoñibles"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de batería"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Auriculares"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Entrada"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brillo"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Xirar automaticamente"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Xirar a pantalla automaticamente"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Conectando..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Conexión compartida"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona wifi"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificacións"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datos móbiles"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> usados"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Límite de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de traballo"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz nocturna"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Activación ao solpor"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Ata o amencer"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Activación (<xliff:g id="TIME">%s</xliff:g>)"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Ata: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"A opción NFC está desactivada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"A opción NFC está activada"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"A aplicación <xliff:g id="APP">%s</xliff:g> está desactivada no modo seguro"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Borrar todo"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Arrastrar aquí para usar a pantalla dividida"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dividir en horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dividir en vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dividir de xeito personalizado"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Cos controis de notificacións mellorados, podes asignarlles un nivel de importancia comprendido entre 0 e 5 ás notificacións dunha aplicación determinada. \n\n"<b>"Nivel 5"</b>" \n- Mostrar na parte superior da lista de notificacións. \n- Permitir interrupcións no modo de pantalla completa. \n- Mostrar sempre. \n\n"<b>"Nivel 4"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Mostrar sempre. \n\n"<b>"Nivel 3"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n\n"<b>"Nivel 2"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n- Non soar nin vibrar nunca. \n\n"<b>"Nivel 1"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n- Non soar nin vibrar nunca. \n- Ocultar na pantalla de bloqueo e na barra de estado. \n- Mostrar na parte inferior da lista de notificacións. \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas as notificacións da aplicación."</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notificacións"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Deixarás de ver estas notificacións"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Queres seguir mostrando estas notificacións?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Deter notificacións"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Continuar mostrando notificacións"</string>
@@ -658,7 +684,8 @@
<item msgid="1545641631806817203">"Portapapeis"</item>
<item msgid="5742013440802239414">"Código de teclas"</item>
<item msgid="8802889973626281575">"Conmutador do teclado"</item>
- <item msgid="8175437057325747277">"Ningún"</item>
+ <item msgid="7095517796293767867">"Suxestión de rotación"</item>
+ <item msgid="8494159969042135235">"Ningún tipo"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -782,4 +809,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Toca para obter información sobre o uso de datos e a batería"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Queres desactivar os datos móbiles?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Dado que unha aplicación se superpón sobre unha solicitude de permiso, a configuración non pode verificar a túa resposta."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Queres permitir que a aplicación <xliff:g id="APP_0">%1$s</xliff:g> mostre partes de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Pode ler información da aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Pode levar a cabo accións dentro da aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Permitir que a aplicación <xliff:g id="APP">%1$s</xliff:g> mostre partes de calquera aplicación"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Permitir"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Denegar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 22966a7..27d3ba8 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -33,13 +33,10 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ચાલુ"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"નોટિફિકેશનો"</string>
<string name="battery_low_title" msgid="6456385927409742437">"બૅટરી ઓછી છે"</string>
- <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
- <skip />
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"બૅટરી ઓછી છે. બૅટરી સેવર ચાલુ કરો"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી"</string>
- <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
- <skip />
- <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
- <skip />
+ <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી, તમારા વપરાશના આધારે લગભગ <xliff:g id="TIME">%s</xliff:g> બાકી છે"</string>
+ <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી, લગભગ <xliff:g id="TIME">%s</xliff:g> બાકી"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> બાકી. બૅટરી સેવર ચાલુ છે."</string>
<string name="invalid_charger" msgid="4549105996740522523">"USB ચાર્જિંગ સમર્થિત નથી.\nફક્ત આપવામાં આવેલ ચાર્જરનો ઉપયોગ કરો."</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"USB ચાર્જિંગ સમર્થિત નથી."</string>
@@ -73,22 +70,15 @@
<string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"હાલમાં આ ઉપકરણમાં સાઇન ઇન થયેલ વપરાશકર્તા USB ડિબગીંગ ચાલુ કરી શકતા નથી. આ સુવિધાનો ઉપયોગ કરવા માટે પ્રાથમિક વપરાશકર્તા પર સ્વિચ કરો."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"સ્ક્રીન ભરવા માટે ઝૂમ કરો"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"સ્ક્રીન ભરવા માટે ખેંચો"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"સ્ક્રીનશૉટ"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
- <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
- <skip />
- <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
- <skip />
- <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
- <skip />
- <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
- <skip />
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"સ્ક્રીનશૉટ સાચવવામાં આવી રહ્યો છે"</string>
+ <string name="screenshot_saved_title" msgid="5637073968117370753">"સ્ક્રીનશૉટ સાચવ્યો"</string>
+ <string name="screenshot_saved_text" msgid="7574667448002050363">"તમારા સ્ક્રીનશૉટને જોવા માટે ટૅપ કરો"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"સ્ક્રીનશૉટ કૅપ્ચર કરી શકાયો નથી"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"સ્ક્રીનશૉટ સાચવવામાં સમસ્યા આવી"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"મર્યાદિત સ્ટોરેજ સ્પેસને કારણે સ્ક્રીનશૉટ સાચવી શકાતો નથી"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશૉટ લેવાની મંજૂરી નથી"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ફાઇલ ટ્રાન્સફર વિકલ્પો"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"મીડિયા પ્લેયર તરીકે માઉન્ટ કરો (MTP)"</string>
@@ -98,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"હોમ"</string>
<string name="accessibility_menu" msgid="316839303324695949">"મેનુ"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"ઍક્સેસિબિલિટી"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"સ્ક્રીન ફેરવો"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"ઝલક"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"શોધો"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"કૅમેરો"</string>
@@ -112,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"કૅમેરો ખોલો"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"નવું કાર્ય લેઆઉટ પસંદ કરો"</string>
<string name="cancel" msgid="6442560571259935130">"રદ કરો"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"સુસંગતતા ઝૂમ બટન."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"નાનીથી મોટી સ્ક્રીન પર ઝૂમ કરો."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"બ્લૂટૂથ કનેક્ટ થયું."</string>
@@ -188,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"રિંગર શાંત છે."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"કાર્ય મોડ"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> કાઢી નાખો."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> કાઢી નાખી."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"તમામ તાજેતરની ઍપ્લિકેશનો કાઢી નાખી."</string>
@@ -285,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"બ્લૂટૂથ (<xliff:g id="NUMBER">%d</xliff:g> ઉપકરણો)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"બ્લૂટૂથ બંધ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"કોઈ જોડી કરેલ ઉપકરણો ઉપલબ્ધ નથી"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> બૅટરી"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ઑડિઓ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"હૅડસેટ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ઇનપુટ"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"તેજ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"આપમેળે ફેરવો"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"સ્ક્રીનને આપમેળે ફેરવો"</string>
@@ -325,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"કનેક્ટ કરી રહ્યું છે..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ટિથરિંગ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"હૉટસ્પૉટ"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"નોટિફિકેશનો"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ફ્લેશલાઇટ"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"મોબાઇલ ડેટા"</string>
@@ -334,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> વાપર્યો"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> મર્યાદા"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ચેતવણી"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"કાર્ય મોડ"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"રાત્રિ પ્રકાશ"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"સૂર્યાસ્ત વખતે"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"સૂર્યોદય સુધી"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> વાગ્યે"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> સુધી"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC અક્ષમ કરેલ છે"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC સક્ષમ કરેલ છે"</string>
@@ -348,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"સુરક્ષિત મોડમાં <xliff:g id="APP">%s</xliff:g> અક્ષમ કરેલ છે."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"બધું સાફ કરો"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"વિભાજિત સ્ક્રીનનો ઉપયોગ કરવા માટે અહીં ખેંચો"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"આડું વિભક્ત કરો"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ઊભું વિભક્ત કરો"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"કસ્ટમ વિભક્ત કરો"</string>
@@ -571,27 +585,21 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"બંધ"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"પાવર સૂચના નિયંત્રણો સાથે, તમે ઍપની સૂચનાઓ માટે 0 થી 5 સુધીના મહત્વના સ્તરને સેટ કરી શકો છો. \n\n"<b>"સ્તર 5"</b>" \n- સૂચના સૂચિની ટોચ પર બતાવો \n- પૂર્ણ સ્ક્રીન અવરોધની મંજૂરી આપો \n- હંમેશાં ત્વરિત દૃષ્ટિ કરો \n\n"<b>"સ્તર 4"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- હંમેશાં ત્વરિત દૃષ્ટિ કરો \n\n"<b>"સ્તર 3"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n\n"<b>"સ્તર 2"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n- ક્યારેય અવાજ અથવા વાઇબ્રેટ કરશો નહીં \n\n"<b>"સ્તર 1"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધની મંજૂરી આપો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n- ક્યારેય અવાજ અથવા વાઇબ્રેટ કરશો નહીં \n- લૉક સ્ક્રીન અને સ્ટેટસ બારથી છુપાવો \n- સૂચના સૂચિના તળિયા પર બતાવો \n\n"<b>"સ્તર 0"</b>" \n- ઍપની તમામ સૂચનાઓને બ્લૉક કરો"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"નોટિફિકેશનો"</string>
- <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+ <string name="notification_channel_disabled" msgid="344536703863700565">"તમને હવેથી આ નોટિફિકેશન દેખાશે નહીં"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
<skip />
- <!-- no translation found for inline_keep_showing (8945102997083836858) -->
- <skip />
- <!-- no translation found for inline_stop_button (4172980096860941033) -->
- <skip />
- <!-- no translation found for inline_keep_button (6665940297019018232) -->
- <skip />
- <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
- <skip />
- <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
- <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"આ નોટિફિકેશન બતાવવાનું ચાલુ રાખીએ?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"નોટિફિકેશન બંધ કરો"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"બતાવવાનું ચાલુ રાખો"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"આ ઍપમાંથી નોટિફિકેશન બતાવવાનું ચાલુ રાખીએ?"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"આ નોટિફિકેશન બંધ કરી શકશો નહીં"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે સૂચના નિયંત્રણો ચાલુ છે"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે સૂચના નિયંત્રણો બંધ છે"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"આ ચૅનલની સૂચનાઓને મંજૂરી આપો"</string>
<string name="notification_more_settings" msgid="816306283396553571">"વધુ સેટિંગ્સ"</string>
- <!-- no translation found for notification_app_settings (420348114670768449) -->
- <skip />
+ <string name="notification_app_settings" msgid="420348114670768449">"કસ્ટમાઇઝ કરો"</string>
<string name="notification_done" msgid="5279426047273930175">"થઈ ગયું"</string>
- <!-- no translation found for inline_undo (558916737624706010) -->
- <skip />
+ <string name="inline_undo" msgid="558916737624706010">"રદ કરો"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"સૂચના નિયંત્રણો"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"સૂચના સ્નૂઝ કરવાના વિકલ્પો"</string>
@@ -674,7 +682,8 @@
<item msgid="1545641631806817203">"ક્લિપબોર્ડ"</item>
<item msgid="5742013440802239414">"કીકોડ"</item>
<item msgid="8802889973626281575">"કીબોર્ડ સ્વિચર"</item>
- <item msgid="8175437057325747277">"કોઈ નહીં"</item>
+ <item msgid="7095517796293767867">"રોટેશન માટે સૂચન"</item>
+ <item msgid="8494159969042135235">"કોઈ નહીં"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"સામાન્ય"</item>
@@ -798,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"બૅટરી અને ડેટા વપરાશ વિશેની વિગતો માટે ટૅપ કરો"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"મોબાઇલ ડેટા બંધ કરીએ?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"એક ઍપ પરવાનગી વિનંતીને અસ્પષ્ટ કરતી હોવાને કારણે, સેટિંગ્સ તમારા પ્રતિસાદને ચકાસી શકતી નથી."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g>ને <xliff:g id="APP_2">%2$s</xliff:g> સ્લાઇસ બતાવવાની મંજૂરી આપીએ?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- મારાથી <xliff:g id="APP">%1$s</xliff:g>ની માહિતી વાંચી શકાતી નથી"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- મારાથી <xliff:g id="APP">%1$s</xliff:g>ની અંદર ક્રિયાઓ કરી શકાતી નથી"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g>ને કોઈપણ ઍપના સ્લાઇસ બતાવવાની મંજૂરી આપો"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"મંજૂરી આપો"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"નકારો"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index ec37855..bb2e897 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"होम"</string>
<string name="accessibility_menu" msgid="316839303324695949">"मेन्यू"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"सुलभता"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"स्क्रीन घुमाएं"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"खास जानकारी"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"सर्च करें"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"कैमरा"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"कैमरा खोलें"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"नया कार्य लेआउट चुनें"</string>
<string name="cancel" msgid="6442560571259935130">"रद्द करें"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"संगतता ज़ूम बटन."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"छोटी से बड़ी स्क्रीन पर ज़ूम करें."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लूटूथ कनेक्ट किया गया."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"रिंगर मौन."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"कार्य मोड"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> को ख़ारिज करें."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खा़रिज कर दिया गया."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"हाल ही के सभी ऐप्लिकेशन ख़ारिज कर दिए गए."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लूटूथ (<xliff:g id="NUMBER">%d</xliff:g> डिवाइस)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब्लूटूथ बंद"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"कोई भी युग्मित डिवाइस उपलब्ध नहीं"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> बैटरी"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ऑडियो"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"हेडसेट"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"इनपुट"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"स्क्रीन की रोशनी"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"स्वत: घुमाएं"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"स्क्रीन स्वत: घुमाएं"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"कनेक्ट हो रहा है..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"टेदरिंग"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"हॉटस्पॉट"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"सूचनाएं"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ़्लैशलाइट"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"मोबाइल डेटा"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> उपयोग किया गया"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> सीमा"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"कार्य मोड"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"नाइट लाइट"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"शाम को चालू की जाएगी"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"सुबह तक चालू रहेगी"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> पर चालू की जाएगी"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> तक"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC बंद है"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC चालू है"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> को सुरक्षित-मोड में बंद किया गया."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Clear all"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"स्क्रीन के दो हिस्से में बंट जाने, स्पिल्ट स्क्रीन, का इस्तेमाल करने के लिए यहां खींचें और छोडें"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"क्षैतिज रूप से विभाजित करें"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"लम्बवत रूप से विभाजित करें"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"अपने मुताबिक बांटें"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"पावर सूचना नियंत्रण के ज़रिये, आप किसी ऐप की सूचना को उसकी अहमियत के हिसाब से 0 से 5 के लेवल पर सेट कर सकते हैं.\n\n"<b>"लेवल 5"</b>" \n- सूचना सूची में सबसे ऊपर दिखाएं \n- पूरे स्क्रीन को ढंकने की अनुमति दें \n- लगातार देखते रहें \n\n"<b>" लेवल 4"</b>" \n- पूरे स्क्रीन को ढंकें \n- लगातार देखते रहें \n\n"<b>"लेवल 3"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n-कभी भी न देखें \n\n"<b>"लेवल 2"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n\n"<b>"लेवल 1"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी न देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n- लॉक स्क्रीन और स्टेटस बार से छिपाएं \n- सूचना सूची के नीचे दिखाएं \n\n"<b>"लेवल 0"</b>" \n- ऐप्लिकेशन की सभी सूचनाएं रोक दें"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"सूचना"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"अब आपको ये सूचनाएं दिखाई नहीं देंगी"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"ये सूचनाएं दिखाना जारी रखें?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"सूचनाएं दिखाना बंद करें"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"दिखाना जारी रखें"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"क्लिपबोर्ड"</item>
<item msgid="5742013440802239414">"कुंजी कोड"</item>
<item msgid="8802889973626281575">"कीबोर्ड स्विचर"</item>
- <item msgid="8175437057325747277">"कोई नहीं"</item>
+ <item msgid="7095517796293767867">"घुमाने के सुझाव"</item>
+ <item msgid="8494159969042135235">"कोई नहीं"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"सामान्य"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"बैटरी और डेटा खर्च की जानकारी के लिए छूएं"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"मोबाइल डेटा बंद करना चाहते हैं?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"ऐप की वजह से मंज़ूरी के अनुरोध को समझने में दिक्कत हो रही है, इसलिए सेटिंग से आपके जवाब की पुष्टि नहीं हो पा रही है."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> को <xliff:g id="APP_2">%2$s</xliff:g> से हिस्से (स्लाइस) दिखाने की मंज़ूरी दें?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- यह <xliff:g id="APP">%1$s</xliff:g> से सूचना पढ़ सकता है"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- यह <xliff:g id="APP">%1$s</xliff:g> में कार्रवाई कर सकता है"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> को किसी भी ऐप्लिकेशन से हिस्से (स्लाइस) दिखाने की मंज़ूरी दें."</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"मंज़ूरी दें"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"नामंज़ूर करें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index cb62834..e8096f5 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -89,6 +89,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Početna"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Izbornik"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Pristupačnost"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Zakretanje zaslona"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Pregled"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Pretraži"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotoaparat"</string>
@@ -103,6 +104,12 @@
<string name="camera_label" msgid="7261107956054836961">"otvaranje fotoaparata"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Odaberite novi izgled zadataka"</string>
<string name="cancel" msgid="6442560571259935130">"Odustani"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb za kompatibilnost zumiranja."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zumiranje manjeg zaslona na veći."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth povezan."</string>
@@ -179,7 +186,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Softver zvona utišan."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Način rada"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbacivanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> odbačena je."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Odbačene su sve nedavne aplikacije."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (broj uređaja: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth isključen"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Upareni uređaji nisu dostupni"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> baterije"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Slušalice"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Unos"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Svjetlina"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatsko izmjenjivanje"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatsko zakretanje zaslona"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Povezivanje..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Dijeljenje veze"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Žarišna točka"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obavijesti"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svjetiljka"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilni podaci"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> iskorišteno"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ograničenje od <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Način rada"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noćno svjetlo"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Uključuje se u suton"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Do izlaska sunca"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je onemogućen"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je omogućen"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacija <xliff:g id="APP">%s</xliff:g> onemogućena je u sigurnom načinu."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Izbriši sve"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Povucite ovdje da biste upotrebljavali podijeljeni zaslon"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podijeli vodoravno"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podijeli okomito"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podijeli prilagođeno"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Napredne kontrole obavijesti omogućuju vam da postavite razinu važnosti za obavijesti aplikacije od 0 do 5. \n\n"<b>"Razina 5"</b>" \n– prikaži na vrhu popisa obavijesti \n– dopusti prekide prikaza na cijelom zaslonu \n– uvijek dopusti brzi pregled \n\n"<b>"Razina 4"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– uvijek dopusti brzi pregled \n\n"<b>"Razina 3"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled\n\n"<b>"Razina 2"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled \n– nikad ne emitiraj zvuk ni vibraciju \n\n"<b>"Razina 1"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled \n– nikad ne emitiraj zvuk ni vibraciju \n– ne prikazuj na zaključanom zaslonu i traci statusa \n– prikaži na dnu popisa obavijesti \n\n"<b>"Razina 0"</b>" \n– blokiraj sve obavijesti aplikacije"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Obavijesti"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Te vam se obavijesti više neće prikazivati"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Želite li da se obavijesti nastave prikazivati?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Zaustavi obavijesti"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Nastavi prikazivati"</string>
@@ -660,7 +686,8 @@
<item msgid="1545641631806817203">"Međuspremnik"</item>
<item msgid="5742013440802239414">"Kôd tipke"</item>
<item msgid="8802889973626281575">"Izmjena tipkovnice"</item>
- <item msgid="8175437057325747277">"Ništa"</item>
+ <item msgid="7095517796293767867">"Predložena rotacija"</item>
+ <item msgid="8494159969042135235">"Ništa"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Uobičajen"</item>
@@ -784,4 +811,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Dodirnite da biste vidjeli pojedinosti o potrošnji baterije i podatkovnom prometu"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Isključiti mobilne podatke?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Budući da aplikacija prekriva zahtjev za dopuštenje, Postavke ne mogu potvrditi vaš odgovor."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Želite li dopustiti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> da prikazuje isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– može čitati informacije aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– može vršiti radnje u aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Dopusti aplikaciji <xliff:g id="APP">%1$s</xliff:g> da prikazuje isječke iz bilo koje aplikacije"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Dopusti"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Odbij"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2069952..fa173d6 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Főoldal"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menü"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Kisegítő lehetőségek"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Képernyő elforgatása"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Áttekintés"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Keresés"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"kamera megnyitása"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Új feladatelrendezés kiválasztása"</string>
<string name="cancel" msgid="6442560571259935130">"Mégse"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kompatibilitási zoom gomb."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kicsinyítsen a nagyobb képernyőhöz."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth csatlakoztatva."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Csengő néma."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Munka mód"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"A(z) <xliff:g id="APP">%s</xliff:g> elvetése."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eltávolítva."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Az összes alkalmazás eltávolítva a nemrég használtak közül."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> eszköz)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth kikapcsolva"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nem áll rendelkezésre párosított eszköz"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Hang"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Bevitel"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Fényerő"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatikus elforgatás"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatikus képernyőforgatás"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Csatlakozás…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Megosztás"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Értesítések"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zseblámpa"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiladatok"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> felhasználva"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> korlát"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Figyelem! <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Munka mód"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Éjszakai fény"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Be: naplemente"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Napfelkeltéig"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Bekapcsolás: <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Eddig: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Az NFC ki van kapcsolva"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Az NFC be van kapcsolva"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"A(z) <xliff:g id="APP">%s</xliff:g> csökkentett módban ki van kapcsolva."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Összes törlése"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Húzza ide az osztott képernyő használatához"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Osztott vízszintes"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Osztott függőleges"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Osztott egyéni"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Az értesítési beállítások révén 0-tól 5-ig állíthatja be a fontossági szintet az alkalmazás értesítéseinél. \n\n"<b>"5. szint"</b>" \n– Megjelenítés az értesítési lista tetején \n– Teljes képernyő megszakításának engedélyezése \n– Mindig felugrik \n\n"<b>"4. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Mindig felugrik \n\n"<b>"3. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n\n"<b>"2. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n– Soha nincs hangjelzés és rezgés \n\n"<b>"1. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n– Soha nincs hangjelzés vagy rezgés \n– Elrejtés a lezárási képernyőről és az állapotsávról \n– Megjelenítés az értesítési lista alján \n\n"<b>"0. szint"</b>" \n– Az alkalmazás összes értesítésének letiltása"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Értesítések"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Többé nem jelennek meg ezek az értesítések"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Továbbra is megjelenjenek ezek az értesítések?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Értesítések letiltása"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Megjelenítés továbbra is"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Vágólap"</item>
<item msgid="5742013440802239414">"Billentyűkód"</item>
<item msgid="8802889973626281575">"Billentyűzetváltó"</item>
- <item msgid="8175437057325747277">"Nincs"</item>
+ <item msgid="7095517796293767867">"Forgatási javaslat"</item>
+ <item msgid="8494159969042135235">"Nincs"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normál"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Koppintson az akkumulátor- és adathasználat részleteinek megtekintéséhez"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Kikapcsolja a mobiladatokat?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Mivel az egyik alkalmazás eltakarja az engedélykérést, a Beállítások alkalmazás nem tudja ellenőrizni az Ön válaszát."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Engedélyezi a(z) <xliff:g id="APP_0">%1$s</xliff:g> alkalmazásnak, hogy részleteket mutasson a(z) <xliff:g id="APP_2">%2$s</xliff:g> alkalmazásból?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Információkat olvashat a(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazásból"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Műveleteket végezhet a(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazáson belül"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Engedélyezi a(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazásnak, hogy bármely alkalmazásból részletet jelenítsen meg"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Engedélyezés"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Elutasítás"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 0656f0c..33d8821 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Տուն"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Ցանկ"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Մատչելիություն"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Պտտել էկրանը"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Համատեսք"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Որոնել"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Տեսախցիկ"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"բացել ֆոտոխցիկը"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Ընտրել առաջադրանքի նոր դասավորություն"</string>
<string name="cancel" msgid="6442560571259935130">"Չեղարկել"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Համատեղելիության խոշորացման կոճակը:"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Դիտափոխել փոքրից ավելի մեծ էկրան:"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-ը միացված է:"</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Զանգակը լռեցված է:"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Աշխատանքային ռեժիմ"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Անտեսել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>-ը անտեսված է:"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Բոլոր վերջին հավելվածները հեռացվել են ցուցակից:"</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> սարք)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth-ն անջատված է"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Զուգակցված սարքեր չկան"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Աուդիո"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Ականջակալ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Մուտքագրում"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Պայծառություն"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Ինքնապտտում"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Ավտոմատ պտտել էկրանը"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Միանում է..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Մոդեմի ռեժիմ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Թեժ կետ"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ծանուցումներ"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Լապտեր"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Բջջային ինտերնետ"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Օգտագործված է՝ <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Սահմանաչափ՝ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> զգուշացում"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Աշխատանքային ռեժիմ"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Գիշերային լույս"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Կմիացվի մայրամուտին"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Մինչև լուսաբաց"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Կմիացվի ժամը <xliff:g id="TIME">%s</xliff:g>-ին"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Մինչև <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC-ն անջատված է"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC-ն միացված է"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> հավելվածը անվտանգ ռեժիմում անջատված է:"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Մաքրել բոլորը"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Քաշեք այստեղ՝ էկրանի տրոհումն օգտագործելու համար"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Հորիզոնական տրոհում"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ուղղահայաց տրոհում"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Հատուկ տրոհում"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Ծանուցումների ընդլայնված կառավարման օգնությամբ կարող եք յուրաքանչյուր հավելվածի ծանուցումների համար նշանակել կարևորության աստիճան՝ 0-5 սահմաններում: \n\n"<b>"5-րդ աստիճան"</b>" \n- Ցուցադրել ծանուցումների ցանկի վերևում \n- Թույլատրել լիաէկրան ընդհատումները \n- Միշտ ցուցադրել կարճ ծանուցումները \n\n"<b>"4-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Միշտ ցուցադրել կարճ ծանուցումները \n\n"<b>"3-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n\n"<b>"2-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n- Անջատել ձայնը և թրթռումը \n\n"<b>"1-ին աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n- Անջատել ձայնը և թրթռումը \n- Չցուցադրել կողպէկրանում և կարգավիճակի գոտում \n- Ցուցադրել ծանուցումների ցանկի ներքևում \n\n"<b>"0-րդ աստիճան"</b>\n"- Արգելափակել հավելվածի բոլոր ծանուցումները"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Ծանուցումներ"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Դուք այլևս չեք ստանա այս ծանուցումները"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Ցուցադրե՞լ այս ծանուցումները։"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Չցուցադրել ծանուցումներ"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Ցուցադրել"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Սեղմատախտակ"</item>
<item msgid="5742013440802239414">"Ստեղնային կոդ"</item>
<item msgid="8802889973626281575">"Ստեղնաշարի փոխարկիչ"</item>
- <item msgid="8175437057325747277">"Չկան"</item>
+ <item msgid="7095517796293767867">"Պտույտ"</item>
+ <item msgid="8494159969042135235">"Ոչ մեկը"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Սովորական"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Հպեք՝ մարտկոցի և թրաֆիկի մանրամասները տեսնելու համար"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Անջատե՞լ բջջային ինտերնետը։"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Քանի որ ներածումն արգելափակված է ինչ-որ հավելվածի կողմից, Կարգավորումները չեն կարող հաստատել ձեր պատասխանը:"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Թույլատրե՞լ <xliff:g id="APP_0">%1$s</xliff:g> հավելվածին ցուցադրել հատվածներ <xliff:g id="APP_2">%2$s</xliff:g> հավելվածից"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Կարող է կարդալ տեղեկություններ <xliff:g id="APP">%1$s</xliff:g> հավելվածից"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Կարող է կատարել գործողություններ <xliff:g id="APP">%1$s</xliff:g> հավելվածում"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Թույլատրել <xliff:g id="APP">%1$s</xliff:g> հավելվածին ցուցադրել հատվածներ ցանկացած հավելվածից"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Թույլատրել"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Մերժել"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 6d08308..7ed6234 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Utama"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Aksesibilitas"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Putar layar"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Ringkasan"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Telusuri"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"buka kamera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Pilih tata letak tugas baru"</string>
<string name="cancel" msgid="6442560571259935130">"Batal"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tombol perbesar/perkecil kompatibilitas."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Perbesar dari layar kecil ke besar."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tersambung."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Pendering senyap."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Mode kerja"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Menyingkirkan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> disingkirkan."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaru telah ditutup."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Perangkat)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Mati"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Perangkat yang disandingkan tak tersedia"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Masukan"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Kecerahan"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotasi otomatis"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Putar layar otomatis"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Menyambung..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Menambatkan"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifikasi"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampu senter"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Data seluler"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> digunakan"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Batas <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Peringatan <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Mode kerja"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Profil kerja"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Notifikasi & aplikasi dinonaktifkan"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Cahaya Malam"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Aktif saat matahari terbenam"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Sampai matahari terbit"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Aktif pada <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Sampai <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC dinonaktifkan"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC diaktifkan"</string>
@@ -337,7 +357,8 @@
<string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulai <xliff:g id="APP">%s</xliff:g>."</string>
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> dinonaktifkan dalam mode aman."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Hapus semua"</string>
- <string name="recents_drag_hint_message" msgid="2649739267073203985">"Seret ke sini untuk menggunakan layar terpisah"</string>
+ <string name="recents_drag_hint_message" msgid="2649739267073203985">"Tarik ke sini untuk menggunakan layar terpisah"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Geser ke atas untuk beralih aplikasi"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Pisahkan Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pisahkan Vertikal"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pisahkan Khusus"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Dengan kontrol notifikasi daya, Anda dapt menyetel level kepentingan notifikasi aplikasi dari 0 sampai 5. \n\n"<b>"Level 5"</b>" \n- Muncul di atas daftar notifikasi \n- Izinkan interupsi layar penuh \n- Selalu intip pesan \n\n"<b>"Level 4"</b>" \n- Jangan interupsi layar penuh \n- Selalu intip pesan \n\n"<b>"Level 3"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n\n"<b>"Level 2"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n- Tanpa suara dan getaran \n\n"<b>"Level 1"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n- Tanpa suara atau getaran \n- Sembunyikan dari layar kunci dan bilah status \n- Muncul di bawah daftar notifikasi \n\n"<b>"Level 0"</b>" \n- Blokir semua notifikasi dari aplikasi"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notifikasi"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Anda tidak akan melihat notifikasi ini lagi"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Terus tampilkan notifikasi ini?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Hentikan notifikasi"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Terus tampilkan"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Papan klip"</item>
<item msgid="5742013440802239414">"Kode tombol"</item>
<item msgid="8802889973626281575">"Pengalih keyboard"</item>
- <item msgid="8175437057325747277">"Tidak ada"</item>
+ <item msgid="7095517796293767867">"Saran rotasi"</item>
+ <item msgid="8494159969042135235">"Tak Ada"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Biasa"</item>
@@ -674,8 +698,8 @@
<string name="right_keycode" msgid="708447961000848163">"Kode tombol kanan"</string>
<string name="left_icon" msgid="3096287125959387541">"Ikon kiri"</string>
<string name="right_icon" msgid="3952104823293824311">"Ikon kanan"</string>
- <string name="drag_to_add_tiles" msgid="7058945779098711293">"Seret untuk menambahkan ubin"</string>
- <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Seret ke sini untuk menghapus"</string>
+ <string name="drag_to_add_tiles" msgid="7058945779098711293">"Tarik untuk menambahkan ubin"</string>
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Tarik ke sini untuk menghapus"</string>
<string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
<string name="tuner_time" msgid="6572217313285536011">"Waktu"</string>
<string-array name="clock_options">
@@ -729,7 +753,7 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalkan"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Tutup"</string>
<string name="pip_phone_settings" msgid="8080777499521528521">"Setelan"</string>
- <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Seret ke bawah untuk menutup"</string>
+ <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Tarik ke bawah untuk menutup"</string>
<string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> adalah picture-in-picture"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, tap untuk membuka setelan dan menonaktifkannya."</string>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap untuk melihat detail penggunaan baterai dan data"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Nonaktifkan data seluler?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Karena sebuah aplikasi menghalangi permintaan izin, Setelan tidak dapat memverifikasi respons Anda."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Izinkan <xliff:g id="APP_0">%1$s</xliff:g> menampilkan potongan <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Dapat membaca informasi dari <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Dapat mengambil tindakan di dalam <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Izinkan <xliff:g id="APP">%1$s</xliff:g> menampilkan potongan dari aplikasi apa pun"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Izinkan"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Tolak"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index dbdb273..1e0cd63 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Heim"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Valmynd"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Aðgengi"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Snúa skjánum"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Yfirlit"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Leita"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Myndavél"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"opna myndavél"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Velja nýtt útlit verkefna"</string>
<string name="cancel" msgid="6442560571259935130">"Hætta við"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Hnappur fyrir samhæfisaðdrátt."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aðlaga forrit fyrir lítinn skjá að stærri skjá."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tengt."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Engin hringing."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Vinnustilling"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hunsa <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> vísað frá."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Öll nýleg forrit fjarlægð."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> tæki)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Slökkt á Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Engin pöruð tæki til staðar"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> rafhlöðuhleðsla"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Hljóð"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Höfuðtól"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Inntak"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Birtustig"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Sjálfvirkur snúningur"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Snúa skjá sjálfkrafa"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Tengist..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tjóðrun"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Heitur reitur"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Tilkynningar"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Vasaljós"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Farsímagögn"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> notuð"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> hámark"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> viðvörun"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Vinnustilling"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Næturljós"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Kveikt við sólsetur"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Til sólarupprásar"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Kveikt klukkan <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Til klukkan <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Slökkt á NFC"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Kveikt á NFC"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Slökkt er á <xliff:g id="APP">%s</xliff:g> í öruggri stillingu."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Hreinsa allt"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Dragðu hingað til að skipta skjánum"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Lárétt skipting"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Lóðrétt skipting"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Sérsniðin skipting"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Með orkutilkynningastýringum geturðu stillt mikilvægi frá 0 upp í 5 fyrir tilkynningar forrita. \n\n"<b>"Stig 5"</b>" \n- Sýna efst á tilkynningalista \n- Leyfa truflun þegar birt er á öllum skjánum \n- Kíkja alltaf \n\n"<b>"Stig 4"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja alltaf \n\n"<b>"Stig 3"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n\n"<b>"Stig 2"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n- Slökkva á hljóði og titringi \n\n"<b>"Stig 1"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n- Slökkva á hljóði og titringi \n- Fela á lásskjá og stöðustiku \n- Sýna neðst á tilkynningalista \n\n"<b>"Stig 0"</b>" \n- Setja allar tilkynningar frá forriti á bannlista"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Tilkynningar"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Þú munt ekki sjá þessar tilkynningar aftur"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Sýna áfram þessar tilkynningar?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Stöðva tilkynningar"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Sýna áfram"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Klippiborð"</item>
<item msgid="5742013440802239414">"Lykilkóði"</item>
<item msgid="8802889973626281575">"Lyklaborðsval"</item>
- <item msgid="8175437057325747277">"Ekkert"</item>
+ <item msgid="7095517796293767867">"Tillaga um snúning"</item>
+ <item msgid="8494159969042135235">"Ekkert"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Venjulegt"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Ýttu til að fá upplýsingar um rafhlöðu- og gagnanotkun"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Slökkva á farsímagögnum?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Stillingar geta ekki staðfest svarið þitt vegna þess að forrit er að fela heimildarbeiðni."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Viltu leyfa <xliff:g id="APP_0">%1$s</xliff:g> að sýna sneiðar úr <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Það getur lesið upplýsingar úr <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Það getur gripið til aðgerða í <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Leyfa <xliff:g id="APP">%1$s</xliff:g> að sýna sneiðar úr hvaða forriti sem er"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Leyfa"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Hafna"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 642a8dc..880da63 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Home"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accessibilità"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Ruota lo schermo"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Panoramica"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Cerca"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotocamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"apri fotocamera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Seleziona un nuovo layout per le attività"</string>
<string name="cancel" msgid="6442560571259935130">"Annulla"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Pulsante zoom compatibilità."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom inferiore per schermo più grande."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth collegato."</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Suoneria silenziosa."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Modalità Lavoro"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Elimina <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eliminata."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tutte le applicazioni recenti sono state rimosse."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivi)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth spento"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nessun dispositivo accoppiato disponibile"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Auricolare"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Ingresso"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminosità"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotazione automatica"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Rotazione automatica dello schermo"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Connessione..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifiche"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Torcia"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dati mobili"</string>
@@ -326,8 +341,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilizzati"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limite di <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avviso <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modalità Lavoro"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Profilo di lavoro"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Le app e le notifiche sono disattivate"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luminosità notturna"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Attivata al tramonto"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Fino all\'alba"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Attivata alle ore <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Fino alle ore <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC non attiva"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC attiva"</string>
@@ -340,6 +360,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"L\'app <xliff:g id="APP">%s</xliff:g> è stata disattivata in modalità provvisoria."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Cancella tutto"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Trascina qui per utilizzare la modalità Schermo diviso"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Scorri verso l\'alto per passare ad altre app"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisione in orizzontale"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisione in verticale"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisione personalizzata"</string>
@@ -564,6 +585,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"I controlli di gestione delle notifiche ti consentono di impostare un livello di importanza compreso tra 0 e 5 per le notifiche di un\'app. \n\n"<b>"Livello 5"</b>" \n- Mostra in cima all\'elenco di notifiche \n- Consenti l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 4"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 3"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n\n"<b>"Livello 2"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n\n"<b>"Livello 1"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n- Nascondi da schermata di blocco e barra di stato \n- Mostra in fondo all\'elenco di notifiche \n\n"<b>"Livello 0"</b>" \n- Blocca tutte le notifiche dell\'app"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notifiche"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Non vedrai più queste notifiche"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Continuare a ricevere queste notifiche?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Interrompi la ricezione di notifiche"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Continua a mostrare"</string>
@@ -658,7 +681,8 @@
<item msgid="1545641631806817203">"Appunti"</item>
<item msgid="5742013440802239414">"Keycode"</item>
<item msgid="8802889973626281575">"Selettore tastiera"</item>
- <item msgid="8175437057325747277">"Nessuno"</item>
+ <item msgid="7095517796293767867">"Suggerimento per la rotazione"</item>
+ <item msgid="8494159969042135235">"Nessuno"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normale"</item>
@@ -782,4 +806,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tocca per conoscere i dettagli sull\'utilizzo dei dati e della batteria"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Disattivare i dati mobili?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Un\'app sta oscurando una richiesta di autorizzazione, pertanto Impostazioni non può verificare la tua risposta."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Vuoi consentire all\'app <xliff:g id="APP_0">%1$s</xliff:g> di mostrare porzioni dell\'app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Può leggere informazioni dell\'app <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Può compiere azioni nell\'app <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Consenti all\'app <xliff:g id="APP">%1$s</xliff:g> di mostrare porzioni di qualsiasi app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Consenti"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Nega"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 4fd68c2..b6a153e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -35,7 +35,7 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"מתמשך"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"הודעות"</string>
<string name="battery_low_title" msgid="6456385927409742437">"עוצמת הסוללה נמוכה"</string>
- <string name="battery_low_title_hybrid" msgid="6268991275887381595">"עוצמת הסוללה נמוכה. כדאי להפעיל את מצב החיסכון בסוללה"</string>
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"הסוללה חלשה: כדאי להפעיל את מצב החיסכון בסוללה"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>, נשארו בערך <xliff:g id="TIME">%s</xliff:g> על סמך השימוש במכשיר"</string>
<string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>, נשארו בערך <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -78,9 +78,9 @@
<string name="screenshot_saving_text" msgid="2545047868936087248">"מתבצעת שמירה של צילום המסך"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"צילום המסך נשמר"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"אפשר להקיש כדי להציג את צילום המסך"</string>
- <string name="screenshot_failed_title" msgid="9096484883063264803">"לא ניתן לבצע צילום מסך"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"לא ניתן היה לבצע צילום מסך"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"התגלתה בעיה בשמירת צילום המסך"</string>
- <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"לא ניתן לשמור צילום מסך עקב שטח אחסון מוגבל"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"לא היה מספיק מקום לשמור את צילום המסך"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"האפליקציה או הארגון שלך אינם מתירים ליצור צילומי מסך"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"אפשרויות העברת קבצים ב-USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"טען כנגן מדיה (MTP)"</string>
@@ -90,6 +90,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"בית"</string>
<string name="accessibility_menu" msgid="316839303324695949">"תפריט"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"נגישות"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"סיבוב המסך"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"סקירה"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"חיפוש"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"מצלמה"</string>
@@ -104,6 +105,12 @@
<string name="camera_label" msgid="7261107956054836961">"פתח את המצלמה"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"בחר פריסה חדשה להצגת משימות"</string>
<string name="cancel" msgid="6442560571259935130">"ביטול"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"לחצן מרחק מתצוגה של תאימות."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"שנה מרחק מתצוגה של מסך קטן לגדול יותר."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth מחובר."</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"צלצול שקט."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"מצב עבודה"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"סגור את <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> נדחה."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"כל האפליקציות האחרונות נסגרו."</string>
@@ -279,6 +287,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> מכשירים)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth מופסק"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"אין מכשירים מותאמים זמינים"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> סוללה"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"אודיו"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"אוזניות"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"קלט"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"בהירות"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"סיבוב אוטומטי"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"סיבוב אוטומטי של המסך"</string>
@@ -319,6 +331,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"מתחבר..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"שיתוף אינטרנט בין ניידים"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"נקודה לשיתוף אינטרנט"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"הודעות"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"פנס"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"חבילת גלישה"</string>
@@ -328,8 +343,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> בשימוש"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"הגבלה של <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"אזהרה - <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"מצב עבודה"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"תאורת לילה"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"מופעל בשקיעה"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"עד הזריחה"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"מופעל בשעה <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"עד <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC מושבת"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC מופעל"</string>
@@ -342,6 +364,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> מושבת במצב בטוח."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"נקה הכל"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"גרור לכאן כדי להשתמש במסך מפוצל"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"פיצול אופקי"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"פיצול אנכי"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"פיצול מותאם אישית"</string>
@@ -565,11 +589,13 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"כבוי"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"בעזרת פקדים של הודעות הפעלה, תוכל להגדיר רמת חשיבות מ-0 עד 5 להודעות אפליקציה. \n\n"<b>"רמה 5"</b>" \n- הצג בראש רשימת ההודעות \n- אפשר הפרעה במסך מלא \n- תמיד אפשר הצצה \n\n"<b>"רמה 4"</b>" \n- מנע הפרעה במסך מלא \n- תמיד אפשר הצצה \n\n"<b>"רמה 3"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n\n"<b>"רמה 2"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n- אף פעם אל תאפשר קול ורטט \n\n"<b>"רמה 1"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n- אף פעם אל תאפשר קול ורטט \n- הסתר ממסך הנעילה ומשורת הסטטוס \n- הצג בתחתית רשימת ההודעות \n\n"<b>"רמה 0"</b>" \n- חסום את כל ההודעות מהאפליקציה"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"הודעות"</string>
- <string name="notification_channel_disabled" msgid="344536703863700565">"לא תראה יותר את ההודעות האלה"</string>
- <string name="inline_keep_showing" msgid="8945102997083836858">"להמשיך להציג את ההודעות האלה?"</string>
- <string name="inline_stop_button" msgid="4172980096860941033">"הפסקת הודעות"</string>
- <string name="inline_keep_button" msgid="6665940297019018232">"להמשיך להציג"</string>
- <string name="inline_keep_showing_app" msgid="1723113469580031041">"להמשיך להציג הודעות מהאפליקציה הזאת?"</string>
+ <string name="notification_channel_disabled" msgid="344536703863700565">"ההודעות האלה לא יוצגו לך יותר"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"שנמשיך להציג לך את ההודעות האלה?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"לא, אל תמשיכו"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"כן, המשיכו"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"שנמשיך להציג לך הודעות מהאפליקציה הזאת?"</string>
<string name="notification_unblockable_desc" msgid="1037434112919403708">"לא ניתן לכבות את ההודעות האלה"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"פקדי ההודעות של <xliff:g id="APP_NAME">%1$s</xliff:g> נפתחו"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"פקדי ההודעות של <xliff:g id="APP_NAME">%1$s</xliff:g> נסגרו"</string>
@@ -664,7 +690,8 @@
<item msgid="1545641631806817203">"לוח"</item>
<item msgid="5742013440802239414">"קוד מפתח"</item>
<item msgid="8802889973626281575">"מחליף מקלדת"</item>
- <item msgid="8175437057325747277">"ללא"</item>
+ <item msgid="7095517796293767867">"הצעת סיבוב"</item>
+ <item msgid="8494159969042135235">"אף אחת"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"רגילה"</item>
@@ -788,4 +815,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"הקש לקבלת פרטים על צריכה של נתונים וסוללה"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"לכבות את חבילת הגלישה?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"יש אפליקציה שמסתירה את בקשת ההרשאה, ולכן להגדרות אין אפשרות לאמת את התשובה."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"האם לאפשר ל-<xliff:g id="APP_0">%1$s</xliff:g> להציג חלקים מ-<xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- תהיה לה אפשרות לקרוא מידע מ-<xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- תהיה לה יכולת לנקוט פעולה בתוך <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"יש לאשר ל-<xliff:g id="APP">%1$s</xliff:g> להראות חלקים מכל אפליציה שהיא"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"אני רוצה לאשר"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"אני לא מרשה"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 09c978f..3a7fc50 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"საწყისი"</string>
<string name="accessibility_menu" msgid="316839303324695949">"მენიუ"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"მარტივი წვდომა"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"ეკრანის შეტრიალება"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"მიმოხილვა"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ძიება"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"კამერა"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"კამერის გახსნა"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"ახალი ამოცანის განლაგების არჩევა"</string>
<string name="cancel" msgid="6442560571259935130">"გაუქმება"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"თავსებადი მასშტაბირების ღილაკი."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"შეცვალეთ პატარა ეკრანი უფრო დიდით."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth დაკავშირებულია."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"უხმო რეჟიმი."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"სამსახურის რეჟიმი"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-ის უგულებელყოფა."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ამოშლილია სიიდან."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ყველა ბოლო აპლიკაცია გაუქმდა."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> მოწყობილობა)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth გამორთულია"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"დაწყვილებული მოწყობილობები მიუწვდომელია"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ბატარეა"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"აუდიო"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"ყურსაცვამი"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"შეყვანა"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"სიკაშკაშე"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ავტოროტაცია"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"ეკრანის ავტომატური შეტრიალება"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"დაკავშირება..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ტეტერინგი"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"წვდომის წერტილი"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"შეტყობინებები"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ფანარი"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"მობილური ინტერნეტი"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"გამოყენებულია: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"ლიმიტი: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> გაფრთხილება"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"სამსახურის რეჟიმი"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"ღამის განათება"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"ჩაირთოს მზის ჩასვლისას"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"მზის ამოსვლამდე"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"ჩაირთოს <xliff:g id="TIME">%s</xliff:g>-ზე"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g>-მდე"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC გათიშულია"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ჩართულია"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> გათიშულია უსაფრთხო რეჟიმში."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"ყველას გასუფთავება"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"ეკრანის გასაყოფად, ჩავლებით გადმოიტანეთ აქ"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ჰორიზონტალური გაყოფა"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ვერტიკალური გაყოფა"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ინდივიდუალური გაყობა"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"შეტყობინებების მართვის საშუალებების მეშვეობით, შეგიძლიათ განსაზღვროთ აპის შეტყობინებების მნიშვნელობის დონე 0-დან 5-მდე დიაპაზონში. \n\n"<b>"დონე 5"</b>" \n— შეტყობინებათა სიის თავში ჩვენება \n— სრულეკრანიანი რეჟიმის შეფერხების დაშვება \n— ეკრანზე ყოველთვის გამოჩენა \n\n"<b>"დონე 4"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე ყოველთვის გამოჩენა \n\n"<b>"დონე 3"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n\n"<b>"დონე 2"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n— ხმისა და ვიბრაციის აღკვეთა \n\n"<b>"დონე 1"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n— ხმისა და ვიბრაციის აღკვეთა \n— ჩაკეტილი ეკრანიდან და სტატუსის ზოლიდან დამალვა \n— შეტყობინებათა სიის ბოლოში ჩვენება \n\n"<b>"დონე 0"</b>" \n— აპის ყველა შეტყობინების დაბლოკვა"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"შეტყობინებები"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"ამ შეტყობინებებს აღარ დაინახავთ"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"გაგრძელდეს ამ შეტყობინებათა ჩვენება?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"შეტყობინებების შეწყვეტა"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"ჩვენების გაგრძელება"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"გაცვლის ბუფერი"</item>
<item msgid="5742013440802239414">"კლავიშის კოდი"</item>
<item msgid="8802889973626281575">"კლავიატურის გადამრთველი"</item>
- <item msgid="8175437057325747277">"არცერთი"</item>
+ <item msgid="7095517796293767867">"შეტრიალების შეთავაზება"</item>
+ <item msgid="8494159969042135235">"არც ერთი"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"ჩვეულებრივი"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"შეეხეთ ბატარეისა და მონაცემების მოხმარების შესახებ დეტალური ინფორმაციისთვის"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"გსურთ მობილური ინტერნეტის გამორთვა?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"ვინაიდან აპი ფარავს ნებართვის მოთხოვნას, პარამეტრების მიერ თქვენი პასუხი ვერ დასტურდება."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"ანიჭებთ ნებართვას <xliff:g id="APP_0">%1$s</xliff:g>-ს, აჩვენოს <xliff:g id="APP_2">%2$s</xliff:g>-ის ფრაგმენტები?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- მას შეუძლია ინფორმაციის <xliff:g id="APP">%1$s</xliff:g>-დან წაკითხვა"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- მას შეუძლია ქმედებების <xliff:g id="APP">%1$s</xliff:g>-ში განხორციელება"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g>-ისთვის ფრაგმენტების ნებისმიერი აპიდან ჩვენების ნების დართვა"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"დაშვება"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"უარყოფა"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 061a926..15d109c 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Үй"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Mәзір"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Арнайы мүмкіндіктер"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Экранды бұру"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Шолу"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Іздеу"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"камераны ашу"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Жаңа тапсырма пішімін таңдау"</string>
<string name="cancel" msgid="6442560571259935130">"Бас тарту"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Үйлесімділік ұлғайту түймесі."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Үлкендеу экранда кішірейту."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth қосылған."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Қоңырау үнсіз."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Жұмыс режимі"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> қолданбасынан бас тарту."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> алынып тасталған."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Барлық жақындағы қабылданбаған қолданбалар."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> құрылғылары)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth өшірулі"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Жұптасқан құрылғылар жоқ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Батарея деңгейі: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Aудио"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Гарнитура"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Кіріс"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Жарықтығы"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоматты түрде бұру"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Автоматты айналатын экран"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Қосылуда…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Тетеринг"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Хот-спот"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Хабарландырулар"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Қалта шам"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобильдік деректер"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> пайдаланылған"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> шегі"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> туралы ескерту"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Жұмыс режимі"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Жұмыс профилі"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Хабарландырулар мен қолданбалар өшірулі"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Түнгі жарық"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Күн батқанда қосу"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Күн шыққанға дейін"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> дейін"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC өшірулі"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC қосулы"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> қауіпсіз режимде өшіріледі."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Барлығын тазалау"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Бөлінген экранды пайдалану үшін осында сүйреңіз"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Қолданбаларға ауысу үшін жоғары сырғытыңыз"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Бөлінген көлденең"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Бөлінген тік"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Бөлінген теңшелетін"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Қуат хабарландыруының басқару элементтерімен қолданбаның хабарландырулары үшін 0-ден бастап 5-ке дейін маңыздылық деңгейін орнатуға болады. \n\n"<b>"5-деңгей"</b>" \n- Хабарландыру тізімінің ең басында көрсету \n- Толық экранға ашылуын рұқсат ету \n- Әрдайым қалқымалы хабарландыру түрінде көрсету \n\n"<b>"4-деңгей"</b>" \n- Толық экранға шығармау \n- Әрдайым қалқымалы хабарландыру түрінде көрсету \n\n"<b>"3-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n\n"<b>"2-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n- Ешқашан дыбыс және діріл шығармау \n\n"<b>"1-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n- Ешқашан дыбыс немесе діріл шығармау \n- Құлыпталған экраннан және күйін көрсету жолағынан жасыру \n- Хабарландыру тізімінің ең астында көрсету \n\n"<b>"0-деңгей"</b>" \n- Қолданбадағы барлық хабарландыруларға тыйым салу"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Хабарландырулар"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Хабарландырулар бұдан былай көрсетілмейді"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Хабарландырулар көрсетілсін бе?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Хабарландыруларға тыйым салу"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Көрсету"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Буфер"</item>
<item msgid="5742013440802239414">"Перне коды"</item>
<item msgid="8802889973626281575">"Пернетақта ауыстырғышы"</item>
- <item msgid="8175437057325747277">"Ешқандай"</item>
+ <item msgid="7095517796293767867">"Бұру ұсынысы"</item>
+ <item msgid="8494159969042135235">"Ешқайсысы"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Орташа"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Батарея мен деректер трафигі туралы білу үшін түртіңіз"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Мобильдік деректер өшірілсін бе?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Басқа қолданба рұқсат сұрауын жасырып тұрғандықтан, параметрлер жауабыңызды растай алмайды."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> қолданбасына <xliff:g id="APP_2">%2$s</xliff:g> қолданбасының үзінділерін көрсетуге рұқсат берілсін бе?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Бұл <xliff:g id="APP">%1$s</xliff:g> қолданбасындағы ақпаратты оқи алады"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Бұл <xliff:g id="APP">%1$s</xliff:g> қолданбасында әрекет ете алады"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына кез келген қолданбаның үзіндісін көрсетуге рұқсат беру"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Рұқсат беру"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Тыйым салу"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 175e10c..77fc137 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"គេហទំព័រ"</string>
<string name="accessibility_menu" msgid="316839303324695949">"ម៉ឺនុយ"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"ភាពងាយស្រួល"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"បង្វិលអេក្រង់"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"ទិដ្ឋភាព"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ស្វែងរក"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ម៉ាស៊ីនថត"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"បើកម៉ាស៊ីនថត"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"ជ្រើសប្លង់ភារកិច្ចថ្មី"</string>
<string name="cancel" msgid="6442560571259935130">"បោះបង់"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ប៊ូតុងពង្រីកត្រូវគ្នា។"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ពង្រីក/បង្រួមអេក្រង់ពីទៅធំ"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"បានតភ្ជាប់ប៊្លូធូស។"</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"កម្មវិធីរោទ៍ស្ងាត់។"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"របៀបការងារ"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"បោះបង់ <xliff:g id="APP">%s</xliff:g> ។"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"កម្មវិធីថ្មីៗទាំងអស់ត្រូវបានបោះបង់។"</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ប៊្លូធូស (ឧបករណ៍ <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ប៊្លូធូសបានបិទ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"មិនមានឧបករណ៍ផ្គូផ្គងដែលអាចប្រើបាន"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"សំឡេង"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"កាស"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"បញ្ចូល"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ពន្លឺ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"បង្វិលស្វ័យប្រវត្តិ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"បង្វិលអេក្រង់ស្វ័យប្រវត្តិ"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"កំពុងតភ្ជាប់..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ការភ្ជាប់"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ហតស្ប៉ត"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"ការជូនដំណឹង"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ពិល"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ទិន្នន័យទូរសព្ទចល័ត"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"បានប្រើ <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"ដែនកំណត់ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ការព្រមាន"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"របៀបការងារ"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"កម្រងព័ត៌មានការងារ"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"ការជូនដំណឹង និងកម្មវិធីត្រូវបានបិទ"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"ពន្លឺពេលយប់"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"បើកនៅពេលថ្ងៃលិច"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"រហូតដល់ពេលថ្ងៃរះ"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"បើកនៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"រហូតដល់ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"បានបិទ NFC"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"បានបើក NFC"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ត្រូវបានបិទដំណើរការក្នុងរបៀបសុវត្ថិភាព"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"សម្អាតទាំងអស់"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"អូសនៅទីនេះដើម្បីប្រើអេក្រង់បំបែក"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"អូសឡើងលើដើម្បីប្តូរកម្មវិធី"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"បំបែកផ្តេក"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"បំបែកបញ្ឈរ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"បំបែកផ្ទាល់ខ្លួន"</string>
@@ -562,10 +583,12 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"ជាមួយអង្គគ្រប់គ្រងការជូនដំណឹងថាមពល អ្នកអាចកំណត់កម្រិតសំខាន់ពី 0 ទៅ 5 សម្រាប់ការជូនដំណឹងរបស់កម្មវិធី។ \n\n"<b>"កម្រិត 5"</b>" \n- បង្ហាញនៅផ្នែកខាងលើបញ្ជីជូនដំណឹង \n- អនុញ្ញាតការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 4"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 3"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 2"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n- មិនបន្លឺសំឡេង ឬញ័រ \n\n"<b>"កម្រិត 1"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n- មិនបន្លឺសំឡេង ឬញ័រ \n- លាក់ពីអេក្រង់ចាក់សោ និងរបារស្ថានភាព \n- បង្ហាញនៅផ្នែកខាងក្រោមបញ្ជីជូនដំណឹង \n\n"<b>"កម្រិត 0"</b>" \n- រារាំងការជូនដំណឹងទាំងអស់ពីកម្មវិធី"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"ការជូនដំណឹង"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"អ្នកនឹងមិនឃើញការជូនដំណឹងទាំងនេះទៀតទេ"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"បន្តបង្ហាញការជូនដំណឹងទាំងនេះ?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"បញ្ឈប់ការជូនដំណឹង"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"បន្តបង្ហាញ"</string>
- <string name="inline_keep_showing_app" msgid="1723113469580031041">"បន្តបង្ហាញការជូនដំណឹងសម្រាប់កម្មវិធីនេះ?"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"បន្តបង្ហាញការជូនដំណឹងពីកម្មវិធីនេះ?"</string>
<string name="notification_unblockable_desc" msgid="1037434112919403708">"មិនអាចបិទការជូនដំណឹងទាំងនេះបានទេ"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"ការគ្រប់គ្រងការជូនដំណឹងសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> បានបើក"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"ការគ្រប់គ្រងការជូនដំណឹងសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> បានបិទ"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"អង្គចងចាំ"</item>
<item msgid="5742013440802239414">"លេខកូដគ្រាប់ចុច"</item>
<item msgid="8802889973626281575">"កម្មវិធីប្តូរក្តារចុច"</item>
- <item msgid="8175437057325747277">"គ្មាន"</item>
+ <item msgid="7095517796293767867">"ការណែនាំការបង្វិល"</item>
+ <item msgid="8494159969042135235">"គ្មាន"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"ធម្មតា"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"ចុចដើម្បីមើលព័ត៌មានលម្អិតអំពីការប្រើប្រាស់ទិន្នន័យ និងថ្ម"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"បិទទិន្នន័យចល័ត?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"ការកំណត់មិនអាចផ្ទៀងផ្ទាត់ការឆ្លើយតបរបស់អ្នកបានទេ ដោយសារកម្មវិធីកំពុងបាំងសំណើសុំការអនុញ្ញាត។"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"អនុញ្ញាតឱ្យ <xliff:g id="APP_0">%1$s</xliff:g> បង្ហាញស្ថិតិប្រើប្រាស់របស់ <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- វាអាចអានព័ត៌មានពី <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- វាអាចធ្វើសកម្មភាពនៅក្នុង <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"អនុញ្ញាតឱ្យ <xliff:g id="APP">%1$s</xliff:g> បង្ហាញស្ថិតិប្រើប្រាស់ពីកម្មវិធីនានា"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"អនុញ្ញាត"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"បដិសេធ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 3ce5e76..a8b3007 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -33,13 +33,10 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"ಅಧಿಸೂಚನೆಗಳು"</string>
<string name="battery_low_title" msgid="6456385927409742437">"ಬ್ಯಾಟರಿ ಕಡಿಮೆ ಇದೆ"</string>
- <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
- <skip />
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"ಬ್ಯಾಟರಿ ಕಡಿಮೆ ಇದೆ. ಬ್ಯಾಟರಿ ಸೇವರ್ ಆನ್ ಮಾಡಿ"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಉಳಿದಿದೆ"</string>
- <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
- <skip />
- <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
- <skip />
+ <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಬಾಕಿ ಉಳಿದಿದೆ, ನಿಮ್ಮ ಬಳಕೆಯ ಆಧಾರದ ಮೇಲೆ <xliff:g id="TIME">%s</xliff:g> ಉಳಿದಿದೆ"</string>
+ <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಬಾಕಿ ಉಳಿದಿದೆ, <xliff:g id="TIME">%s</xliff:g> ಉಳಿದಿದೆ"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಉಳಿದಿದೆ. ಬ್ಯಾಟರಿ ಉಳಿತಾಯ ಆನ್ ಆಗಿದೆ."</string>
<string name="invalid_charger" msgid="4549105996740522523">"USB ಚಾರ್ಜಿಂಗ್ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ.\nಒದಗಿಸಿರುವ ಚಾರ್ಜರ್ ಮಾತ್ರ ಬಳಸಿ."</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"USB ಚಾರ್ಜಿಂಗ್ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ."</string>
@@ -73,22 +70,15 @@
<string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ಬಳಕೆದಾರರು ಪ್ರಸ್ತುತ ಈ ಸಾಧನಕ್ಕೆ ಸೈನ್ ಇನ್ ಮಾಡಿದ್ದಾರೆ USB ಡೀಬಗ್ ಮಾಡುವುದನ್ನು ಆನ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲು, ಪ್ರಾಥಮಿಕ ಬಳಕೆದಾರರಿಗೆ ಬದಲಾಯಿಸಿ."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"ಪರದೆ ತುಂಬಿಸಲು ಝೂಮ್ ಮಾಡು"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"ಪರದೆ ತುಂಬಿಸಲು ವಿಸ್ತಾರಗೊಳಿಸು"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"ಸ್ಕ್ರೀನ್ಶಾಟ್"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
- <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
- <skip />
- <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
- <skip />
- <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
- <skip />
- <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
- <skip />
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ"</string>
+ <string name="screenshot_saved_title" msgid="5637073968117370753">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ"</string>
+ <string name="screenshot_saved_text" msgid="7574667448002050363">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ಶಾಟ್ ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸುವಲ್ಲಿ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ಸಂಸ್ಥೆಯು ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳನ್ನು ತೆಗೆಯುವುದನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ಫೈಲ್ ವರ್ಗಾವಣೆ ಆಯ್ಕೆಗಳು"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"ಮೀಡಿಯಾ ಪ್ಲೇಯರ್ ರೂಪದಲ್ಲಿ ಅಳವಡಿಸಿ (MTP)"</string>
@@ -98,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"ಮುಖಪುಟ"</string>
<string name="accessibility_menu" msgid="316839303324695949">"ಮೆನು"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"ಪ್ರವೇಶಿಸುವಿಕೆ"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"ಪರದೆಯನ್ನು ತಿರುಗಿಸಿ"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"ಸಮಗ್ರ ನೋಟ"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ಹುಡುಕಿ"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ಕ್ಯಾಮರಾ"</string>
@@ -112,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"ಕ್ಯಾಮರಾ ತೆರೆಯಿರಿ"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"ಹೊಸ ಕಾರ್ಯ ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="cancel" msgid="6442560571259935130">"ರದ್ದುಮಾಡಿ"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ಹೊಂದಾಣಿಕೆಯ ಝೂಮ್ ಬಟನ್."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ಚಿಕ್ಕ ಪರದೆಯಿಂದ ದೊಡ್ಡ ಪರದೆಗೆ ಝೂಮ್ ಮಾಡು."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ಬ್ಲೂಟೂತ್ ಸಂಪರ್ಕಗೊಂಡಿದೆ."</string>
@@ -188,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"ರಿಂಗರ್ ಶಾಂತ."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"ಕೆಲಸದ ಮೋಡ್"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸಿ."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ಇತ್ತೀಚಿನ ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
@@ -285,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ಬ್ಲೂಟೂತ್ (<xliff:g id="NUMBER">%d</xliff:g> ಸಾಧನಗಳು)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ಬ್ಲೂಟೂತ್ ಆಫ್"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"ಯಾವುದೇ ಜೋಡಿಸಲಾದ ಸಾಧನಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ಬ್ಯಾಟರಿ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ಆಡಿಯೋ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"ಹೆಡ್ಸೆಟ್"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ಇನ್ಪುಟ್"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ಪ್ರಕಾಶಮಾನ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ಸ್ವಯಂ-ತಿರುಗುವಿಕೆ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"ಪರದೆಯನ್ನು ಸ್ವಯಂ-ತಿರುಗಿಸಿ"</string>
@@ -325,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ಟೆಥರಿಂಗ್"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ಹಾಟ್ಸ್ಪಾಟ್"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"ಅಧಿಸೂಚನೆಗಳು"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ಫ್ಲಾಶ್ಲೈಟ್"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
@@ -334,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ಬಳಸಲಾಗಿದೆ"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ಮಿತಿ"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ಎಚ್ಚರಿಕೆ"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"ಕೆಲಸದ ಮೋಡ್"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"ನೈಟ್ ಲೈಟ್"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"ಸೂರ್ಯಾಸ್ತದಲ್ಲಿ"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"ಸೂರ್ಯೋದಯದ ತನಕ"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> ಸಮಯದಲ್ಲಿ"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> ವರೆಗೂ"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
@@ -348,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ಅನ್ನು ಸುರಕ್ಷಿತ ಮೋಡ್ನಲ್ಲಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"ವಿಭಜಿತ ಪರದೆಯನ್ನು ಬಳಸಲು ಇಲ್ಲಿ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ಅಡ್ಡಲಾಗಿ ವಿಭಜಿಸಿದ"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ಲಂಬವಾಗಿ ವಿಭಜಿಸಿದ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ಕಸ್ಟಮ್ ವಿಭಜಿಸಿದ"</string>
@@ -571,27 +585,21 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ಆಫ್"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"ಪವರ್ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳ ಮೂಲಕ, ನೀವು ಅಪ್ಲಿಕೇಶನ್ಗಳ ಅಧಿಸೂಚನೆಗಳನ್ನು 0 ರಿಂದ 5 ರವರೆಗಿನ ಹಂತಗಳ ಪ್ರಾಮುಖ್ಯತೆಯನ್ನು ಹೊಂದಿಸಬಹುದು. \n\n"<b>"ಹಂತ 5"</b>" \n- ಮೇಲಿನ ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ಅನುಮತಿಸಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ \n\n"<b>"ಹಂತ 4"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ\n\n"<b>"ಹಂತ 3"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n\n"<b>"ಹಂತ 2"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n\n"<b>"ಹಂತ 1"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n- ಸ್ಥಿತಿ ಪಟ್ಟಿ ಮತ್ತು ಲಾಕ್ ಪರದೆಯಿಂದ ಮರೆಮಾಡಿ \n- ಕೆಳಗಿನ ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n\n"<b>"ಹಂತ 0"</b>" \n- ಅಪ್ಲಿಕೇಶನ್ನಿಂದ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"ಅಧಿಸೂಚನೆಗಳು"</string>
- <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+ <string name="notification_channel_disabled" msgid="344536703863700565">"ನೀವು ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಇನ್ನು ಮುಂದೆ ನೋಡುವುದಿಲ್ಲ"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
<skip />
- <!-- no translation found for inline_keep_showing (8945102997083836858) -->
- <skip />
- <!-- no translation found for inline_stop_button (4172980096860941033) -->
- <skip />
- <!-- no translation found for inline_keep_button (6665940297019018232) -->
- <skip />
- <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
- <skip />
- <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
- <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸುತ್ತಲೇ ಇರಬೇಕೆ?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿಲ್ಲಿಸಿ"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"ತೋರಿಸುತ್ತಲಿರಿ"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"ಈ ಅಪ್ಲಿಕೇಶನ್ನಿಂದ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸುತ್ತಲೇ ಇರಬೇಕೆ?"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಫ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳನ್ನು ತೆರೆಯಲಾಗಿದೆ"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳನ್ನು ಮುಚ್ಚಲಾಗಿದೆ"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ಈ ಚಾನಲ್ನ ಅಧಿಸೂಚನೆಗಳಿಗೆ ಅನುಮತಿ ನೀಡಿ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
- <!-- no translation found for notification_app_settings (420348114670768449) -->
- <skip />
+ <string name="notification_app_settings" msgid="420348114670768449">"ಕಸ್ಟಮೈಜ್ ಮಾಡಿ"</string>
<string name="notification_done" msgid="5279426047273930175">"ಮುಗಿದಿದೆ"</string>
- <!-- no translation found for inline_undo (558916737624706010) -->
- <skip />
+ <string name="inline_undo" msgid="558916737624706010">"ರದ್ದುಮಾಡಿ"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳು"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"ಅಧಿಸೂಚನೆ ಸ್ನೂಜ್ ಆಯ್ಕೆಗಳು"</string>
@@ -674,7 +682,8 @@
<item msgid="1545641631806817203">"ಕ್ಲಿಪ್ಬೋರ್ಡ್"</item>
<item msgid="5742013440802239414">"ಕೀಕೋಡ್"</item>
<item msgid="8802889973626281575">"ಕೀಬೋರ್ಡ್ ಬದಲಾಯಿಸುವಿಕೆ"</item>
- <item msgid="8175437057325747277">"ಯಾವುದೂ ಅಲ್ಲ"</item>
+ <item msgid="7095517796293767867">"ತಿರುಗಿಸುವಿಕೆ ಸಲಹೆ"</item>
+ <item msgid="8494159969042135235">"ಯಾವುದೂ ಅಲ್ಲ"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"ಸಾಮಾನ್ಯ"</item>
@@ -798,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"ಬ್ಯಾಟರಿ,ಡೇಟಾ ಬಳಕೆಯ ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"ಮೊಬೈಲ್ ಡೇಟಾ ಆಫ್ ಮಾಡಬೇಕೆ?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"ಅನುಮತಿ ವಿನಂತಿಯನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಮರೆಮಾಚುತ್ತಿರುವ ಕಾರಣ, ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_2">%2$s</xliff:g> ಸ್ಲೈಸ್ಗಳನ್ನು ತೋರಿಸಲು <xliff:g id="APP_0">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- ಇದು <xliff:g id="APP">%1$s</xliff:g> ನಿಂದ ಮಾಹಿತಿಯನ್ನು ಓದಬಹುದು"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- ಇದು <xliff:g id="APP">%1$s</xliff:g> ಒಳಗಡೆ ಕ್ರಿಯೆಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಹುದು"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್ನಿಂದ ಸ್ಲೈಸ್ಗಳನ್ನು ತೋರಿಸಲು <xliff:g id="APP">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸಿ"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"ಅನುಮತಿಸಿ"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"ನಿರಾಕರಿಸಿ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 285c569..b42d0b5 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"홈"</string>
<string name="accessibility_menu" msgid="316839303324695949">"메뉴"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"접근성"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"화면 회전"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"최근 사용"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"검색"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"카메라"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"카메라 열기"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"새 작업 레이아웃 선택"</string>
<string name="cancel" msgid="6442560571259935130">"취소"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"호환성 확대/축소 버튼입니다."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"작은 화면을 큰 화면으로 확대합니다."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"블루투스가 연결되었습니다."</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"벨소리가 무음입니다."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"작업 모드"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>을(를) 숨깁니다."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>이(가) 제거되었습니다."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"최근 사용한 애플리케이션을 모두 닫았습니다."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"블루투스(<xliff:g id="NUMBER">%d</xliff:g>개의 기기)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"블루투스 사용 안함"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"페어링된 기기가 없습니다"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"오디오"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"헤드셋"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"입력"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"밝기"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"자동 회전"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"화면 자동 회전"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"연결 중..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"테더링"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"핫스팟"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"알림"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"손전등"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"모바일 데이터"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> 사용됨"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"한도: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 경고"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"작업 모드"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"야간 조명"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"일몰에"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"일출까지"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>에"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g>까지"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC 사용 중지됨"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC 사용 설정됨"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>은(는) 안전 모드에서 사용 중지됩니다."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"모두 지우기"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"여기를 드래그하여 분할 화면 사용하기"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"수평 분할"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"수직 분할"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"맞춤 분할"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"전원 알림 컨트롤을 사용하면 앱 알림 관련 중요도를 0부터 5까지로 설정할 수 있습니다. \n\n"<b>"레벨 5"</b>" \n- 알림 목록 상단에 표시 \n- 전체 화면일 경우 알림 표시 허용 \n- 항상 엿보기 표시 \n\n"<b>"레벨 4"</b>" \n- 전체 화면에 알림 표시 금지 \n- 항상 엿보기 표시 \n\n"<b>"레벨 3"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n\n"<b>"레벨 2"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n- 소리나 진동으로 알리지 않음 \n\n"<b>"레벨 1"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n- 소리나 진동으로 알리지 않음 \n- 잠금 화면 및 상태 표시줄에서 숨김 \n- 알림 목록 하단에 표시 \n\n"<b>"레벨 0"</b>" \n- 앱의 모든 알림 차단"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"알림"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"더 이상 다음의 알림을 받지 않습니다"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"이 알림을 계속 표시하시겠습니까?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"알림 중지"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"계속 표시하기"</string>
@@ -658,7 +684,8 @@
<item msgid="1545641631806817203">"클립보드"</item>
<item msgid="5742013440802239414">"키 코드"</item>
<item msgid="8802889973626281575">"키보드 전환 도구"</item>
- <item msgid="8175437057325747277">"없음"</item>
+ <item msgid="7095517796293767867">"추천 항목 회전"</item>
+ <item msgid="8494159969042135235">"없음"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"보통"</item>
@@ -782,4 +809,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"탭하여 배터리 및 데이터 사용량 확인"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"모바일 데이터를 사용 중지하시겠습니까?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"앱이 권한 요청을 가리고 있기 때문에 설정에서 내 응답을 확인할 수 없습니다."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g>에서 <xliff:g id="APP_2">%2$s</xliff:g>의 슬라이스를 표시하도록 허용하시겠습니까?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- <xliff:g id="APP">%1$s</xliff:g>의 정보를 읽을 수 있음"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- <xliff:g id="APP">%1$s</xliff:g>에서 작업할 수 있음"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g>에서 모든 앱의 슬라이스를 표시하도록 허용"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"허용"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"거부"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 0687c2d..a1e1415 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -67,7 +67,7 @@
<string name="usb_debugging_message" msgid="2220143855912376496">"Компүтердин RSA ачкычынын контролдук суммасы:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
<string name="usb_debugging_always" msgid="303335496705863070">"Бул компүтерден дайыма уруксат берилсин"</string>
<string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB мүчүлүштүктөрүн оңдоого уруксат жок"</string>
- <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Учурда бул түзмөккө каттоо эсеби менен кирген колдонуучу USB мүчүлүштүктөрүн оңдоо функциясын күйгүзө албай жатат. Бул функцияны колдонуу үчүн негизги колдонуучунун каттоо эсебине которулуңуз."</string>
+ <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Учурда бул аккаунтта USB аркылуу мүчүлүштүктөрдү оңдоо функциясын иштетүүгө болбойт. Негизги колдонуучунун аккаунтуна кириңиз."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Экрнд тлтр ү. чен өлч өзг"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Экранды толтуруу ү-н чоюу"</string>
<string name="global_action_screenshot" msgid="8329831278085426283">"Скриншот"</string>
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Үйгө"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Меню"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Атайын мүмкүнчүлүктөр"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Экранды буруу"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Көз жүгүртүү"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Издөө"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"камераны ачуу"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Жаңы тапшырманын планын тандаңыз"</string>
<string name="cancel" msgid="6442560571259935130">"Жокко чыгаруу"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Масштабды сыйыштыруу баскычы."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Кичинекейди чоң экранга масштабдоо."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth байланышта"</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Үнсүз шыңгыроо."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Иштөө режими"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> этибарга албоо."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> жок болду."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Акыркы колдонмолордун баары көз жаздымда калтырылды."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> түзмөк)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth өчүк"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Жупташкан түзмөктөр жок"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Батареянын деңгээли <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Аудио"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Гарнитура"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Киргизүү"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Жарыктыгы"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоматтык бурулуу"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Экрандын авто-айлануусу"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Туташууда…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Тетеринг"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Туташуу чекити"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Эскертмелер"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Кол чырак"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилдик Интернет"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> колдонулду"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> чектөө"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> эскертүү"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Иштөө режими"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Жумуш профили"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Эскертмелер менен колдонмолор өчүрүлгөн"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Түнкү жарык"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Күн батканда күйөт"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Күн чыкканга чейин"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Саат <xliff:g id="TIME">%s</xliff:g> күйөт"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> чейин"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC өчүрүлгөн"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC иштетилген"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> коопсуз режиминде өчүрүлдү."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Баарын тазалоо"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Экранды бөлүү үчүн бул жерге сүйрөңүз"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Колдонмолорду которуштуруу үчүн өйдө сүрүңүз"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Туурасынан бөлүү"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Тигинен бөлүү"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ыңгайлаштырылган бөлүү"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Бул функциянын жардамы менен ар бир колдонмо үчүн эскертменин маанилүүлүк деңгээлин 0дон 5ке чейин койсоңуз болот. \n\n"<b>"5-деңгээл"</b>" \n- Эскертмелер тизмесинин башында көрсөтүлсүн \n- Эскертмелер толук экранда көрсөтүлсүн \n- Калкып чыгуучу эскертмелерге уруксат берилсин \n\n"<b>"4-деңгээл"</b>" \n- Эскертмелер толук экранда көрсөтүлбөсүн \n- Калкып чыгуучу эскертмелерге уруксат берилсин \n\n"<b>"3-деңгээл"</b>" \n- Эскертмелер толук экранда көрсөтүлбөсүн \n- Калкып чыгуучу эскертмелерге тыюу салынсын \n\n"<b>"2-деңгээл"</b>" \n- Эскертмелер толук экранда көрсөтүлбөсүн \n- Калкып чыгуучу эскертмелерге тыюу салынсын \n- Эч качан добуш чыгып же дирилдебесин \n\n"<b>"1-деңгээл"</b>" \n- Эскертмелер толук экранда көрсөтүлбөсүн \n- Калкып чыгуучу эскертмелерге тыюу салынсын \n- Эч качан добуш чыгып же дирилдебесин \n- Кулпуланган экрандан жана абал тилкесинен жашырылсын \n- Эскертмелер тизмесинин аягында көрсөтүлсүн \n\n"<b>"0-деңгээл"</b>" \n- Колдонмодон алынган бардык эскертмелер бөгөттөлсүн"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Эскертмелер"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Мындан ары бул эскертмелер сизге көрсөтүлбөйт"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Бул эскертмелер көрсөтүлө берсинби?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Эскертмелерди токтотуу"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Көрсөтүлө берсин"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Алмашуу буфери"</item>
<item msgid="5742013440802239414">"Баскыч коду"</item>
<item msgid="8802889973626281575">"Баскычтоп которуштургуч"</item>
- <item msgid="8175437057325747277">"Эч бири"</item>
+ <item msgid="7095517796293767867">"Буруу сунушу"</item>
+ <item msgid="8494159969042135235">"Эч бири"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Кадимки"</item>
@@ -718,7 +742,7 @@
<string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"Ыкчам жөндөөлөрдү ачуу."</string>
<string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"Ыкчам жөндөөлөрдү жабуу."</string>
<string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"Ойготкуч коюлду."</string>
- <string name="accessibility_quick_settings_user" msgid="1567445362870421770">"<xliff:g id="ID_1">%s</xliff:g> каттоо эсеби аркылуу кирди"</string>
+ <string name="accessibility_quick_settings_user" msgid="1567445362870421770">"<xliff:g id="ID_1">%s</xliff:g> аккаунту менен кирди"</string>
<string name="accessibility_quick_settings_no_internet" msgid="31890692343084075">"Интернет жок."</string>
<string name="accessibility_quick_settings_open_details" msgid="4230931801728005194">"Чоо-жайын ачуу."</string>
<string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> жөндөөлөрүн ачуу."</string>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Мобилдик Интернетти өчүрөсүзбү?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Уруксат берүү сурамыңыз көрүнбөй калгандыктан, Жөндөөлөр жообуңузду ырастай албай жатат."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> колдонмосуна <xliff:g id="APP_2">%2$s</xliff:g> үлгүлөрүн көрсөтүүгө уруксат берилсинби?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- <xliff:g id="APP">%1$s</xliff:g> колдонмосунун маалыматын окуйт"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- <xliff:g id="APP">%1$s</xliff:g> колдонмосунда аракеттерди аткарат"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> бардык колдонмолордун үлгүлөрүн көрсөтүүгө уруксат берүү"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Уруксат берүү"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Жок"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 587686f..338da6c 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"ໜ້າທຳອິດ"</string>
<string name="accessibility_menu" msgid="316839303324695949">"ເມນູ"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"ການຊ່ວຍເຂົ້າເຖິງ"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"ໝຸນໜ້າຈໍ"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"ພາບຮວມ"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ຊອກຫາ"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ກ້ອງ"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"ເປີດກ້ອງ"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"ເລືອກແຜນຜັງໜ້າວຽກໃໝ່"</string>
<string name="cancel" msgid="6442560571259935130">"ຍົກເລີກ"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ປຸ່ມຊູມທີ່ໃຊ້ຮ່ວມກັນໄດ້."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ຊູມຈໍນ້ອຍໄປເປັນຈໍຂະຫນາດໃຫຍ່."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ເຊື່ອມຕໍ່ Bluetooth ແລ້ວ."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"ປິດສຽງ."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"ໂໝດການເຮັດວຽກ"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"ປິດ <xliff:g id="APP">%s</xliff:g> ໄວ້."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"ປິດ <xliff:g id="APP">%s</xliff:g> ແລ້ວ."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ທຸກແອັບພລິເຄຊັນບໍ່ດົນມານີ້ຖືກປ່ອຍໄປ."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ອຸປະກອນ)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth ປິດ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"ບໍ່ມີອຸປະກອນທີ່ສາມາດຈັບຄູ່ໄດ້"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ສຽງ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"ຊຸດຫູຟັງ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ການປ້ອນຂໍ້ມູນ"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ຄວາມສະຫວ່າງ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ໝຸນອັດຕະໂນມັດ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"ໝຸນໜ້າຈໍອັດຕະໂນມັດ"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"ກຳລັງເຊື່ອມຕໍ່..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ການປ່ອນສັນຍານ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ຮັອດສະປອດ"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"ການແຈ້ງເຕືອນ"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ໄຟສາຍ"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ອິນເຕີເນັດມືຖື"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"ໃຊ້ໄປແລ້ວ <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"ຈຳກັດ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"ຄຳເຕືອນ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"ໂໝດການເຮັດວຽກ"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"ແສງກາງຄືນ"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"ເປີດຕອນຕາເວັນຕົກ"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"ຈົນກວ່າຕາເວັນຂຶ້ນ"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"ເປີດຕອນ <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"ຈົນກວ່າຈະຮອດ <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ຖືກປິດໃຊ້ໃນໂໝດຄວາມມປອດໄພ."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"ລຶບລ້າງທັງໝົດ"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"ລາກມາບ່ອນນີ້ເພື່ອໃຊ້ການແບ່ງໜ້າຈໍ"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ການແຍກລວງຂວາງ"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ການແຍກລວງຕັ້ງ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ການແຍກກຳນົດເອງ"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"ດ້ວຍການຄວບຄຸມການແຈ້ງເຕືອນ, ທ່ານສາມາດຕັ້ງລະດັບຄວາມສຳຄັນຈາກ 0 ຮອດ 5 ໃຫ້ກັບການແຈ້ງເຕືອນແອັບໃດໜຶ່ງໄດ້. \n\n"<b>"ລະດັບ 5"</b>" \n- ສະແດງຢູ່ເທິງສຸດຂອງລາຍການແຈ້ງເຕືອນ \n- ອະນຸຍາດໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ແນມເບິ່ງທຸກເທື່ອ \n\n"<b>"ລະດັບ 4"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ແນມເບິ່ງທຸກເທື່ອ \n\n"<b>"ລະດັບ 3"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n\n"<b>"ລະດັບ 2"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n- ບໍ່ມີສຽງ ແລະ ບໍ່ມີການສັ່ນເຕືອນ \n\n"<b>"ລະດັບ 1"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n- ບໍ່ມີສຽງ ແລະ ບໍ່ມີການສັ່ນເຕືອນ \n- ເຊື່ອງຈາກໜ້າຈໍລັອກ ແລະ ແຖບສະຖານະ \n- ສະແດງຢູ່ລຸ່ມສຸດຂອງລາຍການແຈ້ງເຕືອນ \n\n"<b>"ລະດັບ 0"</b>" \n- ປິດກັ້ນການແຈ້ງເຕືອນທັງໝົດຈາກແອັບ"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"ການແຈ້ງເຕືອນ"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"ທ່ານຈະບໍ່ໄດ້ຮັບການແຈ້ງເຕືອນເຫຼົ່ານີ້ອີກຕໍ່ໄປ"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"ສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້ຕໍ່ໄປບໍ?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"ຢຸດການແຈ້ງເຕືອນ"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"ສະແດງຕໍ່ໄປ"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"ຄລິບບອດ"</item>
<item msgid="5742013440802239414">"ລະຫັດກະແຈ"</item>
<item msgid="8802889973626281575">"ຕົວສະຫຼັບແປ້ນພິມ"</item>
- <item msgid="8175437057325747277">"ບໍ່ໃຊ້"</item>
+ <item msgid="7095517796293767867">"ການແນະນຳການໝຸນ"</item>
+ <item msgid="8494159969042135235">"ບໍ່ມີ"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"ປົກກະຕິ"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດການນຳໃຊ້ແບັດເຕີຣີ ແລະ ອິນເຕີເນັດ"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"ປິດອິນເຕີເນັດມືຖືໄວ້ບໍ?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"ເນື່ອງຈາກມີແອັບໃດໜຶ່ງກຳລັງຂັດຂວາງການຂໍອະນຸຍາດ, ການຕັ້ງຄ່າຈຶ່ງບໍ່ສາມາດຢັ້ງຢືນການຕອບຮັບຂອງທ່ານໄດ້."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"ອະນຸຍາດ <xliff:g id="APP_0">%1$s</xliff:g> ໃຫ້ສະແດງ <xliff:g id="APP_2">%2$s</xliff:g> ສະໄລ້ບໍ?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- ມັນສາມາດອ່ານຂໍ້ມູນຈາກ <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- ມັນສາມາດໃຊ້ຄຳສັ່ງພາຍໃນ <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"ອະນຸຍາດ <xliff:g id="APP">%1$s</xliff:g> ເພື່ອສະແດງສະໄລ້ຈາກແອັບ"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"ອະນຸຍາດ"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"ປະຕິເສດ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a613b23..cc0f8ab 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -90,6 +90,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Pagrindinis"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Meniu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Pritaikymas neįgaliesiems"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Pasukti ekraną"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Apžvalga"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Ieškoti"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotoaparatas"</string>
@@ -104,6 +105,12 @@
<string name="camera_label" msgid="7261107956054836961">"atidaryti fotoaparatą"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Pasirinkti naują užduoties išdėstymą"</string>
<string name="cancel" msgid="6442560571259935130">"Atšaukti"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Suderinamumo priartinimo mygtukas."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Padidinti ekraną."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"„Bluetooth“ prijungtas."</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Skambutis tylus."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Darbo režimas"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Atsisakyti <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Atsisakyta programos „<xliff:g id="APP">%s</xliff:g>“."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Atsisakyta visų naujausių programų."</string>
@@ -279,6 +287,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"„Bluetooth“ (<xliff:g id="NUMBER">%d</xliff:g> įreng.)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"„Bluetooth“ išjungta"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nėra pasiekiamų susietų įrenginių"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Akumuliatorius: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Garsas"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Virtualiosios realybės įrenginys"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Įvestis"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Šviesumas"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatinis pasukimas"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatiškai sukti ekraną"</string>
@@ -319,6 +331,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Prisijungiama..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Susiejimas"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Viešosios interneto prieigos taškas"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pranešimai"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Žibintuvėlis"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiliojo ryšio duomenys"</string>
@@ -328,8 +343,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Išnaudota: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limitas: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> įspėjimas"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Darbo režimas"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nakties šviesa"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Per saulėlydį"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Iki saulėtekio"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Iki <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"ALR"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"ALR išjungtas"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"ALR įjungtas"</string>
@@ -342,6 +364,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Programa „<xliff:g id="APP">%s</xliff:g>“ išjungta saugos režimu."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Išvalyti viską"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Vilkite čia, kad naudotumėte skaidytą ekraną"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontalus skaidymas"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikalus skaidymas"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tinkintas skaidymas"</string>
@@ -566,6 +590,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Naudodami pranešimų valdiklius galite nustatyti programos pranešimų svarbos lygį nuo 0 iki 5. \n\n"<b>"5 lygis"</b>" \n– Rodyti pranešimų sąrašo viršuje \n– Leisti pertraukti, kai veikia viso ekrano režimas \n– Visada rodyti pranešimus \n\n"<b>"4 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Visada rodyti pranešimus \n\n"<b>"3 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n\n"<b>"2 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n– Niekada neleisti garso ir nevibruoti \n\n"<b>"1 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n– Niekada neleisti garso ir nevibruoti \n– Slėpti užrakinimo ekrane ir būsenos juostoje \n– Rodyti pranešimų sąrašo apačioje \n\n"<b>"0 lygis"</b>" \n– Blokuoti visus programos pranešimus"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Pranešimai"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Nebematysite šių pranešimų"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Toliau rodyti šiuos pranešimus?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Sustabdyti pranešimus"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Toliau rodyti"</string>
@@ -664,7 +690,8 @@
<item msgid="1545641631806817203">"Iškarpinė"</item>
<item msgid="5742013440802239414">"Klavišo kodas"</item>
<item msgid="8802889973626281575">"Klaviatūros perjungiklis"</item>
- <item msgid="8175437057325747277">"Nėra"</item>
+ <item msgid="7095517796293767867">"Pasukimo pasiūlymas"</item>
+ <item msgid="8494159969042135235">"Nėra"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Įprastas"</item>
@@ -788,4 +815,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Palieskite ir sužinokite išsamios informacijos apie akumuliatoriaus bei duomenų naudojimą"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Išjungti mobiliojo ryšio duomenis?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Kadangi programa užstoja leidimo užklausą, nustatymuose negalima patvirtinti jūsų atsakymo."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Leisti „<xliff:g id="APP_0">%1$s</xliff:g>“ rodyti „<xliff:g id="APP_2">%2$s</xliff:g>“ fragmentus?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Gali nuskaityti informaciją iš „<xliff:g id="APP">%1$s</xliff:g>“"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Gali imtis veiksmų programoje „<xliff:g id="APP">%1$s</xliff:g>“"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Leisti „<xliff:g id="APP">%1$s</xliff:g>“ rodyti bet kurios programos fragmentus"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Leisti"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Neleisti"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index a02a20b..1d0d57a 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -89,6 +89,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Sākums"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Izvēlne"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Pieejamība"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Pagriezt ekrānu"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Pārskats"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Meklēt"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -103,6 +104,12 @@
<string name="camera_label" msgid="7261107956054836961">"atvērt kameru"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Atlasiet jaunu uzdevumu izkārtojumu"</string>
<string name="cancel" msgid="6442560571259935130">"Atcelt"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Saderības tālummaiņas poga."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Veikt tālummaiņu no mazāka ekrāna uz lielāku."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth savienojums ir izveidots."</string>
@@ -179,7 +186,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Zvana signāls — kluss."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Darba režīms"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Nerādīt lietotni <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Lietotne <xliff:g id="APP">%s</xliff:g> vairs netiek rādīta."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Visas nesen izmantotās lietojumprogrammas tika noņemtas."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ierīce(-es))"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth savienojums ir izslēgts."</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nav pieejama neviena pārī savienota ierīce."</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Akumulators: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Austiņas"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Ievade"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Spilgtums"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automātiska pagriešana"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automātiska ekrāna pagriešana"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Notiek savienojuma izveide…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Piesaiste"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Tīklājs"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Paziņojumi"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zibspuldze"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilie dati"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Tiek izmantots: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ierobežojums: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> brīdinājums"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Darba režīms"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nakts režīms"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Saulrietā"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Līdz saullēktam"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Līdz plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ir atspējoti"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ir iespējoti"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Lietotne <xliff:g id="APP">%s</xliff:g> ir atspējota drošajā režīmā."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Notīrīt visu"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Velciet šeit, lai izmantotu ekrāna sadalīšanu"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontāls dalījums"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikāls dalījums"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pielāgots dalījums"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Izmantojot barošanas paziņojumu vadīklas, varat lietotnes paziņojumiem iestatīt svarīguma līmeni (no 0 līdz 5). \n\n"<b>"5. līmenis"</b>" \n- Tiek rādīts paziņojumu saraksta augšdaļā \n- Tiek atļauta pilnekrāna režīma pārtraukšana \n- Ieskats vienmēr atļauts \n\n"<b>"4. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats vienmēr atļauts \n\n"<b>"3. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n\n"<b>"2. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n- Nav atļautas skaņas un vibrosignāls \n\n"<b>"1. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n- Nav atļautas skaņas un vibrosignāls \n- Paziņojumi tiek paslēpti bloķēšanas ekrānā un statusa joslā \n- Paziņojumi tiek rādīti paziņojumu saraksta apakšdaļā \n\n"<b>"0. līmenis"</b>" \n- Visi lietotnes paziņojumi tiek bloķēti"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Paziņojumi"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Jūs vairs neredzēsiet šos paziņojumus."</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Vai turpināt rādīt šos paziņojumus?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Apturēt paziņojumu rādīšanu"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Turpināt rādīt"</string>
@@ -660,7 +686,8 @@
<item msgid="1545641631806817203">"Starpliktuve"</item>
<item msgid="5742013440802239414">"Taustiņu kods"</item>
<item msgid="8802889973626281575">"Tastatūras pārslēdzējs"</item>
- <item msgid="8175437057325747277">"Neviens"</item>
+ <item msgid="7095517796293767867">"Rotācijas ieteikums"</item>
+ <item msgid="8494159969042135235">"Nav"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normāls"</item>
@@ -784,4 +811,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Pieskarieties, lai skatītu detalizētu informāciju par akumulatora un datu lietojumu"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vai izslēgt mobilos datus?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Lietotne Iestatījumi nevar verificēt jūsu atbildi, jo cita lietotne aizsedz atļaujas pieprasījumu."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Vai atļaut lietotnei <xliff:g id="APP_0">%1$s</xliff:g> rādīt lietotnes <xliff:g id="APP_2">%2$s</xliff:g> sadaļas?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Var lasīt informāciju no lietotnes <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Var veikt darbības lietotnē <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Atļaut lietotnei <xliff:g id="APP">%1$s</xliff:g> rādīt sadaļas no jebkuras lietotnes"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Atļaut"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Neatļaut"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 886e083..9808ab6 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Почетна страница"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Мени"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Пристапност"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Ротирај екран"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Краток преглед"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Пребарај"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"отвори камера"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Изберете нов распоред на задача"</string>
<string name="cancel" msgid="6442560571259935130">"Откажи"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Копче за компатибилност на зум."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Зумот е помал на поголем екран."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth е поврзан."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ѕвонче на тивко."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Режим на работа"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отфрли <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> е отфрлена."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Сите неодамнешни апликации се отфрлени."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> уреди)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth е исклучен"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Нема достапни спарени уреди"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> батерија"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Аудио"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Слушалки"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Влез"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Осветленост"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоматско ротирање"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Автоматско ротирање на екранот"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Се поврзува..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Поврзување"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка на пристап"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Известувања"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Светилка"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилен интернет"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Искористено: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Лимит: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупредување за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Режим на работа"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Работен профил"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Известувањата и апликациите се исклучени"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ноќно светло"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Вклуч. на зајдисонце"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"До изгрејсонце"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ќе се вклучи во <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC е оневозможено"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC е овозможено"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> е оневозможен во безбеден режим."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Исчисти ги сите"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Повлечете тука за да користите поделен екран"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Повлечете нагоре за да се префрлите од една на друга апликација"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Раздели хоризонтално"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Раздели вертикално"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Раздели прилагодено"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Со контролите за известувањата за напојување, може да поставите ниво на важност од 0 до 5 за известувањата на која било апликација. \n\n"<b>"Ниво 5"</b>" \n- Прикажувај на врвот на списокот со известувања \n- Дозволи прекин во цел екран \n- Секогаш користи појавување \n\n"<b>"Ниво 4"</b>" \n- Спречи прекин во цел екран \n- Секогаш користи појавување \n\n"<b>"Ниво 3"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n\n"<b>"Ниво 2"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n- Без звук и вибрации \n\n"<b>"Ниво 1"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n- Без звук и вибрации \n- Сокриј од заклучен екран и статусна лента \n- Прикажувај на дното на списокот со известувања \n\n"<b>"Ниво 0"</b>" \n- Блокирај ги сите известувања од апликацијата"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Известувања"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Веќе нема да ги гледате овие известувања"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Дали да продолжат да се прикажуваат известувањава?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Запри ги известувањата"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Продолжи да ги прикажуваш"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Табла со исечоци"</item>
<item msgid="5742013440802239414">"Код на копче"</item>
<item msgid="8802889973626281575">"Менувач на тастатура"</item>
- <item msgid="8175437057325747277">"Ништо"</item>
+ <item msgid="7095517796293767867">"Предлог за ротација"</item>
+ <item msgid="8494159969042135235">"Нема"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Нормални"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Допрете за детали за батеријата и потрошениот сообраќај"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Да се исклучи мобилниот интернет?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Бидејќи апликацијата го прикрива барањето за дозвола, „Поставките“ не може да го потврдат вашиот одговор."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Дали да се дозволи <xliff:g id="APP_0">%1$s</xliff:g> да прикажува делови од <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Може да чита информации од <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Може да презема дејства во <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Дозволете <xliff:g id="APP">%1$s</xliff:g> да прикажува делови од која било апликација"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Дозволи"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Одбиј"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index f3fa9e9..446f0e4 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -33,13 +33,10 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"നടന്നുകൊണ്ടിരിക്കുന്നവ"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"അറിയിപ്പുകൾ"</string>
<string name="battery_low_title" msgid="6456385927409742437">"ബാറ്ററി കുറവാണ്"</string>
- <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
- <skip />
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"ബാറ്ററി ചാർജ് കുറവാണ്. ബാറ്ററി ലാഭിക്കൽ ഓണാക്കുക"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ശേഷിക്കുന്നു"</string>
- <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
- <skip />
- <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
- <skip />
+ <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> അവശേഷിക്കുന്നു, ഉപയോഗം അടിസ്ഥാനമാക്കി ഏകദേശം <xliff:g id="TIME">%s</xliff:g> ശേഷിക്കുന്നു"</string>
+ <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> അവശേഷിക്കുന്നു, ഏകദേശം <xliff:g id="TIME">%s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ശേഷിക്കുന്നു. ബാറ്ററി ലാഭിക്കൽ ഓണാണ്."</string>
<string name="invalid_charger" msgid="4549105996740522523">"USB ചാർജ്ജുചെയ്യൽ പിന്തുണയ്ക്കുന്നില്ല.\nഅതിന്റെ അനുബന്ധ ചാർജ്ജർ മാത്രം ഉപയോഗിക്കുക."</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"USB ചാർജ്ജുചെയ്യൽ പിന്തുണച്ചില്ല."</string>
@@ -73,22 +70,15 @@
<string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ഉപകരണത്തിൽ ഇപ്പോൾ സൈൻ ഇൻ ചെയ്തിരിക്കുന്ന ഉപയോക്താവിന് USB ഡീബഗ്ഗിംഗ് ഓണാക്കാനാകില്ല. ഈ ഫീച്ചർ ഉപയോഗിക്കാൻ പ്രാഥമിക ഉപയോക്താവിലേക്ക് മാറുക."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"സ്ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ സൂം ചെയ്യുക"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"സ്ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ വലിച്ചുനീട്ടുക"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"സ്ക്രീൻഷോട്ട്"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
- <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
- <skip />
- <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
- <skip />
- <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
- <skip />
- <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
- <skip />
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു"</string>
+ <string name="screenshot_saved_title" msgid="5637073968117370753">"സ്ക്രീൻഷോട്ട് സംരക്ഷിച്ചു"</string>
+ <string name="screenshot_saved_text" msgid="7574667448002050363">"സ്ക്രീൻഷോട്ട് കാണാൻ ടാപ്പ് ചെയ്യുക"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"സ്ക്രീൻഷോട്ട് എടുക്കാനായില്ല"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"സ്ക്രീൻഷോട്ട് സംരക്ഷിമ്പോൾ പ്രശ്നം നേരിട്ടു"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"സ്റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കാനാകുന്നില്ല"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ഫയൽ കൈമാറൽ ഓപ്ഷനുകൾ"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"ഒരു മീഡിയ പ്ലേയറായി (MTP) മൗണ്ടുചെയ്യുക"</string>
@@ -98,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"ഹോം"</string>
<string name="accessibility_menu" msgid="316839303324695949">"മെനു"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"ഉപയോഗസഹായി"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"സ്ക്രീൻ തിരിക്കുക"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"അവലോകനം"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"തിരയൽ"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ക്യാമറ"</string>
@@ -112,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"ക്യാമറ തുറക്കുക"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"പുതിയ ടാസ്ക് ലേഔട്ട് തിരഞ്ഞെടുക്കുക"</string>
<string name="cancel" msgid="6442560571259935130">"റദ്ദാക്കുക"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"അനുയോജ്യതാ സൂം ബട്ടൺ."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ചെറുതിൽ നിന്ന് വലിയ സ്ക്രീനിലേക്ക് സൂം ചെയ്യുക."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ബ്ലൂടൂത്ത് കണക്റ്റുചെയ്തു."</string>
@@ -188,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"റിംഗർ നിശ്ശബ്ദമാണ്."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"പ്രവർത്തന മോഡ്"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> നിരസിക്കുക."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> നിരസിച്ചു."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"അടുത്തിടെയുള്ള എല്ലാ അപ്ലിക്കേഷനും നിരസിച്ചു."</string>
@@ -285,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ബ്ലൂടൂത്ത് (<xliff:g id="NUMBER">%d</xliff:g> ഉപകരണങ്ങൾ)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ബ്ലൂടൂത്ത് ഓഫുചെയ്യുക"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"ജോടിയാക്കിയ ഉപകരണങ്ങളൊന്നും ലഭ്യമല്ല"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ബാറ്ററി"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ഓഡിയോ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"ഹെഡ്സെറ്റ്"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ഇൻപുട്ട്"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"തെളിച്ചം"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ആവശ്യാനുസരണം തിരിയുക"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"സ്ക്രീൻ സ്വയമേ തിരിക്കുക"</string>
@@ -325,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"കണക്റ്റുചെയ്യുന്നു..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ടെതറിംഗ്"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ഹോട്ട്സ്പോട്ട്"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"അറിയിപ്പുകൾ"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ടോർച്ച്"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"മൊബൈൽ ഡാറ്റ"</string>
@@ -334,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ഉപയോഗിച്ചു"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> പരിധി"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> മുന്നറിയിപ്പ്"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"പ്രവർത്തന മോഡ്"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"നൈറ്റ് ലൈറ്റ്"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"സൂര്യാസ്തമയത്തിന്"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"സൂര്യോദയം വരെ"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>-ന്"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> വരെ"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC പ്രവർത്തനക്ഷമമാക്കി"</string>
@@ -348,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"സുരക്ഷിത മോഡിൽ <xliff:g id="APP">%s</xliff:g> പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"എല്ലാം മായ്ക്കുക"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"സ്പ്ലിറ്റ് സ്ക്രീൻ ഉപയോഗിക്കുന്നതിന് ഇവിടെ വലിച്ചിടുക"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"തിരശ്ചീനമായി വേർതിരിക്കുക"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ലംബമായി വേർതിരിക്കുക"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ഇഷ്ടാനുസൃതമായി വേർതിരിക്കുക"</string>
@@ -571,27 +585,21 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ഓഫ്"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"പവർ അറിയിപ്പ് നിയന്ത്രണം ഉപയോഗിച്ച്, ഒരു ആപ്പിനായുള്ള അറിയിപ്പുകൾക്ക് 0 മുതൽ 5 വരെയുള്ള പ്രാധാന്യ ലെവലുകളിലൊന്ന് നിങ്ങൾക്ക് സജ്ജമാക്കാവുന്നതാണ്. \n\n"<b>"ലെവൽ 5"</b>" \n- അറിയിപ്പ് ലിസ്റ്റിന്റെ മുകളിൽ കാണിക്കുക \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം അനുവദിക്കുക \n- എല്ലായ്പ്പോഴും ദൃശ്യമാക്കുക \n\n"<b>"ലെവൽ 4"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- എല്ലായ്പ്പോഴും ദൃശ്യമാക്കുക \n\n"<b>"ലെവൽ 3"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും സൃശ്യമാക്കരുത് \n\n"<b>"ലെവൽ 2"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും ദൃശ്യമാക്കരുത് \n- ഒരിക്കലും ശബ്ദവും വൈബ്രേഷനും ഉണ്ടാക്കരുത് \n\n"<b>"ലെവൽ 1"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും ദൃശ്യമാക്കരുത് \n- ഒരിക്കലും ശബ്ദവും വൈബ്രേഷനും ഉണ്ടാക്കരുത് \n- ലോക്ക് സ്ക്രീനിൽ നിന്നും സ്റ്റാറ്റസ് ബാറിൽ നിന്നും മറയ്ക്കുക \n- അറിയിപ്പ് ലിസ്റ്റിന്റെ അടിയിൽ കാണിക്കുക \n\n"<b>"ലെവൽ 0"</b>" \n- ആപ്പിൽ നിന്നുള്ള എല്ലാ അറിയിപ്പുകളും ബ്ലോക്കുചെയ്യുക"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"അറിയിപ്പുകൾ"</string>
- <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+ <string name="notification_channel_disabled" msgid="344536703863700565">"നിങ്ങൾ ഇനി ഈ അറിയിപ്പുകൾ കാണില്ല"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
<skip />
- <!-- no translation found for inline_keep_showing (8945102997083836858) -->
- <skip />
- <!-- no translation found for inline_stop_button (4172980096860941033) -->
- <skip />
- <!-- no translation found for inline_keep_button (6665940297019018232) -->
- <skip />
- <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
- <skip />
- <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
- <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"ഈ അറിയിപ്പുകൾ തുടർന്നും കാണിക്കണോ?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"അറിയിപ്പുകൾ നിർത്തുക"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"തുടർന്നും കാണിക്കുക"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"ഈ ആപ്പിൽ നിന്നുള്ള അറിയിപ്പുകൾ തുടർന്നും കാണിക്കണോ?"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"ഈ അറിയിപ്പുകൾ ഓഫാക്കാനാവില്ല"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിന്റെ അറിയിപ്പ് നിയന്ത്രണങ്ങൾ തുറന്നു"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> ആപ്പിന്റെ അറിയിപ്പ് നിയന്ത്രണങ്ങൾ അടച്ചു"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ഈ ചാനലിൽ നിന്നുള്ള അറിയിപ്പുകൾ അനുവദിക്കുക"</string>
<string name="notification_more_settings" msgid="816306283396553571">"കൂടുതൽ ക്രമീകരണം"</string>
- <!-- no translation found for notification_app_settings (420348114670768449) -->
- <skip />
+ <string name="notification_app_settings" msgid="420348114670768449">"ഇഷ്ടാനുസൃതമാക്കുക"</string>
<string name="notification_done" msgid="5279426047273930175">"പൂർത്തിയായി"</string>
- <!-- no translation found for inline_undo (558916737624706010) -->
- <skip />
+ <string name="inline_undo" msgid="558916737624706010">"പഴയപടിയാക്കുക"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"അറിയിപ്പ് നിയന്ത്രണങ്ങൾ"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"അറിയിപ്പ് സ്നൂസ് ഓപ്ഷനുകൾ"</string>
@@ -674,7 +682,8 @@
<item msgid="1545641631806817203">"ക്ലിപ്പ്ബോർഡ്"</item>
<item msgid="5742013440802239414">"കീകോഡ്"</item>
<item msgid="8802889973626281575">"കീബോർഡ് സ്വിച്ചർ"</item>
- <item msgid="8175437057325747277">"ഒന്നുമില്ല"</item>
+ <item msgid="7095517796293767867">"തിരിക്കൽ നിർദ്ദേശം"</item>
+ <item msgid="8494159969042135235">"ഒന്നുമില്ല"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"സാധാരണ വേഗത്തിൽ"</item>
@@ -798,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"ബാറ്ററി, ഡാറ്റ ഉപയോഗം എന്നിവയുടെ വിശദാംശങ്ങളറിയാൻ ടാപ്പുചെയ്യുക"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"മൊബൈൽ ഡാറ്റ ഓഫാക്കണോ?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"അനുമതി അഭ്യർത്ഥനയെ ഒരു ആപ്പ് മറയ്ക്കുന്നതിനാൽ, ക്രമീകരണത്തിന് നിങ്ങളുടെ പ്രതികരണം പരിശോധിച്ചുറപ്പിക്കാനാകില്ല."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_2">%2$s</xliff:g> സ്ലൈസുകൾ കാണിക്കാൻ <xliff:g id="APP_0">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- ഇതിന് <xliff:g id="APP">%1$s</xliff:g>-ൽ നിന്ന് വിവരങ്ങൾ വായിക്കാനാകും"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- ഇതിന് <xliff:g id="APP">%1$s</xliff:g>-നുള്ളിൽ പ്രവർത്തനങ്ങൾ ചെയ്യാനാകും"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"ഏത് ആപ്പിൽ നിന്നും സ്ലൈസുകൾ കാണിക്കാൻ <xliff:g id="APP">%1$s</xliff:g>-നെ അനുവദിക്കുക"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"അനുവദിക്കുക"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"നിരസിക്കുക"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index c8aba01..f1d0c18 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -86,6 +86,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Гэрийн"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Цэс"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Хүртээмж"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Дэлгэцийг эргүүлэх"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Тойм"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Хайх"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камер"</string>
@@ -100,6 +101,12 @@
<string name="camera_label" msgid="7261107956054836961">"камер нээх"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Шинэ ажиллах талбарыг сонгоно уу"</string>
<string name="cancel" msgid="6442560571259935130">"Цуцлах"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Тохиромжтой өсгөх товч."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Жижгээс том дэлгэцрүү өсгөх."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth холбогдсон."</string>
@@ -176,7 +183,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Хонхыг хаах."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Ажлын горим"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-г хаах."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> байхгүй."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Хамгийн сүүлийн бүх програмыг арилгасан байна."</string>
@@ -273,6 +281,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> төхөөрөмж)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth унтраалттай"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Хослуулсан төхөөрөмж байхгүй"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> батерей"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Аудио"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Чихэвч"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Оролт"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Тодрол"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоматаар эргэх"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Дэлгэцийг автоматаар эргүүлэх"</string>
@@ -313,6 +325,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Холбогдож байна..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Модем болгох"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Сүлжээний цэг"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Мэдэгдэл"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Гар чийдэн"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобайл дата"</string>
@@ -322,8 +337,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ашигласан"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> хязгаар"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> анхааруулга"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Ажлын горим"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Шөнийн гэрэл"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Нар жаргах үед"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Нар мандах хүртэл"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>-д"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> хүртэл"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC-г цуцалсан"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC-г идэвхжүүлсэн"</string>
@@ -336,6 +358,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>-г аюулгүй горимд идэвхгүй болгосон."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Бүгдийг арилгах"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Хуваагдсан дэлгэцийг ашиглахын тулд энд чирэх"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Хэвтээ чиглэлд хуваах"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Босоо чиглэлд хуваах"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Хүссэн хэлбэрээр хуваах"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Тэжээлийн мэдэгдлийн удирдлагын тусламжтайгаар та апп-н мэдэгдэлд 0-5 хүртэлх ач холбогдлын түвшин тогтоох боломжтой. \n\n"<b>"5-р түвшин"</b>" \n- Мэдэгдлийн жагсаалтын хамгийн дээр харуулна \n- Бүтэн дэлгэцэд саад болно \n- Дэлгэцэд тогтмол гарч ирнэ \n\n"<b>"4-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд тогтмол гарч ирнэ \n\n"<b>"3-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n\n"<b>"2-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n- Дуу болон чичиргээ хэзээ ч гаргахгүй \n\n"<b>"1-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n- Дуу болон чичиргээ хэзээ ч гаргахгүй \n- Түгжигдсэн дэлгэц болон статусын самбараас нууна \n- Мэдэгдлийн жагсаалтын доор харуулна \n\n"<b>"0-р түвшин"</b>" \n- Энэ апп-н бүх мэдэгдлийг блоклоно"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Мэдэгдэл"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Та эдгээр мэдэгдлийг цаашид харахгүй"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Эдгээр мэдэгдлийг харуулсан хэвээр байх уу?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Мэдэгдлийг зогсоох"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Харуулсан хэвээр байх"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Түр санах ой"</item>
<item msgid="5742013440802239414">"Түлхүүр код"</item>
<item msgid="8802889973626281575">"Гар солигч"</item>
- <item msgid="8175437057325747277">"Хоосон"</item>
+ <item msgid="7095517796293767867">"Эргүүлэлтийн зөвлөмж"</item>
+ <item msgid="8494159969042135235">"Байхгүй"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Энгийн"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Батерей, дата ашиглалтын талаар дэлгэрэнгүйг харахын тулд товшино уу"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Мобайл датаг унтраах уу?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Апп нь зөвшөөрлийн хүсэлтийг танихгүй байгаа тул Тохиргооноос таны хариултыг баталгаажуулах боломжгүй байна."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g>-д <xliff:g id="APP_2">%2$s</xliff:g>-н хэсгүүдийг (slices) харуулахыг зөвшөөрөх үү?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Энэ нь <xliff:g id="APP">%1$s</xliff:g>-с мэдээлэл унших боломжтой"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Энэ нь <xliff:g id="APP">%1$s</xliff:g>-д үйлдэл хийх боломжтой"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g>-д дурын аппаас хэсэг харуулахыг зөвшөөрөх"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Зөвшөөрөх"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Татгалзах"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 803366f..804e916 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -33,13 +33,10 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"सुरु असलेले"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचना"</string>
<string name="battery_low_title" msgid="6456385927409742437">"बॅटरी कमी आहे"</string>
- <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
- <skip />
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"बॅटरी कमी आहे. बॅटरी सेव्हर चालू करा"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक"</string>
- <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
- <skip />
- <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
- <skip />
+ <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाकी, तुमच्या वापरावर आधारित सुमारे <xliff:g id="TIME">%s</xliff:g> शिल्लक"</string>
+ <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाकी, सुमारे <xliff:g id="TIME">%s</xliff:g> शिल्लक"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक. बॅटरी सेव्हर चालू आहे."</string>
<string name="invalid_charger" msgid="4549105996740522523">"USB चार्जिंग समर्थित नाही.\nफक्त पुरवठा केलेले चार्जर वापरा."</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"USB चार्जिंग समर्थित नाही."</string>
@@ -73,22 +70,15 @@
<string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"सध्या या डीव्हाइसमध्ये साइन इन केलेला वापरकर्ता USB डीबग करणे चालू करू शकत नाही. हे वैशिष्ट्य वापरण्यासाठी, प्राथमिक वापरकर्त्यावर स्विच करा."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"स्क्रीन भरण्यासाठी झूम करा"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"स्क्रीन भरण्यासाठी ताणा"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"स्क्रीनशॉट"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"स्क्रीनशॉट जतन करत आहे…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"स्क्रीनशॉट जतन करत आहे…"</string>
- <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
- <skip />
- <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
- <skip />
- <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
- <skip />
- <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
- <skip />
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"स्क्रीनशॉट सेव्ह केला जात आहे"</string>
+ <string name="screenshot_saved_title" msgid="5637073968117370753">"स्क्रीनशॉट सेव्ह केला"</string>
+ <string name="screenshot_saved_text" msgid="7574667448002050363">"तुमचा स्क्रीनशॉट पाहण्यासाठी टॅप करा"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"स्क्रीनशॉट कॅप्चर करता आला नाही"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"स्क्रीनशॉट सेव्ह करताना समस्या आली"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"मर्यादित स्टोरेज जागेमुळे स्क्रीनशॉट सेव्ह करू शकत नाही"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"अॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्याची अनुमती नाही"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB फाईल स्थानांतरण पर्याय"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेअर म्हणून माउंट करा (MTP)"</string>
@@ -98,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"होम"</string>
<string name="accessibility_menu" msgid="316839303324695949">"मेनू"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"प्रवेशयोग्यता"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"स्क्रीन फिरवा"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"अवलोकन"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"शोधा"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"कॅमेरा"</string>
@@ -112,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"कॅमेरा उघडा"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"नवीन कार्य लेआउट निवडा"</string>
<string name="cancel" msgid="6442560571259935130">"रद्द करा"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"सुसंगतता झूम बटण."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"लहानपासून मोठ्या स्क्रीनवर झूम करा."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लूटूथ कनेक्ट केले."</string>
@@ -188,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"रिंगर मूक."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"कार्य मोड"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> डिसमिस करा."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> डिसमिस केला."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"अलीकडील सर्व अॅप्लिकेशन डिसमिस झाले."</string>
@@ -285,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लूटूथ (<xliff:g id="NUMBER">%d</xliff:g> डिव्हाइस)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब्लूटूथ बंद"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"कोणतेही जोडलेले डिव्हाइसेस उपलब्ध नाहीत"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> बॅटरी"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ऑडिओ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"हेडसेट"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"इनपुट"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"चमक"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"स्वयं-फिरवा"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"स्वयं-फिरणारी स्क्रीन"</string>
@@ -325,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"कनेक्ट करत आहे..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"टेदरिंग"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"हॉटस्पॉट"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"सूचना"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ्लॅशलाइट"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"मोबाइल डेटा"</string>
@@ -334,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> वापरले"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> मर्यादा"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावणी"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"कार्य मोड"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"रात्रीचा प्रकाश"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"संध्याकाळी चालू असते"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"सूर्योदयापर्यंत"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> वाजता चालू"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> पर्यंत"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC अक्षम केले आहे"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC सक्षम केले आहे"</string>
@@ -348,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> सुरक्षित-मोडमध्ये अक्षम केला आहे."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"सर्व साफ करा"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"विभाजित स्क्रीन वापर करण्यासाठी येथे ड्रॅग करा"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"क्षैतिज विभाजित करा"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"अनुलंब विभाजित करा"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"सानुकूल विभाजित करा"</string>
@@ -571,27 +585,21 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"बंद"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"पॉवर सूचना नियंत्रणांच्या साहाय्याने तुम्ही अॅप सूचनांसाठी 0 ते 5 असे महत्त्व स्तर सेट करू शकता. \n\n"<b>"स्तर 5"</b>" \n- सूचना सूचीच्या शीर्षस्थानी दाखवा \n- पूर्ण स्क्रीन व्यत्ययास अनुमती द्या \n- नेहमी डोकावून पहा \n\n"<b>"स्तर 4"</b>\n" - पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- नेहमी डोकावून पहा \n\n"<b>"स्तर 3"</b>" \n- पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n\n"<b>"स्तर 2"</b>" \n- पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा कंपन करू नका \n\n"<b>"स्तर 1"</b>\n"- पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा कंपन करू नका \n- लॉक स्क्रीन आणि स्टेटस बार मधून लपवा \n- सूचना सूचीच्या तळाशी दर्शवा \n\n"<b>"स्तर 0"</b>" \n- अॅपमधील सर्व सूचना ब्लॉक करा"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"सूचना"</string>
- <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+ <string name="notification_channel_disabled" msgid="344536703863700565">"आता तुम्हाला या सूचना दिसणार नाहीत"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
<skip />
- <!-- no translation found for inline_keep_showing (8945102997083836858) -->
- <skip />
- <!-- no translation found for inline_stop_button (4172980096860941033) -->
- <skip />
- <!-- no translation found for inline_keep_button (6665940297019018232) -->
- <skip />
- <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
- <skip />
- <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
- <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"या सूचना दाखवणे सुरू ठेवायचे?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"सूचना थांबवा"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"दाखवणे सुरू ठेवा"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"या अॅपकडील सूचना दाखवणे सुरू ठेवायचे?"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"या सूचना बंद करता येत नाहीत"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी सूचना नियंत्रणे खुली आहेत"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी सूचना नियंत्रणे बंद आहेत"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"या चॅनेलकडील सूचनांना मान्यता द्या"</string>
<string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंग्ज"</string>
- <!-- no translation found for notification_app_settings (420348114670768449) -->
- <skip />
+ <string name="notification_app_settings" msgid="420348114670768449">"कस्टमाइझ करा"</string>
<string name="notification_done" msgid="5279426047273930175">"पूर्ण झाले"</string>
- <!-- no translation found for inline_undo (558916737624706010) -->
- <skip />
+ <string name="inline_undo" msgid="558916737624706010">"पहिल्यासारखे करा"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना नियंत्रणे"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना स्नूझ पर्याय"</string>
@@ -674,7 +682,8 @@
<item msgid="1545641631806817203">"क्लिपबोर्ड"</item>
<item msgid="5742013440802239414">"कीकोड"</item>
<item msgid="8802889973626281575">"कीबोर्ड स्विचर"</item>
- <item msgid="8175437057325747277">"काहीही नाही"</item>
+ <item msgid="7095517796293767867">"रोटेशन सूचना"</item>
+ <item msgid="8494159969042135235">"काहीही नाही"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"सामान्य"</item>
@@ -798,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"बॅटरी आणि डेटा वापराच्या तपशीलांसाठी टॅप करा"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"मोबाइल डेटा बंद करायचा?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"अॅप परवानगी विनंती अस्पष्ट करत असल्याने, सेटिंग्ज तुमचा प्रतिसाद पडताळू शकत नाहीत."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> ला <xliff:g id="APP_2">%2$s</xliff:g> चे तुकडे दाखवण्याची अनुमती द्यायची का?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- ते <xliff:g id="APP">%1$s</xliff:g> ची माहिती वाचू शकते"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- ते <xliff:g id="APP">%1$s</xliff:g> मध्ये कृती करू शकते"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> ला कुठल्याही अॅपमधील तुकडे दाखवण्याची अनुमती द्या"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"अनुमती द्या"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"नकार द्या"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 399be8b..d2674ae 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Rumah"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Kebolehaksesan"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Putar skrin"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Ikhtisar"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Cari"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"buka kamera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Pilih reka letak tugas baharu"</string>
<string name="cancel" msgid="6442560571259935130">"Batal"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Butang zum keserasian."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Skrin zum lebih kecil kepada lebih besar."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth disambungkan."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Pendering senyap."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Mod kerja"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ketepikan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ditolak."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaharu diketepikan."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Peranti)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Dimatikan"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Tiada peranti berpasangan tersedia"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> bateri"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Set Kepala"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Input"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Kecerahan"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Autoputar"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Autoputar skrin"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Menyambung..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Penambatan"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Tempat liputan"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pemberitahuan"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampu suluh"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Data mudah alih"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> digunakan"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> had"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Amaran <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Mod kerja"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Cahaya Malam"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Dihidupkan pd senja"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Hingga matahari terbit"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Dihidupkan pada <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Hingga <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC dilumpuhkan"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC didayakan"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> dilumpuhkan dalam mod selamat."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Kosongkan semua"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Seret ke sini untuk menggunakan skrin pisah"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Mendatar Terpisah"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Menegak Terpisah"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tersuai Terpisah"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Dengan kawalan pemberitahuan berkuasa, anda boleh menetapkan tahap kepentingan dari 0 hingga 5 untuk pemberitahuan apl. \n\n"<b>"Tahap 5"</b>" \n- Tunjukkan pada bahagian atas senarai pemberitahuan \n- Benarkan gangguan skrin penuh \n- Sentiasa intai \n\n"<b>"Tahap 4"</b>" \n- Halang gangguan skrin penuh \n- Sentiasa intai \n\n"<b>"Tahap 3"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n\n"<b>"Tahap 2"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n- Jangan berbunyi dan bergetar \n\n"<b>"Tahap 1"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n- Jangan berbunyi atau bergetar \n- Sembunyikan daripada skrin kunci dan bar status \n- Tunjukkan di bahagian bawah senarai pemberitahuan \n\n"<b>"Tahap 0"</b>" \n- Sekat semua pemberitahuan daripada apl"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Pemberitahuan"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Anda tidak akan melihat pemberitahuan ini lagi"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Terus tunjukkan pemberitahuan ini?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Hentikan pemberitahuan"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Terus tunjukkan"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Papan Keratan"</item>
<item msgid="5742013440802239414">"Kod Kunci"</item>
<item msgid="8802889973626281575">"Penukar papan kekunci"</item>
- <item msgid="8175437057325747277">"Tiada"</item>
+ <item msgid="7095517796293767867">"Cadangan putaran"</item>
+ <item msgid="8494159969042135235">"Tiada"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Biasa"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Ketik untuk mendapatkan butiran tentang penggunaan kuasa bateri dan data"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Matikan data mudah alih?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Oleh sebab apl melindungi permintaan kebenaran, Tetapan tidak dapat mengesahkan jawapan anda."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Benarkan <xliff:g id="APP_0">%1$s</xliff:g> menunjukkan <xliff:g id="APP_2">%2$s</xliff:g> hirisan?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Hos hirisan boleh membaca maklumat daripada <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Hos hirisan boleh mengambil tindakan dalam <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Benarkan <xliff:g id="APP">%1$s</xliff:g> menunjukkan hirisan daripada mana-mana apl"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Benarkan"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Tolak"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index ac6adb8..972f4ee 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -73,10 +73,10 @@
<string name="global_action_screenshot" msgid="8329831278085426283">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"ဖန်သားပြင်ဓါတ်ပုံသိမ်းစဉ်.."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား သိမ်းဆည်းပါမည်"</string>
- <string name="screenshot_saving_text" msgid="2545047868936087248">"ဖန်သားပြင်ဓါတ်ပုံကို သိမ်းနေသည်"</string>
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းနေသည်"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းပြီးပါပြီ"</string>
<string name="screenshot_saved_text" msgid="7574667448002050363">"ဖန်သားပြင်ဓာတ်ပုံကို ကြည့်ရန် တို့ပါ"</string>
- <string name="screenshot_failed_title" msgid="9096484883063264803">"ဖန်သားပြင်ဓါတ်ပုံ ရိုက်၍မရပါ"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"ဖန်သားပြင်ဓာတ်ပုံ ရိုက်၍မရပါ"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းရာတွင် ပြဿနာရှိနေသည်"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို ဤအက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string>
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"ပင်မစာမျက်နှာ"</string>
<string name="accessibility_menu" msgid="316839303324695949">"မီနူး"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"အများသုံးစွဲနိုင်မှု"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"မျက်နှာပြင် လှည့်ရန်"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"ခြုံကြည့်မှု။"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ရှာဖွေရန်"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ကင်မရာ"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"ကင်မရာ ဖွင့်ရန်"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"အလုပ်သစ်စီစဥ်မှုကို ရွေးပါ။"</string>
<string name="cancel" msgid="6442560571259935130">"မလုပ်တော့"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"အံဝင်ခွင်ကျ ဇူးမ်ခလုတ်"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ဖန်သားပြင်ပေါ်တွင် အသေးမှအကြီးသို့ ဇူးမ်ဆွဲခြင်း"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ဘလူးတုသ်ချိတ်ဆက်ထားမှု"</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"ဖုန်းမြည်သံပိတ်သည်။"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"အလုပ် မုဒ်"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ကို ပယ်ရန်"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ထုတ်ထားသည်။"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"မကြာသေးမီက အပလီကေးရှင်းများအားလုံး ဖယ်ထုတ်ပြီးပါပြီ။"</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ဘလူးတုသ် (<xliff:g id="NUMBER">%d</xliff:g> စက်များ)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ဘလူးတုသ် ပိတ်ထားရန်"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"ချိတ်တွဲထားသည့် ကိရိယာများ မရှိ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ဘက်ထရီ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"အသံ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"မိုက်ခွက်ပါနားကြပ်"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"အဝင်"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"အလင်းတောက်ပမှု"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"အော်တို-လည်"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"မျက်နှာပြင်အား အလိုအလျောက်လှည့်ခြင်း"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"ဆက်သွယ်နေ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"တွဲချီပေးခြင်း"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ဟော့စပေါ့"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"အကြောင်းကြားချက်များ"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ဖလက်ရှ်မီး"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"မိုဘိုင်းဒေတာ"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> သုံးထား"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ကန့်သတ်ချက်"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> သတိပေးချက်"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"အလုပ် မုဒ်"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"အလုပ်ပရိုဖိုင်"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"အကြောင်းကြားချက်နှင့် အက်ပ်များကို ပိတ်ထားသည်"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"ညအလင်းရောင်"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"နေဝင်ချိန်၌ ဖွင့်ရန်"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"နေထွက်ချိန် အထိ"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> တွင် ဖွင့်ရန်"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> အထိ"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ကို ပိတ်ထားသည်"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ကို ဖွင့်ထားသည်"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ကို ဘေးကင်းလုံခြုံသည့်မုဒ်တွင် ပိတ်ထားပါသည်။"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"အားလုံး ဖယ်ရှားပါ"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"မျက်နှာပြင် ခွဲခြမ်းပြသခြင်းကို အသုံးပြုရန် ဤနေရာသို့ ပွတ်၍ဆွဲထည့်ပါ"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"အက်ပ်များကို ဖွင့်ရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ရေပြင်ညီ ပိုင်းမည်"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ဒေါင်လိုက်ပိုင်းမည်"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"စိတ်ကြိုက် ပိုင်းမည်"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"ပါဝါအကြောင်းကြားချက် ထိန်းချုပ်မှုများကိုအသုံးပြုပြီး အက်ပ်တစ်ခု၏ အကြောင်းကြားချက် အရေးပါမှု ၀ မှ ၅ အထိသတ်မှတ်ပေးနိုင်သည်။ \n\n"<b>"အဆင့် ၅"</b>" \n- အကြောင်းကြားချက်စာရင်း၏ ထိပ်ဆုံးတွင် ပြသည် \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်းကို ခွင့်ပြုသည် \n- အမြဲတမ်း ခေတ္တပြပါမည် \n\n"<b>"အဆင့် ၄"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- အမြဲတမ်း ခေတ္တပြပါမည် \n\n"<b>"အဆင့် ၃"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n\n"<b>"အဆင့် ၂"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n- အသံမြည်ခြင်းနှင့် တုန်ခါခြင်းများ ဘယ်တော့မှ မပြုလုပ်ပါ \n\n"<b>"အဆင့် ၁"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n- အသံမြည်ခြင်းနှင့် တုန်ခါခြင်းများ ဘယ်တော့မှ မပြုလုပ်ပါ \n- လော့ခ်ချထားသည့် မျက်နှာပြင်နှင့် အခြေအနေဘားတန်းတို့တွင် မပြပါ \n- အကြောင်းကြားချက်စာရင်း အောက်ဆုံးတွင်ပြသည် \n\n"<b>"အဆင့် ၀"</b>" \n- အက်ပ်မှ အကြောင်းကြားချက်များ အားလုံးကို ပိတ်ဆို့သည်"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"အကြောင်းကြားချက်များ"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"ဤအကြောင်းကြားချက်များကို မြင်ရတော့မည် မဟုတ်ပါ"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"ဤအကြောင်းကြားချက်များကို ဆက်ပြလိုပါသလား။"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"အကြောင်းကြားချက်များကို ရပ်ရန်"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"ဆက်ပြရန်"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"ကလစ်ဘုတ်"</item>
<item msgid="5742013440802239414">"ကီးကုဒ်"</item>
<item msgid="8802889973626281575">"ကီးဘုတ် ပြောင်းလဲပေးသည့်စနစ်"</item>
- <item msgid="8175437057325747277">"တစ်ခုမျှမရှိ"</item>
+ <item msgid="7095517796293767867">"လှည့်မှု အကြံပြုချက်"</item>
+ <item msgid="8494159969042135235">"တစ်ခုမျှမရှိ"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"ပုံမှန်"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"ဘက်ထရီနှင့် ဒေတာအသုံးပြုမှု အသေးစိတ်ကို ကြည့်ရန် တို့ပါ"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"မိုဘိုင်းဒေတာကို ပိတ်လိုပါသလား။"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"အပလီကေးရှင်းတစ်ခုက ခွင့်ပြုချက်တောင်းခံမှုကို ပိတ်ထားသောကြောင့် ဆက်တင်များသည် သင်၏ လုပ်ဆောင်ကို တုံ့ပြန်နိုင်ခြင်းမရှိပါ။"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> အား <xliff:g id="APP_2">%2$s</xliff:g> ၏အချပ်များ ပြသခွင့်ပြုပါသလား။"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- ၎င်းသည် <xliff:g id="APP">%1$s</xliff:g> မှ အချက်အလက်ကို ဖတ်နိုင်သည်"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- ၎င်းသည် <xliff:g id="APP">%1$s</xliff:g> အတွင်း လုပ်ဆောင်ချက်များ ပြုလုပ်နိုင်သည်"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"မည်သည့်အက်ပ်မဆိုမှ အချပ်များ ပြသရန်အတွက် <xliff:g id="APP">%1$s</xliff:g> ကို ခွင့်ပြုရန်"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"ခွင့်ပြုရန်"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"ငြင်းပယ်ရန်"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 0e7447a..d4d6160 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Startside"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Meny"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Tilgjengelighet"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rotér skjermen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Oversikt"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Søk"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"åpne kamera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Velg en ny utforming for oppgaver"</string>
<string name="cancel" msgid="6442560571259935130">"Avbryt"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoomknapp for kompatibilitet."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom fra mindre til større skjerm."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth er tilkoblet."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Stille modus."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Arbeidsmodus"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Avvis <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> avvist."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle nylig brukte apper er avvist."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheter)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth er slått av"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Ingen sammenkoblede enheter er tilgjengelige"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batteri"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Lyd"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Hodetelefoner"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Innenhet"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Lysstyrke"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotér automatisk"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Rotér skjermen automatisk"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Kobler til …"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internettdeling"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Wi-Fi-sone"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Varsler"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lommelykt"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> brukt"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Grense på <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advarsel for <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Arbeidsmodus"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nattlys"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"På ved solnedgang"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Til soloppgang"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"På kl. <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC er slått av"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC er slått på"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> er slått av i sikker modus."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Tøm alt"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Dra hit for å bruke delt skjerm"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Del horisontalt"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Del vertikalt"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Del tilpasset"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Med effektive varselinnstillinger kan du angi viktighetsnivåer fra 0 til 5 for appvarsler. \n\n"<b>"Nivå 5"</b>" \n– Vis øverst på varsellisten \n– Tillat forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 4"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 3"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n\n"<b>"Nivå 2"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri fort \n– Tillat aldri lyder eller vibrering \n\n"<b>"Nivå 1"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n– Tillat aldri lyder eller vibrering \n– Skjul fra låseskjermen og statusfeltet \n– Vis nederst på varsellisten \n\n"<b>"Nivå 0"</b>" \n– Blokkér alle varsler fra appen"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Varsler"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Du ser ikke disse varslene lenger"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Vil du fortsette å vise disse varslene?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Stopp varsler"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Fortsett å vise"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Utklippstavle"</item>
<item msgid="5742013440802239414">"Tastkode"</item>
<item msgid="8802889973626281575">"Bytteknapp for tastatur"</item>
- <item msgid="8175437057325747277">"Ingen"</item>
+ <item msgid="7095517796293767867">"Forslag til rotasjon"</item>
+ <item msgid="8494159969042135235">"Ingen"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Trykk for detaljer om batteri- og databruk"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vil du slå av mobildata?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Fordi en app skjuler tillatelsesforespørselen, kan ikke Innstillinger bekrefte svaret ditt."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Vil du tillate at <xliff:g id="APP_0">%1$s</xliff:g> viser <xliff:g id="APP_2">%2$s</xliff:g>-utsnitt?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Den kan lese informasjon fra <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Den kan utføre handlinger i <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Tillat at <xliff:g id="APP">%1$s</xliff:g> viser utsnitt fra alle apper"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Tillat"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Avvis"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 5814542..e3efe1b 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"गृह"</string>
<string name="accessibility_menu" msgid="316839303324695949">"मेनु"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"पहुँच"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"स्क्रिन घुमाउनुहोस्"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"सारांश"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"खोज्नुहोस्"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"क्यामेरा"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"क्यामेरा खोल्नुहोस्"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"नयाँ कार्य लेआउट चयन गर्नुहोस्"</string>
<string name="cancel" msgid="6442560571259935130">"रद्द गर्नुहोस्"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"मिलाउने जुम बटन।"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"स्क्रिनलाई सानोबाट ठूलो पार्नुहोस्।"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लुटुथ जडान भयो।"</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"घन्टी मौन।"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"कार्य मोड"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> खारेज गर्नुहोस्।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खारेज गरिएको छ।"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"सबै हालका अनुप्रयोगहरू खारेज गरियो।"</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लुटुथ (<xliff:g id="NUMBER">%d</xliff:g> उपकरणहरू)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब्लुटुथ बन्द"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"जोडी उपकरणहरू उपलब्ध छैन"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ब्याट्री"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"अडियो"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"हेडसेट"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"इनपुट"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"चमक"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"स्वतःघुम्ने"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"स्क्रिन स्वतःघुम्ने"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"जडान हुँदै..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"टेदर गर्दै"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"हटस्पट"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"अधिसूचनाहरू"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ्ल्यासलाइट"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"मोबाइल डेटा"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> प्रयोग गरियो"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> सीमा"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी दिँदै"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"कार्य मोड"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"रात्रिको प्रकाश"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"सूर्यास्तमा सक्रिय"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"सूर्योदयसम्म"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> मा सक्रिय"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> सम्म"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC लाई असक्षम पारिएको छ"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC लाई सक्षम पारिएको छ"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> लाई सुरक्षित-मोडमा असक्षम गरिएको छ।"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"सबै हटाउनुहोस्"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"विभाजित स्क्रिनको प्रयोग गर्नका लागि यहाँ तान्नुहोस्"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"तेर्सो रूपमा विभाजन गर्नुहोस्"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ठाडो रूपमा विभाजन गर्नुहोस्"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"आफू अनुकूल विभाजन गर्नुहोस्"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"सशक्त सूचना नियन्त्रणहरू मार्फत तपाईं अनुप्रयाेगका सूचनाहरूका लागि ० देखि ५ सम्मको महत्व सम्बन्धी स्तर सेट गर्न सक्नुहुन्छ। \n\n"<b>"स्तर ५"</b>" \n- सूचनाको सूचीको माथिल्लो भागमा देखाउने \n- पूर्ण स्क्रिनमा अवरोधका लागि अनुमति दिने \n- सधैँ चियाउने \n\n"<b>"स्तर ४"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- सधैँ चियाउने \n\n"<b>"स्तर ३"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n\n"<b>"स्तर २"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने र कम्पन नगर्ने \n\n"<b>"स्तर १"</b>" \n- पूर्ण स्क्रिनमा अवरोध रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने वा कम्पन नगर्ने \n- लक स्क्रिन र वस्तुस्थिति पट्टीबाट लुकाउने \n- सूचनाको सूचीको तल्लो भागमा देखाउने \n\n"<b>"स्तर ०"</b>" \n- अनुप्रयोगका सबै सूचनाहरूलाई रोक्ने"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"सूचनाहरू"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"तपाईं अब उप्रान्त यी सूचनाहरू देख्नु हुने छैन"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"यी सूचनाहरू देखाउने क्रम जारी राख्ने हो?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"सूचनाहरू देखाउन छाड्नुहोस्"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"देखाउने क्रम जारी राख्नुहोस्"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"क्लिपबोर्ड"</item>
<item msgid="5742013440802239414">"किकोड"</item>
<item msgid="8802889973626281575">"किबोर्ड स्विचर"</item>
- <item msgid="8175437057325747277">"कुनै पनि होइन"</item>
+ <item msgid="7095517796293767867">"परिक्रमासम्बन्धी सुझाव"</item>
+ <item msgid="8494159969042135235">"कुनै पनि होइन"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"साधारण"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"ब्याट्री र डेटाका प्रयोग सम्बन्धी विवरणहरूका लागि ट्याप गर्नुहोस्"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"मोबाइल डेटा निष्क्रिय पार्ने हो?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"कुनै अनुप्रयोगको कारणले अनुमतिसम्बन्धी अनुरोध बुझ्न गाह्रो भइरहेकोले सेटिङहरूले तपाईंको प्रतिक्रिया प्रमाणित गर्न सक्दैनन्।"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> लाई <xliff:g id="APP_2">%2$s</xliff:g> का स्लाइसहरू देखाउन अनुमति दिने हो?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- यसले <xliff:g id="APP">%1$s</xliff:g> बाट जानकारी पढ्न सक्छ"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- यसले <xliff:g id="APP">%1$s</xliff:g> भित्र कारबाही गर्न सक्छ"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"अन्य अनुप्रयोगबाट <xliff:g id="APP">%1$s</xliff:g> मा स्लाइसहरू देखाउन अनुमति दिनुहोस्"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"अनुमति दिनुहोस्"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"अस्वीकार गर्नु…"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 55a6cb88..896d156 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Homepage"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Toegankelijkheid"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Scherm draaien"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Overzicht"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Zoeken"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"camera openen"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Nieuwe taakindeling selecteren"</string>
<string name="cancel" msgid="6442560571259935130">"Annuleren"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knop voor compatibiliteitszoom."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kleiner scherm uitzoomen naar groter scherm."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-verbinding ingesteld."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Belsoftware stil."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Werkmodus"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> sluiten."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwijderd."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle recente apps gesloten."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> apparaten)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth uit"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Geen gekoppelde apparaten beschikbaar"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batterijniveau"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Invoer"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Helderheid"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatisch draaien"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Scherm automatisch draaien"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Verbinding maken…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Meldingen"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zaklamp"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiele data"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> gebruikt"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limiet van <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Waarschuwing voor <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Werkmodus"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nachtverlichting"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Aan bij zonsondergang"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Tot zonsopgang"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is uitgeschakeld"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is ingeschakeld"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is uitgeschakeld in de veilige modus"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Alles wissen"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Sleep hier naartoe om het scherm te splitsen"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontaal splitsen"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verticaal splitsen"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Aangepast splitsen"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Met beheeropties voor meldingen met betrekking tot stroomverbruik kun je een belangrijkheidsniveau van 0 tot 5 instellen voor de meldingen van een app. \n\n"<b>"Niveau 5"</b>" \n- Boven aan de lijst met meldingen weergeven \n- Onderbreking op volledig scherm toestaan \n- Altijd korte weergave \n\n"<b>"Niveau 4"</b>" \n- Geen onderbreking op volledig scherm \n- Altijd korte weergave \n\n"<b>"Niveau 3"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n\n"<b>"Niveau 2"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n- Nooit geluid laten horen of trillen \n\n"<b>"Niveau 1"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n- Nooit geluid laten horen of trillen \n- Verbergen op vergrendelingsscherm en statusbalk \n- Onder aan de lijst met meldingen weergeven \n\n"<b>"Niveau 0"</b>" \n- Alle meldingen van de app blokkeren"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Meldingen"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Deze meldingen worden niet meer weergegeven"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Deze meldingen blijven weergeven?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Meldingen stoppen"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Blijven weergeven"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Klembord"</item>
<item msgid="5742013440802239414">"Toetscode"</item>
<item msgid="8802889973626281575">"Toetsenbordschakelaar"</item>
- <item msgid="8175437057325747277">"Geen"</item>
+ <item msgid="7095517796293767867">"Rotatiesuggestie"</item>
+ <item msgid="8494159969042135235">"Geen"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normaal"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tik voor batterij- en datagebruik"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Mobiele data uitschakelen?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Aangezien een app een toestemmingsverzoek afdekt, kan Instellingen je reactie niet verifiëren."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> toestaan om segmenten van <xliff:g id="APP_2">%2$s</xliff:g> weer te geven?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Deze kan informatie lezen van <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Deze kan acties uitvoeren in <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> toestaan om segmenten van apps weer te geven"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Toestaan"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Weigeren"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index b65ce97..4e39106 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -33,13 +33,10 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ਜਾਰੀ"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"ਸੂਚਨਾਵਾਂ"</string>
<string name="battery_low_title" msgid="6456385927409742437">"ਬੈਟਰੀ ਘੱਟ ਹੈ"</string>
- <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
- <skip />
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"ਬੈਟਰੀ ਘੱਟ ਹੈ। ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕਰੋ"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ"</string>
- <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
- <skip />
- <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
- <skip />
+ <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ, ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%s</xliff:g> ਬਾਕੀ"</string>
+ <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ, ਲਗਭਗ <xliff:g id="TIME">%s</xliff:g> ਬਾਕੀ"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬਾਕੀ। ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਹੈ।"</string>
<string name="invalid_charger" msgid="4549105996740522523">"USB ਚਾਰਜਿੰਗ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ।\nਕੇਵਲ ਸਪਲਾਈ ਕੀਤਾ ਚਾਰਜਰ ਵਰਤੋ।"</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"USB ਚਾਰਜਿੰਗ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ।"</string>
@@ -73,22 +70,15 @@
<string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਜ਼ੂਮ ਕਰੋ"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਸਟ੍ਰੈਚ ਕਰੋ"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
- <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
- <skip />
- <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
- <skip />
- <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
- <skip />
- <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
- <skip />
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
+ <string name="screenshot_saved_title" msgid="5637073968117370753">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="screenshot_saved_text" msgid="7574667448002050363">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਕੈਪਚਰ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕਰਨ ਦੌਰਾਨ ਸਮੱਸਿਆ ਆਈ"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਹੋਣ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਹੈ"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਚੋਣਾਂ"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"ਇੱਕ ਮੀਡੀਆ ਪਲੇਅਰ (MTP) ਦੇ ਤੌਰ ਤੇ ਮਾਊਂਟ ਕਰੋ"</string>
@@ -98,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"ਘਰ"</string>
<string name="accessibility_menu" msgid="316839303324695949">"ਮੀਨੂ"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"ਪਹੁੰਚਯੋਗਤਾ"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"ਸਕ੍ਰੀਨ ਘੁਮਾਓ"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"ਰੂਪ-ਰੇਖਾ"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ਖੋਜੋ"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"ਕੈਮਰਾ"</string>
@@ -112,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"ਕੈਮਰਾ ਖੋਲ੍ਹੋ"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"ਨਵਾਂ ਕੰਮ ਲੇਆਉਟ ਚੁਣੋ"</string>
<string name="cancel" msgid="6442560571259935130">"ਰੱਦ ਕਰੋ"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ਅਨੁਰੂਪਤਾ ਜ਼ੂਮ ਬਟਨ।"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ਵੱਡੀ ਸਕ੍ਰੀਨ ਤੇ ਛੋਟਾ ਜ਼ੂਮ ਕਰੋ।"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ਕਨੈਕਟ ਕੀਤੀ।"</string>
@@ -188,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"ਰਿੰਗਰ ਸਾਈਲੈਂਟ।"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"ਕੰਮ ਮੋਡ"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਖਾਰਜ ਕਰੋ।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ਰੱਦ ਕੀਤਾ।"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ਸਾਰੀਆਂ ਹਾਲੀਆ ਐਪਲੀਕੇਸ਼ਨਾਂ ਰੱਦ ਕੀਤੀਆਂ।"</string>
@@ -285,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ਡਿਵਾਈਸਾਂ)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth ਬੰਦ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"ਕੋਈ ਜੋੜਾਬੱਧ ਕੀਤੀਆਂ ਡੀਵਾਈਸਾਂ ਉਪਲਬਧ ਨਹੀਂ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ਬੈਟਰੀ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ਆਡੀਓ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"ਹੈੱਡਸੈੱਟ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ਇਨਪੁੱਟ"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ਚਮਕ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ਆਟੋ-ਰੋਟੇਟ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"ਸਕ੍ਰੀਨ ਨੂੰ ਆਪਣੇ ਆਪ ਘੁੰਮਾਓ"</string>
@@ -325,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"ਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ਟੈਦਰਿੰਗ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ਹੌਟਸਪੌਟ"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"ਸੂਚਨਾਵਾਂ"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ਫਲੈਸ਼ਲਾਈਟ"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
@@ -334,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ਵਰਤਿਆ"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ਸੀਮਾ"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ਚਿਤਾਵਨੀ"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"ਕੰਮ ਮੋਡ"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"ਰਾਤਰੀ ਲਾਈਟ"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"ਸੂਰਜ ਛਿਪਣ \'ਤੇ ਚਾਲੂ"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"ਸੂਰਜ ਚੜ੍ਹਨ ਤੱਕ"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਚਾਲੂ"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> ਤੱਕ"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
@@ -348,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਸੁਰੱਖਿਅਤ-ਮੋਡ ਵਿੱਚ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ।"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਇੱਥੇ ਘਸੀਟੋ"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ਹੌਰੀਜ਼ੌਂਟਲ ਸਪਲਿਟ"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ਵਰਟੀਕਲ ਸਪਲਿਟ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ਵਿਉਂਂਤੀ ਸਪਲਿਟ"</string>
@@ -571,27 +585,21 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ਬੰਦ"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"ਪਾਵਰ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨਾਲ, ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਦੀਆਂ ਸੂਚਨਾਵਾਂ ਲਈ ਮਹੱਤਤਾ ਪੱਧਰ ਨੂੰ 0 ਤੋਂ 5 ਤੱਕ ਸੈੱਟ ਕਰ ਸਕਦੇ ਹੋ। \n\n"<b>"ਪੱਧਰ 5"</b>" \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਦਿਖਾਓ \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਦੀ ਆਗਿਆ ਦਿਓ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 4"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 3"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 2"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਵੀ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n\n"<b>"ਪੱਧਰ 1"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n- ਲਾਕ ਸਕ੍ਰੀਨ ਅਤੇ ਸਥਿਤੀ ਪੱਟੀ ਤੋਂ ਲੁਕਾਓ \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 0"</b>" \n- ਐਪ ਤੋਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬਲਾਕ ਕਰੋ"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"ਸੂਚਨਾਵਾਂ"</string>
- <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+ <string name="notification_channel_disabled" msgid="344536703863700565">"ਤੁਹਾਨੂੰ ਹੁਣ ਇਹ ਸੂਚਨਾਵਾਂ ਦਿਖਾਈ ਨਹੀਂ ਦੇਣਗੀਆਂ"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
<skip />
- <!-- no translation found for inline_keep_showing (8945102997083836858) -->
- <skip />
- <!-- no translation found for inline_stop_button (4172980096860941033) -->
- <skip />
- <!-- no translation found for inline_keep_button (6665940297019018232) -->
- <skip />
- <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
- <skip />
- <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
- <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"ਕੀ ਇਨ੍ਹਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"ਸੂਚਨਾਵਾਂ ਬੰਦ ਕਰੋ"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖੋ"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"ਕੀ ਇਸ ਐਪ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"ਇਨ੍ਹਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬੰਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨੂੰ ਖੋਲ੍ਹਿਆ ਗਿਆ"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ਇਸ ਚੈਨਲ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਇਜਾਜ਼ਤ ਦਿਓ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
- <!-- no translation found for notification_app_settings (420348114670768449) -->
- <skip />
+ <string name="notification_app_settings" msgid="420348114670768449">"ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
<string name="notification_done" msgid="5279426047273930175">"ਹੋ ਗਿਆ"</string>
- <!-- no translation found for inline_undo (558916737624706010) -->
- <skip />
+ <string name="inline_undo" msgid="558916737624706010">"ਅਣਕੀਤਾ ਕਰੋ"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"ਸੂਚਨਾ ਕੰਟਰੋਲ"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"ਸੂਚਨਾ ਸਨੂਜ਼ ਵਿਕਲਪ"</string>
@@ -674,7 +682,8 @@
<item msgid="1545641631806817203">"ਕਲਿੱਪਬੋਰਡ"</item>
<item msgid="5742013440802239414">"ਕੀ-ਕੋਡ"</item>
<item msgid="8802889973626281575">"ਕੀ-ਬੋਰਡ ਸਵਿੱਚਰ"</item>
- <item msgid="8175437057325747277">"ਕੋਈ ਨਹੀਂ"</item>
+ <item msgid="7095517796293767867">"ਘੁਮਾਅ ਸੰਬੰਧੀ ਸੁਝਾਅ"</item>
+ <item msgid="8494159969042135235">"ਕੋਈ ਨਹੀਂ"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"ਸਧਾਰਨ"</item>
@@ -798,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"ਬੈਟਰੀ ਅਤੇ ਡਾਟਾ ਵਰਤੋਂ ਸਬੰਧੀ ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"ਮੋਬਾਈਲ ਡਾਟਾ ਬੰਦ ਕਰਨਾ ਹੈ?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"ਕਿਸੇ ਐਪ ਵੱਲੋਂ ਇਜਾਜ਼ਤ ਬੇਨਤੀ ਨੂੰ ਢਕੇ ਜਾਣ ਕਾਰਨ ਸੈਟਿੰਗਾਂ ਤੁਹਾਡੇ ਜਵਾਬ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕਰ ਸਕਦੀਆਂ।"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"ਕੀ <xliff:g id="APP_0">%1$s</xliff:g> ਨੂੰ <xliff:g id="APP_2">%2$s</xliff:g> ਦੇ ਹਿੱਸੇ ਦਿਖਾਉਣ ਦੇਣੇ ਹਨ?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- ਇਹ <xliff:g id="APP">%1$s</xliff:g> ਵਿੱਚੋਂ ਜਾਣਕਾਰੀ ਪੜ੍ਹ ਸਕਦਾ ਹੈ"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- ਇਸ <xliff:g id="APP">%1$s</xliff:g> ਦੇ ਅੰਦਰ ਕਾਰਵਾਈਆਂ ਕਰ ਸਕਦਾ ਹੈ"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> ਨੂੰ ਕਿਸੇ ਵੀ ਐਪ ਵਿੱਚੋਂ ਹਿੱਸੇ ਦਿਖਾਉਣ ਦਿਓ"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"ਕਰਨ ਦਿਓ"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 0c4b71e..d2a863a 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -90,6 +90,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Ekran główny"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Ułatwienia dostępu"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Obracanie ekranu"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Przegląd"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Szukaj"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Aparat"</string>
@@ -104,6 +105,12 @@
<string name="camera_label" msgid="7261107956054836961">"otwórz aparat"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Wybierz nowy układ zadań"</string>
<string name="cancel" msgid="6442560571259935130">"Anuluj"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Przycisk powiększenia na potrzeby zgodności."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Powiększa mniejszy ekran do większego."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth połączony."</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Dzwonek wyciszony."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Tryb pracy"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Usuń stąd <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>: zamknięto."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Wszystkie ostatnie aplikacje zostały zamknięte."</string>
@@ -279,6 +287,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (urządzenia: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth wył."</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Brak dostępnych sparowanych urządzeń"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> naładowania baterii"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Dźwięk"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Zestaw słuchawkowy"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Wejście"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Jasność"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Autoobracanie"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Autoobracanie ekranu"</string>
@@ -319,6 +331,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Łączę..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Powiązanie"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Powiadomienia"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Latarka"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilna transmisja danych"</string>
@@ -328,8 +343,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Wykorzystano <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limit <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Ostrzeżenie: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Tryb pracy"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Podświetlenie nocne"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Włącz o zachodzie"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Do wschodu słońca"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Włącz o <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"Komunikacja NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Komunikacja NFC jest wyłączona"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Komunikacja NFC jest włączona"</string>
@@ -342,6 +364,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacja <xliff:g id="APP">%s</xliff:g> została wyłączona w trybie bezpiecznym."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Wyczyść wszystko"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Przeciągnij tutaj, by podzielić ekran"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podziel poziomo"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podziel pionowo"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podziel niestandardowo"</string>
@@ -566,6 +590,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Dzięki zaawansowanym ustawieniom możesz określić poziom ważności powiadomień z aplikacji w skali od 0 do 5. \n\n"<b>"Poziom 5"</b>" \n– Pokazuj u góry listy powiadomień \n– Zezwalaj na powiadomienia na pełnym ekranie \n– Zawsze pokazuj podgląd \n\n"<b>"Poziom 4"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Zawsze pokazuj podgląd \n\n"<b>"Poziom 3"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n\n"<b>"Poziom 2"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n– NIgdy nie powiadamiaj dźwiękiem ani wibracjami \n\n"<b>"Poziom 1"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n– NIgdy nie powiadamiaj dźwiękiem ani wibracjami \n– Ukrywaj na ekranie blokady i pasku stanu \n– Pokazuj u dołu listy powiadomień \n\n"<b>"Poziom 0"</b>" \n– Blokuj wszystkie powiadomienia aplikacji"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Powiadomienia"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Te powiadomienia nie będą już wyświetlane"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Nadal pokazywać te powiadomienia?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Zatrzymaj powiadomienia"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Pokazuj nadal"</string>
@@ -664,7 +690,8 @@
<item msgid="1545641631806817203">"Schowek"</item>
<item msgid="5742013440802239414">"Klawisz"</item>
<item msgid="8802889973626281575">"Przełączanie klawiatury"</item>
- <item msgid="8175437057325747277">"Brak"</item>
+ <item msgid="7095517796293767867">"Sugestia obrotu"</item>
+ <item msgid="8494159969042135235">"Brak"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normalny"</item>
@@ -788,4 +815,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i użycia danych"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Wyłączyć mobilną transmisję danych?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Aplikacja Ustawienia nie może zweryfikować Twojej odpowiedzi, ponieważ inna aplikacja zasłania prośbę o udzielenie uprawnień."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Zezwolić aplikacji <xliff:g id="APP_0">%1$s</xliff:g> na pokazywanie wycinków z aplikacji <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Może odczytywać informacje z aplikacji <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Może wykonywać działania w aplikacji <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Zezwalaj aplikacji <xliff:g id="APP">%1$s</xliff:g> na pokazywanie wycinków z dowolnych aplikacji"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Zezwól"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Odmów"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 5fb7b19..3472d1d 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Página inicial"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Acessibilidade"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Girar a tela"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Visão geral"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Pesquisar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Câmera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"abrir câmera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Selecionar novo layout da tarefa"</string>
<string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão de zoom da compatibilidade."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aumentar a tela com zoom."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado."</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Campainha silenciosa."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Modo de trabalho"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todos os apps recentes foram dispensados."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desativado"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Não há dispositivos pareados disponíveis"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Áudio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Fone de ouvido"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Entrada"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brilho"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Girar automaticamente"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Girar tela automaticamente"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Conectando..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Ponto de acesso"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dados móveis"</string>
@@ -326,8 +341,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Usados: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limite: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabalho"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Perfil de trabalho"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"As notificações e os apps estão desativados"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Modo noturno"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Ativ. ao pôr do sol"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Até o nascer do sol"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ativado às <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Até <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"A NFC está desativada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"A NFC está ativada"</string>
@@ -340,6 +360,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"O app <xliff:g id="APP">%s</xliff:g> está desativado no modo de segurança."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Limpar tudo"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Arraste aqui para usar a tela dividida"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Deslize para cima para alternar entre os apps"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -564,6 +585,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Com controles de ativação de notificações, é possível definir o nível de importância de 0 a 5 para as notificações de um app. \n\n"<b>"Nível 5"</b>" \n- Exibir na parte superior da lista de notificações \n- Permitir interrupção em tela cheia \n- Sempre exibir \n\n"<b>"Nível 4"</b>" \n- Impedir interrupções em tela cheia \n- Sempre exibir \n\n"<b>"Nível 3"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n\n"<b>"Nível 2"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n- Ocultar da tela de bloqueio e barra de status \n- Exibir na parte inferior da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações do app"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notificações"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Você deixará de ver essas notificações"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Continuar mostrando essas notificações?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Bloquear notificações"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Continuar mostrando"</string>
@@ -658,7 +681,8 @@
<item msgid="1545641631806817203">"Área de transferência"</item>
<item msgid="5742013440802239414">"Código de tecla"</item>
<item msgid="8802889973626281575">"Alternador de teclado"</item>
- <item msgid="8175437057325747277">"Nenhum"</item>
+ <item msgid="7095517796293767867">"Sugestão de rotação"</item>
+ <item msgid="8494159969042135235">"Nenhum"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -782,4 +806,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Desativar os dados móveis?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Como um app está ocultando uma solicitação de permissão, as configurações não podem verificar sua resposta."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Permitir que <xliff:g id="APP_0">%1$s</xliff:g> mostre partes do app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Pode ler informações do app <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Pode realizar ações no app <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Permitir que <xliff:g id="APP">%1$s</xliff:g> mostre partes de qualquer app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Permitir"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Negar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 23a2f988..a631fcc 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Página inicial"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Acessibilidade"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rodar ecrã"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Visão geral"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Pesquisar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Câmara"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"abrir câmara"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Selecionar novo esquema de tarefa"</string>
<string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão zoom de compatibilidade."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom menor para ecrã maior."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ligado."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Campainha em silêncio."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Modo de trabalho"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ignorado."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todas as aplicações recentes foram ignoradas."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Dispositivos)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desat."</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Sem dispositivos sincronizados disponíveis"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> de bateria"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Áudio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Ausc. c/ mic. integ."</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Entrada"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brilho"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotação automática"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Rodar o ecrã automaticamente"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"A ligar..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Associação"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dados móveis"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilizado(s)"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limite de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabalho"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz noturna"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Ativ. ao pôr-do-sol"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Até ao nascer do sol"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ativada à(s) <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Até à(s) <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"O NFC está desativado"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"O NFC está ativado"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"O <xliff:g id="APP">%s</xliff:g> está desativado no modo de segurança."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Limpar tudo"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Arraste aqui para utilizar o ecrã dividido"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Com os controlos de notificações do consumo de energia, pode definir um nível de importância de 0 a 5 para as notificações de aplicações. \n\n"<b>"Nível 5"</b>" \n- Mostrar no início da lista de notificações \n- Permitir a interrupção do ecrã inteiro \n- Aparecer rapidamente sempre \n\n"<b>"Nível 4"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Aparecer rapidamente sempre\n\n"<b>"Nível 3"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n\n"<b>"Nível 2"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n- Nunca tocar nem vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n- Nunca tocar nem vibrar \n- Ocultar do ecrã de bloqueio e da barra de estado \n- Mostrar no fim da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações da aplicação"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notificações"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Nunca mais verá estas notificações."</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Pretende continuar a ver estas notificações?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Parar notificações"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Continuar a mostrar"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Área de transferência"</item>
<item msgid="5742013440802239414">"Código de tecla"</item>
<item msgid="8802889973626281575">"Comutador de teclado"</item>
- <item msgid="8175437057325747277">"Nenhum"</item>
+ <item msgid="7095517796293767867">"Sugestão de rotação"</item>
+ <item msgid="8494159969042135235">"Nenhum"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Toque para obter detalhes acerca da utilização da bateria e dos dados"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Pretende desativar os dados móveis?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Uma vez que uma aplicação está a ocultar um pedido de autorização, as Definições não conseguem validar a sua resposta."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Pretende permitir que a aplicação <xliff:g id="APP_0">%1$s</xliff:g> mostre partes da aplicação <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Pode ler informações da aplicação <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Pode realizar ações na aplicação <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Permitir que a aplicação <xliff:g id="APP">%1$s</xliff:g> mostre partes de qualquer aplicação"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Permitir"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Recusar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 5fb7b19..3472d1d 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Página inicial"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Acessibilidade"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Girar a tela"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Visão geral"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Pesquisar"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Câmera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"abrir câmera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Selecionar novo layout da tarefa"</string>
<string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão de zoom da compatibilidade."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aumentar a tela com zoom."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado."</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Campainha silenciosa."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Modo de trabalho"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todos os apps recentes foram dispensados."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desativado"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Não há dispositivos pareados disponíveis"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Áudio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Fone de ouvido"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Entrada"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brilho"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Girar automaticamente"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Girar tela automaticamente"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Conectando..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Ponto de acesso"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dados móveis"</string>
@@ -326,8 +341,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Usados: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limite: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabalho"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Perfil de trabalho"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"As notificações e os apps estão desativados"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Modo noturno"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Ativ. ao pôr do sol"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Até o nascer do sol"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Ativado às <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Até <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"A NFC está desativada"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"A NFC está ativada"</string>
@@ -340,6 +360,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"O app <xliff:g id="APP">%s</xliff:g> está desativado no modo de segurança."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Limpar tudo"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Arraste aqui para usar a tela dividida"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Deslize para cima para alternar entre os apps"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -564,6 +585,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Com controles de ativação de notificações, é possível definir o nível de importância de 0 a 5 para as notificações de um app. \n\n"<b>"Nível 5"</b>" \n- Exibir na parte superior da lista de notificações \n- Permitir interrupção em tela cheia \n- Sempre exibir \n\n"<b>"Nível 4"</b>" \n- Impedir interrupções em tela cheia \n- Sempre exibir \n\n"<b>"Nível 3"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n\n"<b>"Nível 2"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n- Ocultar da tela de bloqueio e barra de status \n- Exibir na parte inferior da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações do app"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notificações"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Você deixará de ver essas notificações"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Continuar mostrando essas notificações?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Bloquear notificações"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Continuar mostrando"</string>
@@ -658,7 +681,8 @@
<item msgid="1545641631806817203">"Área de transferência"</item>
<item msgid="5742013440802239414">"Código de tecla"</item>
<item msgid="8802889973626281575">"Alternador de teclado"</item>
- <item msgid="8175437057325747277">"Nenhum"</item>
+ <item msgid="7095517796293767867">"Sugestão de rotação"</item>
+ <item msgid="8494159969042135235">"Nenhum"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -782,4 +806,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Desativar os dados móveis?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Como um app está ocultando uma solicitação de permissão, as configurações não podem verificar sua resposta."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Permitir que <xliff:g id="APP_0">%1$s</xliff:g> mostre partes do app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Pode ler informações do app <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Pode realizar ações no app <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Permitir que <xliff:g id="APP">%1$s</xliff:g> mostre partes de qualquer app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Permitir"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Negar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index f30f6d3..58b6b75 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -89,6 +89,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Ecranul de pornire"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Meniu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Accesibilitate"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rotiți ecranul"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Vizualizare generală"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Căutați"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Cameră foto"</string>
@@ -103,6 +104,12 @@
<string name="camera_label" msgid="7261107956054836961">"deschideți camera foto"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Selectați noul aspect pentru activitate"</string>
<string name="cancel" msgid="6442560571259935130">"Anulați"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Buton zoom pentru compatibilitate."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Faceți zoom de la o imagine mai mică la una mai mare."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Conectat prin Bluetooth."</string>
@@ -181,7 +188,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Sonerie silențioasă."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Modul de lucru"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Închideți <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> a fost eliminată."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toate aplicațiile recente au fost închise."</string>
@@ -279,6 +287,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispozitive)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth dezactivat"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Niciun dispozitiv conectat disponibil"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Căști"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Intrare"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminozitate"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotire automată"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Rotirea automată a ecranului"</string>
@@ -319,6 +331,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Se conectează..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificări"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanternă"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Date mobile"</string>
@@ -328,8 +343,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilizați"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limită de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertizare: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modul de lucru"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Profil de serviciu"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Notificările și aplicațiile sunt dezactivate"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Lumină de noapte"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Activată la apus"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Până la răsărit"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Activată la <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Până la <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Serviciul NFC este dezactivat"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Serviciul NFC este activat"</string>
@@ -342,6 +362,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplicația <xliff:g id="APP">%s</xliff:g> este dezactivată în modul sigur."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Ștergeți tot"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Trageți aici pentru a folosi ecranul împărțit"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Glisați în sus pentru a comuta între aplicații"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divizare pe orizontală"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divizare pe verticală"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divizare personalizată"</string>
@@ -566,6 +587,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Folosind comenzile de gestionare a notificărilor, puteți să setați un nivel de importanță de la 0 la 5 pentru notificările unei aplicații. \n\n"<b>"Nivelul 5"</b>" \n– Se afișează la începutul listei de notificări \n– Se permite întreruperea pe ecranul complet \n– Se afișează întotdeauna scurt \n\n"<b>"Nivelul 4"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Se afișează întotdeauna scurt \n\n"<b>"Nivelul 3"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n\n"<b>"Nivelul 2"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n– Nu se emit sunete și nu vibrează niciodată \n\n"<b>"Nivelul 1"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n– Nu se emit sunete și nu vibrează niciodată \n– Se ascunde în ecranul de blocare și în bara de stare \n– Se afișează la finalul listei de notificări \n\n"<b>"Nivelul 0"</b>" \n– Se blochează toate notificările din aplicație"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Notificări"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Nu veți mai vedea aceste notificări"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Doriți să continuați afișarea acestor notificări?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Opriți notificările"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Continuați afișarea"</string>
@@ -662,7 +685,8 @@
<item msgid="1545641631806817203">"Clipboard"</item>
<item msgid="5742013440802239414">"Cod de tastă"</item>
<item msgid="8802889973626281575">"Comutator tastatură"</item>
- <item msgid="8175437057325747277">"Niciunul"</item>
+ <item msgid="7095517796293767867">"Sugestie de rotire"</item>
+ <item msgid="8494159969042135235">"Niciunul"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -786,4 +810,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Atingeți pentru mai multe detalii privind bateria și utilizarea datelor"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Dezactivați datele mobile?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Deoarece o aplicație acoperă o solicitare de permisiune, Setările nu vă pot verifica răspunsul."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Permiteți <xliff:g id="APP_0">%1$s</xliff:g> să afișeze porțiuni din <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Poate citi informații din <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Poate efectua acțiuni în <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Permiteți <xliff:g id="APP">%1$s</xliff:g> să afișeze porțiuni din orice aplicație"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Permiteți"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Refuzați"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 4be72ed..3bda5eb 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -90,6 +90,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Домой"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Меню"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Специальные возможности"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Поворот экрана"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Обзор."</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Поиск"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
@@ -104,6 +105,12 @@
<string name="camera_label" msgid="7261107956054836961">"Открыть камеру."</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Выберите другой макет"</string>
<string name="cancel" msgid="6442560571259935130">"Отмена"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка масштабирования (режим совместимости)"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Уменьшение изображения для увеличения свободного места на экране."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-соединение установлено."</string>
@@ -182,7 +189,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Беззвучный режим."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Рабочий режим"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Удаление приложения <xliff:g id="APP">%s</xliff:g> из списка."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" удалено из списка."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Все недавние приложения закрыты."</string>
@@ -281,6 +289,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth выкл."</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Нет доступных сопряженных устройств"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Уровень заряда: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Аудиоустройство"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Гарнитура"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Устройство ввода"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яркость"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоповорот"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Автоповорот экрана"</string>
@@ -321,6 +333,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Соединение..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Режим модема"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка доступа"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Уведомления"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Фонарик"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобильный Интернет"</string>
@@ -330,8 +345,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Использовано: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ограничение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Рабочий режим"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ночной режим"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Включить на закате"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"До рассвета"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Включить в <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"Модуль NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Модуль NFC отключен"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Модуль NFC включен"</string>
@@ -344,6 +366,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" отключено в безопасном режиме."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Очистить все"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Перетащите сюда, чтобы разделить экран"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Разделить по горизонтали"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Разделить по вертикали"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Разделить по-другому"</string>
@@ -568,6 +592,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"С помощью этой функции вы можете устанавливать уровень важности уведомлений от 0 до 5 для каждого приложения.\n\n"<b>"Уровень 5"</b>\n"‒ Помещать уведомления в начало списка.\n‒ Показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 4\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 3\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\nУровень 2\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\nУровень 1\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\n‒ Не показывать на экране блокировки и в строке состояния.\n‒ Помещать уведомления в конец списка.\nУровень 0\n"<b></b>\n"‒ Блокировать все уведомления приложения."</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Уведомления"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Вы больше не будете получать эти уведомления."</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Показывать эти уведомления?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Отключить уведомления"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Показывать"</string>
@@ -666,7 +692,8 @@
<item msgid="1545641631806817203">"Буфер обмена"</item>
<item msgid="5742013440802239414">"Код клавиши"</item>
<item msgid="8802889973626281575">"Переключение раскладки"</item>
- <item msgid="8175437057325747277">"Нет"</item>
+ <item msgid="7095517796293767867">"Поворот"</item>
+ <item msgid="8494159969042135235">"Нет"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Обычная"</item>
@@ -790,4 +817,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Нажмите, чтобы проверить энергопотребление и трафик"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Отключить мобильный Интернет?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Невозможно принять ваше согласие, поскольку запрос скрыт другим приложением."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Разрешить приложению \"<xliff:g id="APP_0">%1$s</xliff:g>\" показывать фрагменты приложения \"<xliff:g id="APP_2">%2$s</xliff:g>\"?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Ему станут доступны данные из приложения \"<xliff:g id="APP">%1$s</xliff:g>\"."</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Оно сможет совершать действия в приложении \"<xliff:g id="APP">%1$s</xliff:g>\"."</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Разрешить приложению \"<xliff:g id="APP">%1$s</xliff:g>\" показывать фрагменты других приложений"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Да"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Нет"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index f072b73..8c9208b 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"මුල් පිටුව"</string>
<string name="accessibility_menu" msgid="316839303324695949">"මෙනුව"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"ප්රවේශ්යතාව"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"තිරය කරකවන්න"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"දළ විශ්ලේෂණය"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"සොයන්න"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"කැමරාව"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"කැමරාව විවෘත කරන්න"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"නව කාර්යය සැකැස්ම තෝරන්න"</string>
<string name="cancel" msgid="6442560571259935130">"අවලංගු කරන්න"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ගැළපෙන විශාලන බොත්තම."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"විශාල තිරය වෙත කුඩාව විශාලනය කරන්න."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"බ්ලූටූත් සම්බන්ධිතයි."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"හඬ නඟනය නිශ්ශබ්දයි."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"වැඩ ප්රකාරය"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ඉවතලන්න."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> අස් කර ඇත."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"සියලුම මෑත යෙඳුම් අස් කරන ලදි."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"බ්ලූටූත් (උපාංග <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"බ්ලූටූත් අක්රියයි"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"යුගල කළ උපාංග නොතිබේ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ශ්රව්ය"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"හෙඩ්සෙටය"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ආදානය"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"දීප්තිය"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ස්වයංක්රීය කරකැවීම"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"ස්වයංක්රීයව-භ්රමණය වන තිරය"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"සම්බන්ධ වෙමින්..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ටෙදරින්"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"හොට්ස්පොට්"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"දැනුම්දීම්"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"සැණෙළි ආලෝකය"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ජංගම දත්ත"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> භාවිතා කර තිබේ"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> සීමිත"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> අවවාද කිරීම"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"වැඩ ප්රකාරය"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"කාර්යාල පැතිකඩ"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"දැනුම්දීම් සහ යෙදුම් ක්රියාවිරහිතයි"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"රාත්රී ආලෝකය"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"හිරු බැසීමේදී ක්රි."</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"හිරු නගින තෙක්"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>ට ක්රියාත්මකයි"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> තෙක්"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC අබලයි"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC සබලයි"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ආරක්ෂිත ප්රකාරය තුළ අබලයි."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"සියල්ල හිස් කරන්න"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"බෙදුම් තිරය භාවිත කිරීමට මෙතැනට අදින්න"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"යෙදුම් මාරු කිරීමට ස්වයිප් කරන්න"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"තිරස්ව වෙන් කරන්න"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"සිරස්ව වෙන් කරන්න"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"අභිමත ලෙස වෙන් කරන්න"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"බල දැනුම්දීම් පාලන සමගින්, ඔබට යෙදුමක දැනුම්දීම් සඳහා වැදගත්කම 0 සිට 5 දක්වා සැකසිය හැකිය. \n\n"<b>"5 මට්ටම"</b>" \n- දැනුම්දීම් ලැයිස්තුවේ ඉහළින්ම පෙන්වන්න \n- පූර්ණ තිර බාධාවට ඉඩ දෙන්න \n- සැම විට එබී බලන්න \n\n"<b>"4 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- සැම විට එබී බලන්න \n\n"<b>"3 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n\n"<b>"2 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n- කිසි විටක හඬ සහ කම්පනය සිදු නොකරන්න \n\n"<b>"1 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n- කිසි විටක හඬ සහ කම්පනය සිදු නොකරන්න \n- අගුලු තිරය සහ තත්ත්ව තීරුව වෙතින් සඟවන්න \n- දැනුම්දීම් ලැයිස්තුවේ පහළින්ම පෙන්වන්න \n\n"<b>"0 මට්ටම"</b>" \n- යෙදුම වෙතින් වන සියලු දැනුම් දීම් සඟවන්න."</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"දැනුම් දීම්"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"ඔබට තවදුරටත් මෙම දැනුම්දීම් නොදකිනු ඇත"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"මෙම දැනුම්දීම් පෙන්වමින් තබන්නද?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"දැනුම්දීම් නවත්වන්න"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"පෙන්වමින් තබන්න"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"පසුරු පුවරුව"</item>
<item msgid="5742013440802239414">"යතුරු කේතය"</item>
<item msgid="8802889973626281575">"යතුරු පුවරු මාරුව"</item>
- <item msgid="8175437057325747277">"කිසිවක් නැත"</item>
+ <item msgid="7095517796293767867">"කැරකීමේ යෝජනාව"</item>
+ <item msgid="8494159969042135235">"කිසිවක් නැත"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"සාමාන්ය"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"බැටරි හා දත්ත භාවිතය පිළිබඳව විස්තර සඳහා තට්ටු කරන්න"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"ජංගම දත්ත ක්රියාවිරහිත කරන්නද?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"යෙදුමක් අවසර ඉල්ලීමක් කරන නිසා, සැකසීම්වලට ඔබගේ ප්රතිචාරය සත්යාපනය කළ නොහැකිය."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> හට කොටස් <xliff:g id="APP_2">%2$s</xliff:g>ක් පෙන්වීමට ඉඩ දෙන්නද?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- එයට <xliff:g id="APP">%1$s</xliff:g> වෙතින් තොරතුරු කියවිය හැකිය"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- එයට <xliff:g id="APP">%1$s</xliff:g> ඇතුළත ක්රියාමාර්ග ගත හැකිය"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"ඕනෑම යෙදුමකින් කොටස් පෙන්වීමට <xliff:g id="APP">%1$s</xliff:g> හට ඉඩ දෙන්න"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"ඉඩ දෙන්න"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"ප්රතික්ෂේප කර."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 618c950..e9b4e9f 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -90,6 +90,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Plocha"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Dostupnosť"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Otočenie obrazovky"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Prehľad"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Hľadať"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotoaparát"</string>
@@ -104,6 +105,12 @@
<string name="camera_label" msgid="7261107956054836961">"spustiť fotoaparát"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Vyberte nové rozloženie úlohy"</string>
<string name="cancel" msgid="6442560571259935130">"Zrušiť"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačidlo úpravy veľkosti z dôvodu kompatibility."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zväčšiť menší obrázok na väčšiu obrazovku."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth pripojené."</string>
@@ -182,7 +189,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Tiché zvonenie."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Pracovný režim"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zavrieť aplikáciu <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikácia <xliff:g id="APP">%s</xliff:g> bola zrušená."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všetky nedávne aplikácie boli odmietnuté."</string>
@@ -281,6 +289,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Rozhranie Bluetooth (počet zariadení: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Rozhranie Bluetooth je vypnuté"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nie sú k dispozícii žiadne spárované zariadenia"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Zvuk"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Náhlavná súprava"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Vstup"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Jas"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatické otáčanie"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatické otáčanie obrazovky"</string>
@@ -321,6 +333,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Pripája sa..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Zdieľané pripojenie"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Upozornenia"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Baterka"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilné dáta"</string>
@@ -330,8 +345,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Využité: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozornenie pri <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Pracovný režim"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nočný režim"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Zapne sa pri západe slnka"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Do východu slnka"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Zapne sa o <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je deaktivované"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je aktivované"</string>
@@ -344,6 +366,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikácia <xliff:g id="APP">%s</xliff:g> je v núdzovom režime zakázaná."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Vymazať všetko"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Presuňte okno sem a použite tak rozdelenú obrazovku"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Rozdeliť vodorovné"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Rozdeliť zvislé"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Rozdeliť vlastné"</string>
@@ -568,6 +592,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Pomocou ovládacích prvkov zobrazovania upozornení môžete nastaviť pre upozornenia aplikácie úroveň dôležitosti od 0 do 5. \n\n"<b>"Úroveň 5"</b>" \n– Zobrazovať v hornej časti zoznamu upozornení. \n– Povoliť prerušenia na celú obrazovku. \n– Vždy zobrazovať čiastočne. \n\n"<b>"Úroveň 4"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Vždy zobrazovať čiastočne. \n\n"<b>"Úroveň 3"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n\n"<b>"Úroveň 2"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n– Nikdy nespúšťať zvuk ani vibrácie. \n\n"<b>"Úroveň 1"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n– Nikdy nespúšťať zvuk ani vibrácie. \n– Skryť na uzamknutej obrazovke a v stavovom riadku. \n– Zobraziť v dolnej časti zoznamu upozornení. \n\n"<b>"Úroveň 0"</b>" \n– Blokovať všetky upozornenia z aplikácie."</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Upozornenia"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Tieto upozornenia sa už nebudú zobrazovať"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Majú sa tieto upozornenia naďalej zobrazovať?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Prestať zobrazovať upozornenia"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Naďalej zobrazovať"</string>
@@ -666,7 +692,8 @@
<item msgid="1545641631806817203">"Schránka"</item>
<item msgid="5742013440802239414">"Kód klávesnice"</item>
<item msgid="8802889973626281575">"Prepínač klávesnice"</item>
- <item msgid="8175437057325747277">"Žiadne"</item>
+ <item msgid="7095517796293767867">"Návrh otáčania"</item>
+ <item msgid="8494159969042135235">"Žiadne"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Štandardná"</item>
@@ -790,4 +817,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Klepnutím zobrazíte podrobnosti o batérii a spotrebe dát"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vypnúť mobilné dáta?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Nastavenia nemôžu overiť vašu odpoveď, pretože určitá aplikácia blokuje žiadosť o povolenie."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Povoliť aplikácii <xliff:g id="APP_0">%1$s</xliff:g> zobrazovať rezy z aplikácie <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Môže čítať informácie z aplikácie <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Môže vykonávať akcie v aplikácii <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Povoliť aplikácii <xliff:g id="APP">%1$s</xliff:g> zobrazovať rezy z ľubovoľnej aplikácie"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Povoliť"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Zamietnuť"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index e52a43a..65164cc 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -90,6 +90,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Začetni zaslon"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Meni"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Funkcije za ljudi s posebnimi potrebami"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Sukanje zaslona"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Pregled"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Iskanje"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Fotoaparat"</string>
@@ -104,6 +105,12 @@
<string name="camera_label" msgid="7261107956054836961">"odpri fotoaparat"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Izberite novo postavitev opravil"</string>
<string name="cancel" msgid="6442560571259935130">"Prekliči"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb povečave za združljivost."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Povečava manjšega na večji zaslon."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Povezava Bluetooth vzpostavljena."</string>
@@ -182,7 +189,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Zvonjenje izklopljeno."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Način za delo"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Opusti aplikacijo <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> je bila odstranjena."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Vse nedavne aplikacije so bile opuščene."</string>
@@ -281,6 +289,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (št. naprav: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth izklopljen"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Na voljo ni nobene seznanjene naprave"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Akumulator na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Zvok"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Slušalke z mikrofonom"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Vhodna naprava"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Svetlost"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Samodejno sukanje"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Samodejno sukanje zaslona"</string>
@@ -321,6 +333,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Vzpostavljanje povezave ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internet prek mobilne naprave"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Dostopna točka"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obvestila"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svetilka"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Prenos podatkov v mobilnem omrežju"</string>
@@ -330,8 +345,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Porabljeno: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Omejitev: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Opozorilo – <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Način za delo"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nočna svetloba"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Ob sončnem zahodu"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Do sončnega vzhoda"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Vklop ob <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Tehnologija NFC je onemogočena"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Tehnologija NFC je omogočena"</string>
@@ -344,6 +366,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacija <xliff:g id="APP">%s</xliff:g> je v varnem načinu onemogočena."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Izbriši vse"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Povlecite sem za razdeljeni zaslon"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Razdeli vodoravno"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Razdeli navpično"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Razdeli po meri"</string>
@@ -568,6 +592,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"S kontrolniki za pomebnost obvestila je mogoče za obvestila aplikacije nastaviti stopnjo pomembnosti od 0 do 5. \n\n"<b>"Stopnja 5"</b>" \n– Prikaz na vrhu seznama obvestil \n– Omogočanje prekinitev v celozaslonskem načinu \n– Vedno prikaži hitre predoglede \n\n"<b>"Stopnja 4"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Vedno prikaži hitre predoglede \n\n"<b>"Stopnja 3"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n\n"<b>"Stopnja 2"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n– Nikoli ne uporabi zvoka in vibriranja \n\n"<b>"Stopnja 1"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n– Nikoli ne uporabi zvoka in vibriranja \n– Skrivanje na zaklenjenem zaslonu in v vrstici stanja \n– Prikaz na dnu seznama obvestil \n\n"<b>"Stopnja 0"</b>" \n– Blokiranje vseh obvestil aplikacije"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Obvestila"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Ta obvestila ne bodo več prikazana"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Želite, da so ta obvestila še naprej prikazana?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Ustavi prikazovanje obvestil"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Prikazuj še naprej"</string>
@@ -666,7 +692,8 @@
<item msgid="1545641631806817203">"Odložišče"</item>
<item msgid="5742013440802239414">"Koda tipke"</item>
<item msgid="8802889973626281575">"Preklopnik tipkovnice"</item>
- <item msgid="8175437057325747277">"Brez"</item>
+ <item msgid="7095517796293767867">"Predlog za vrtenje"</item>
+ <item msgid="8494159969042135235">"Brez"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Običajna"</item>
@@ -790,4 +817,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Dotaknite se za prikaz podrobnosti porabe akumulatorja in prenosa podatkov"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Želite izklopiti prenos podatkov v mobilnih omrežjih?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Ker aplikacija zakriva zahtevo za dovoljenje, z nastavitvami ni mogoče preveriti vašega odziva."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Želite dovoliti, da aplikacija <xliff:g id="APP_0">%1$s</xliff:g> prikaže izreze aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– lahko bere podatke v aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– lahko izvaja dejanja v aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Dovoli, da aplikacija <xliff:g id="APP">%1$s</xliff:g> prikaže izreze iz poljubne aplikacije"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Dovoli"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Zavrni"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 61f1c86..7634902 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Faqja bazë"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menyja"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Qasshmëria"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rrotullo ekranin"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Përmbledhje"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Kërko"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"hap kamerën"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Zgjidh strukturën e re të detyrës"</string>
<string name="cancel" msgid="6442560571259935130">"Anulo"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Butoni i zmadhimit të pajtueshmërisë."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zmadho nga një ekran i vogël në të madh."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Pajisja është lidhur me \"bluetooth\"."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Zilja është heshtur."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Modaliteti i punës"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Largo <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> është hequr."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Të gjitha aplikacionet e fundit u larguan."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"\"Bluetooth-i\" (<xliff:g id="NUMBER">%d</xliff:g> pajisje)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"\"Bluetooth-i\" është i çaktivizuar"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nuk ofrohet për përdorim asnjë pajisje e çiftuar"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> bateri"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Kufje me mikrofon"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Hyrja"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ndriçimi"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rrotullim automatik"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Ekran me rrotullim automatik"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Po lidhet..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Lidhje çiftimi"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Qasje në zona publike interneti"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Njoftimet"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Elektriku"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Të dhënat celulare"</string>
@@ -324,8 +339,13 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Të përdorura: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Kufiri: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Paralajmërim për kufirin prej <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modaliteti i punës"</string>
+ <string name="quick_settings_work_mode_on_label" msgid="3421274215098764735">"Profili i punës"</string>
+ <string name="quick_settings_work_mode_off_label" msgid="8856918707867192186">"Njoftimet dhe aplikacionet janë joaktive"</string>
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Drita e natës"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Në perëndim të diellit"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Deri në lindje të diellit"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Aktive në <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Deri në <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC është çaktivizuar"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC është aktivizuar"</string>
@@ -338,6 +358,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> është i çaktivizuar në modalitetin e sigurt."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Pastroji të gjitha"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Zvarrit këtu për të përdorur ekranin e ndarë"</string>
+ <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"Rrëshqit shpejt lart për të ndërruar aplikacionet"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Ndaje horizontalisht"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ndaj vertikalisht"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ndaj të personalizuarën"</string>
@@ -562,6 +583,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Me kontrollet e njoftimit të energjisë, mund të caktosh një nivel rëndësie nga 0 në 5 për njoftimet e një aplikacioni. \n\n"<b>"Niveli 5"</b>" \n- Shfaq në krye të listës së njoftimeve \n- Lejo ndërprerjen e ekranit të plotë \n- Gjithmonë shfaq shpejt \n\n"<b>"Niveli 4"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Gijthmonë shfaq shpejt \n\n"<b>"Niveli 3"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n\n"<b>"Niveli 2"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n- Asnjëherë mos lësho tingull dhe dridhje \n\n"<b>"Niveli 1"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n- Asnjëherë mos lësho tingull ose dridhje \n- Fshih nga ekrani i kyçjes dhe shiriti i statusit \n- Shfaq në fund të listës së njoftimeve \n\n"<b>"Niveli 0"</b>" \n- Blloko të gjitha njoftimet nga aplikacioni"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Njoftime"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Nuk do t\'i shikosh më këto njoftime"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Do të vazhdosh t\'i shfaqësh këto njoftime?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Ndalo njoftimet"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Vazhdo të shfaqësh"</string>
@@ -656,7 +679,8 @@
<item msgid="1545641631806817203">"Kujtesa e fragmenteve"</item>
<item msgid="5742013440802239414">"Kodi i tasteve"</item>
<item msgid="8802889973626281575">"Ndërruesi i tastierës"</item>
- <item msgid="8175437057325747277">"Asnjë"</item>
+ <item msgid="7095517796293767867">"Sugjerimi i rrotullimit"</item>
+ <item msgid="8494159969042135235">"Asnjë"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normale"</item>
@@ -780,4 +804,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Trokit për detaje mbi baterinë dhe përdorimin e të dhënave"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Të çaktivizohen të dhënat celulare?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Duke qenë se një aplikacion po bllokon një kërkesë për leje, \"Cilësimet\" nuk mund të verifikojnë përgjigjen tënde."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Të lejohet <xliff:g id="APP_0">%1$s</xliff:g> që të shfaqë pjesë të <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Mund të lexojë informacion nga <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Mund të ndërmarrë veprime brenda <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Lejo <xliff:g id="APP">%1$s</xliff:g> për të shfaqur pjesë nga çdo aplikacion"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Lejo"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Refuzo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 7eb86c2..aa97eb2 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -89,6 +89,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Почетна"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Мени"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Приступачност"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Ротирајте екран"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Преглед"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Претражите"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
@@ -103,6 +104,12 @@
<string name="camera_label" msgid="7261107956054836961">"отвори камеру"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Изабери нови распоред задатака"</string>
<string name="cancel" msgid="6442560571259935130">"Откажи"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Дугме Зум компатибилности."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Зумирање са мањег на већи екран."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth је прикључен."</string>
@@ -179,7 +186,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Нечујно звоно."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Режим рада"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Одбаците <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Апликација <xliff:g id="APP">%s</xliff:g> је одбачена."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Све недавно коришћене апликације су одбачене."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> уређаја)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth искључен"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Није доступан ниједан упарени уређај"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Аудио"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Слушалице"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Унос"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Осветљеност"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Аутоматска ротација"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Аутоматско ротирање екрана"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Повезује се..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Повезивање"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Хотспот"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Обавештења"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Лампа"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилни подаци"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Искористили сте <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ограничење од <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Упозорење за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Режим рада"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ноћно светло"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Укључује се по заласку сунца"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"До изласка сунца"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Укључује се у <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC је онемогућен"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC је омогућен"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Апликација <xliff:g id="APP">%s</xliff:g> је онемогућена у безбедном режиму."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Обриши све"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Превуците овде да бисте користили раздељени екран"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Подели хоризонтално"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Подели вертикално"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Прилагођено дељење"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Помоћу напредних контрола за обавештења можете да подесите ниво важности од 0. до 5. за обавештења апликације. \n\n"<b>"5. ниво"</b>" \n– Приказују се у врху листе обавештења \n- Дозволи прекид режима целог екрана \n– Увек завируј \n\n"<b>"4. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Увек завируј \n\n"<b>"3. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n\n"<b>"2. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n– Никада не производи звук или вибрацију \n\n"<b>"1. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n– Никада не производи звук или вибрацију \n– Сакриј на закључаном екрану и статусној траци \n– Приказују се у дну листе обавештења \n\n"<b>"0. ниво"</b>" \n– Блокирај сва обавештења из апликације"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Обавештења"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Више нећете видети ова обавештења"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Желите ли да се ова обавештења и даље приказују?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Престани да приказујеш обавештења"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Настави да приказујеш"</string>
@@ -660,7 +686,8 @@
<item msgid="1545641631806817203">"Меморија"</item>
<item msgid="5742013440802239414">"Кôд тастера"</item>
<item msgid="8802889973626281575">"Пребацивач за тастатуру"</item>
- <item msgid="8175437057325747277">"Ништа"</item>
+ <item msgid="7095517796293767867">"Предлог за ротацију"</item>
+ <item msgid="8494159969042135235">"Ништа"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Нормални"</item>
@@ -784,4 +811,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Додирните за детаље о батерији и потрошњи података"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Желите да онемогућите мобилне податке?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Подешавања не могу да верификују ваш одговор јер апликација скрива захтев за дозволу."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Желите ли да дозволите апликацији <xliff:g id="APP_0">%1$s</xliff:g> да приказује исечке из апликације <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Може да чита податке из апликације <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Може да обавља радње у апликацији <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Дозволите апликацији <xliff:g id="APP">%1$s</xliff:g> да приказује исечке из било које апликације"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Дозволи"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Одбиј"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index d2da3b7..e5ae211 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -31,7 +31,7 @@
</plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Inga aviseringar"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Pågående"</string>
- <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelanden"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Aviseringar"</string>
<string name="battery_low_title" msgid="6456385927409742437">"Lågt batteri"</string>
<string name="battery_low_title_hybrid" msgid="6268991275887381595">"Batterinivån är låg. Aktivera batterisparläge"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> kvar"</string>
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Startsida"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Meny"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Tillgänglighet"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Rotera skärmen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Översikt"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Sök"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"öppna kameran"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Välj en ny layout för uppgiften"</string>
<string name="cancel" msgid="6442560571259935130">"Avbryt"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knapp för kompatibilitetszoom."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zooma mindre skärm till större."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ansluten."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Tyst ringsignal."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Arbetsläge"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ta bort <xliff:g id="APP">%s</xliff:g> från listan."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> togs bort permanent."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alla appar har tagits bort från listan Senaste."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheter)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth av"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Det finns inga kopplade enheter tillgängliga"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> batteri"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Ljud"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Ingång"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ljusstyrka"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotera automatiskt"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Rotera skärmen automatiskt"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Ansluter ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internetdelning"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Surfzon"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Aviseringar"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ficklampa"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> används"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Gräns: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Varning <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Arbetsläge"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nattljus"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"På från solnedgången"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Till soluppgången"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"På från <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Till <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC är inaktiverat"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC är aktiverat"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> är inaktiverad i säkert läge."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Rensa alla"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Dra hit för att dela upp skärmen"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dela horisontellt"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dela vertikalt"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dela anpassad"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Med aviseringsinställningarna kan du ange prioritetsnivå från 0 till 5 för aviseringar från en app. \n\n"<b>"Nivå 5"</b>" \n– Visa högst upp i aviseringslistan\n– Tillåt avbrott i helskärmsläge \n– Snabbvisa alltid \n\n"<b>"Nivå 4"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa alltid \n\n"<b>"Nivå 3"</b>" \n- Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n\n"<b>"Nivå 2"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n– Aldrig med ljud eller vibration \n\n"<b>"Nivå 1"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n– Aldrig med ljud eller vibration \n– Visa inte på låsskärmen och i statusfältet \n– Visa längst ned i aviseringslistan \n\n"<b>"Nivå 0"</b>" \n– Blockera alla aviseringar från appen"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Aviseringar"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"De här aviseringarna visas inte längre"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Vill du fortsätta visa de här aviseringarna?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Stoppa aviseringar"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Fortsätt visa"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Urklipp"</item>
<item msgid="5742013440802239414">"Tangentkod"</item>
<item msgid="8802889973626281575">"Byt mellan meny/tangentbord"</item>
- <item msgid="8175437057325747277">"Ingen"</item>
+ <item msgid="7095517796293767867">"Rotationsförslag"</item>
+ <item msgid="8494159969042135235">"Inga"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Tryck för information om batteri- och dataanvändning"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vill du inaktivera mobildatan?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Svaret kan inte verifieras av Inställningar eftersom en app skymmer en begäran om behörighet."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Tillåter du att bitar av <xliff:g id="APP_2">%2$s</xliff:g> visas i <xliff:g id="APP_0">%1$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– Kan läsa information från <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– Kan vidta åtgärder i <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Tillåt att bitar av vilken app som helst visas i <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Tillåt"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Neka"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8cae1c4..3880540 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Nyumbani"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menyu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Zana za walio na matatizo ya kuona au kusikia"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Zungusha skrini"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Muhtasari"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Tafuta"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"fungua kamera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Chagua muundo mpya wa kazi"</string>
<string name="cancel" msgid="6442560571259935130">"Ghairi"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kichupo cha kukuza kwa utangamanifu"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kuza kidogo kwa skrini kubwa."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth imeunganishwa."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Mlio wa simu uko kimya."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Hali ya kazi"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ondoa <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> imeondolewa."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Programu za hivi majuzi zimeondolewa."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (Vifaa <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Imezimwa"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Hakuna vifaa vilivyooanishwa vinavyopatikana"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Sauti"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Vifaa vya sauti"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Vifaa vya kuingiza sauti"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ung\'avu"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Zungusha kiotomatiki"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Skrini ijizungushe kiotomatiki"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Inaunganisha..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Kusambaza mtandao"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Mtandao-hewa"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Arifa"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Tochi"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Data ya mtandao wa simu"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> imetumika"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"kikomo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Onyo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Hali ya kazi"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Mwanga wa Usiku"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Itawashwa machweo"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Hadi macheo"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Itawashwa saa <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Hadi <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC imezimwa"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC imewashwa"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> imezimwa katika hali salama."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Futa zote"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Buruta hapa ili utumie skrini iliyogawanywa"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gawanya Mlalo"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Gawanya Wima"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Maalum Iliyogawanywa"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Ukiwa na udhibiti wa arifa, unaweza kuweka kiwango cha umuhimu wa arifa za programu kuanzia 0 hadi 5. \n\n"<b>"Kiwango cha 5"</b>" \n- Onyesha katika sehemu ya juu ya orodha ya arifa \n- Ruhusu ukatizaji wa skrini nzima \n- Ruhusu arifa za kuchungulia kila wakati\n\n"<b>"Kiwango cha 4"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Ruhusu arifa za kuchungulia kila wakati \n\n"<b>"Kiwango cha 3"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia\n\n"<b>"Kiwango cha 2"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti au mtetemo \n\n"<b>"Kiwango cha 1"</b>" \n- Zuia ukatizaji wa skrini nzima \n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti na mtetemo \n- Usionyeshe skrini iliyofungwa na sehemu ya arifa \n- Onyesha katika sehemu ya chini ya orodha ya arifa \n\n"<b>"Kiwango cha 0"</b>" \n- Zuia arifa zote kutoka programu"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Arifa"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Hutaona tena arifa hizi"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Ungependa kuendelea kuonyesha arifa hizi?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Acha kuonyesha arifa"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Endelea kuonyesha"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Ubao wa kunakili"</item>
<item msgid="5742013440802239414">"Msimbo wa ufunguo"</item>
<item msgid="8802889973626281575">"Kibadilishaji cha kibodi"</item>
- <item msgid="8175437057325747277">"Hamna"</item>
+ <item msgid="7095517796293767867">"Mapendekezo ya kuzungusha"</item>
+ <item msgid="8494159969042135235">"Hamna"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Ya Kawaida"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Gusa ili upate maelezo kuhusu betri na matumizi ya data"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Ungependa kuzima data ya mtandao wa simu?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Kwa sababu programu nyingine inazuia ombi la ruhusa, hatuwezi kuthibitisha jibu lako katika Mipangilio."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Ungependa kuruhusu <xliff:g id="APP_0">%1$s</xliff:g> ionyeshe vipengee <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Inaweza kusoma maelezo kutoka <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Inaweza kuchukua hatua ndani ya <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Ruhusu <xliff:g id="APP">%1$s</xliff:g> ionyeshe vipengee kutoka programu yoyote"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Ruhusu"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Kataa"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 268fdec..e95d9fe 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -97,4 +97,7 @@
<!-- The offsets the tasks animate from when recents is launched while docking -->
<dimen name="recents_task_stack_animation_launched_while_docking_offset">192dp</dimen>
+
+ <!-- Home button padding for sizing -->
+ <dimen name="home_padding">0dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 5a209b0..774b2f2 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -33,13 +33,10 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"செயலில் இருக்கும்"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"அறிவிப்புகள்"</string>
<string name="battery_low_title" msgid="6456385927409742437">"பேட்டரி குறைவு"</string>
- <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
- <skip />
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"பேட்டரி குறைவாக உள்ளது. பேட்டரி சேமிப்பானை ஆன் செய்யவும்"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> உள்ளது"</string>
- <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
- <skip />
- <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
- <skip />
+ <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> பேட்டரி மீதமுள்ளது. உங்கள் உபயோகத்தைப் பொறுத்து, இதைச் சுமார் <xliff:g id="TIME">%s</xliff:g> மணி நேரத்திற்குப் பயன்படுத்தலாம்"</string>
+ <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> மீதமுள்ளது, இதைச் சுமார் <xliff:g id="TIME">%s</xliff:g> மணி நேரத்திற்குப் பயன்படுத்தலாம்"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> மீதமுள்ளது. பேட்டரி சேமிப்பான் ஆன் செய்யப்பட்டுள்ளது."</string>
<string name="invalid_charger" msgid="4549105996740522523">"USB மூலம் சார்ஜ் செய்வது ஆதரிக்கப்படவில்லை.\nவழங்கப்பட்ட சார்ஜரை மட்டும் பயன்படுத்தவும்."</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"USB சார்ஜிங் ஆதரிக்கப்படவில்லை."</string>
@@ -73,22 +70,15 @@
<string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"தற்போது இந்தச் சாதனத்தில் உள்நுழைந்துள்ள பயனரால் USB பிழைத்திருத்தத்தை இயக்க முடியாது. இந்த அம்சத்தை இயக்க, முதன்மைப் பயனருக்கு மாறவும்."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"திரையை நிரப்ப அளவை மாற்று"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"திரையை நிரப்ப இழு"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"ஸ்கிரீன் ஷாட்"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
- <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
- <skip />
- <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
- <skip />
- <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
- <skip />
- <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
- <skip />
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"ஸ்கிரீன் ஷாட் சேமிக்கப்படுகிறது"</string>
+ <string name="screenshot_saved_title" msgid="5637073968117370753">"ஸ்கிரீன் ஷாட் சேமிக்கப்பட்டது"</string>
+ <string name="screenshot_saved_text" msgid="7574667448002050363">"ஸ்கிரீன்ஷாட்டைப் பார்க்க, தட்டவும்"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"ஸ்கிரீன் ஷாட் எடுக்க முடியவில்லை"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"ஸ்கிரீன்ஷாட்டைச் சேமிப்பதில் சிக்கல் ஏற்பட்டது"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ஸ்கிரீன் ஷாட்டுகளை எடுப்பதை, பயன்பாடு அல்லது உங்கள் நிறுவனம் அனுமதிக்கவில்லை"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB கோப்பு இடமாற்ற விருப்பங்கள்"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"(MTP) மீடியா பிளேயராக ஏற்று"</string>
@@ -98,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"முகப்பு"</string>
<string name="accessibility_menu" msgid="316839303324695949">"மெனு"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"அணுகல்தன்மை"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"திரையைச் சுழற்று"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"மேலோட்டப் பார்வை"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"தேடு"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"கேமரா"</string>
@@ -112,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"கேமராவைத் திற"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"புதிய பணி தளவமைப்பைத் தேர்ந்தெடுக்கவும்"</string>
<string name="cancel" msgid="6442560571259935130">"ரத்துசெய்"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"பொருந்துமாறு அளவை மாற்றும் பொத்தான்."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"சிறியதிலிருந்து பெரிய திரைக்கு அளவை மாற்றும்."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"புளூடூத் இணைக்கப்பட்டது."</string>
@@ -188,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"ரிங்கர் நிசப்தம்."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"பணிப் பயன்முறை"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ஐ நிராகரி."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> விலக்கப்பட்டது."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"எல்லா சமீபத்திய பயன்பாடுகளும் விலக்கப்பட்டன."</string>
@@ -285,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"புளூடூத் (<xliff:g id="NUMBER">%d</xliff:g> சாதனங்கள்)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"புளூடூத் ஐ முடக்கு"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"இணைக்கப்பட்ட சாதனங்கள் இல்லை"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> பேட்டரி"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ஆடியோ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"ஹெட்செட்"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"உள்ளீடு"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ஒளிர்வு"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"தானாகச் சுழற்று"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"திரையைத் தானாகச் சுழற்று"</string>
@@ -325,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"இணைக்கிறது..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"டெதெரிங்"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ஹாட்ஸ்பாட்"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"அறிவிப்புகள்"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"டார்ச் லைட்"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"மொபைல் டேட்டா"</string>
@@ -334,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"பயன்படுத்தியது - <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> வரம்பு"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> எச்சரிக்கை"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"பணிப் பயன்முறை"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"இரவு ஒளி"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"மாலையில் ஆன் செய்"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"சூரிய உதயம் வரை"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>க்கு ஆன் செய்"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> மணி வரை"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC முடக்கப்பட்டது"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC இயக்கப்பட்டது"</string>
@@ -348,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"பாதுகாப்புப் பயன்முறையில் <xliff:g id="APP">%s</xliff:g> முடக்கப்பட்டது."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"அனைத்தையும் அழி"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"திரைப் பிரிப்பைப் பயன்படுத்த, இங்கே இழுக்கவும்"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"கிடைமட்டமாகப் பிரி"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"செங்குத்தாகப் பிரி"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"தனிவிருப்பத்தில் பிரி"</string>
@@ -571,27 +585,21 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ஆஃப்"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"ஆற்றல்மிக்க அறிவிப்புக் கட்டுப்பாடுகள் மூலம், பயன்பாட்டின் அறிவிப்புகளுக்கு முக்கியத்துவ நிலையை (0-5) அமைக்கலாம். \n\n"<b>"நிலை 5"</b>" \n- அறிவிப்புப் பட்டியலின் மேலே காட்டும் \n- முழுத் திரைக் குறுக்கீட்டை அனுமதிக்கும் \n- எப்போதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டும் \n\n"<b>"நிலை 4"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- எப்போதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டும் \n\n"<b>"நிலை 3"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n\n"<b>"நிலை 2"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n- ஒருபோதும் ஒலி எழுப்பாது, அதிர்வுறாது \n\n"<b>"நிலை 1"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n- ஒருபோதும் ஒலி எழுப்பாது அல்லது அதிர்வுறாது \n- பூட்டுத்திரை மற்றும் நிலைப்பட்டியிலிருந்து மறைக்கும் \n- அறிவிப்புகள் பட்டியலின் கீழே காட்டும் \n\n"<b>"நிலை 0"</b>" \n- பயன்பாட்டின் எல்லா அறிவிப்புகளையும் தடுக்கும்"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"அறிவிப்புகள்"</string>
- <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+ <string name="notification_channel_disabled" msgid="344536703863700565">"இந்த அறிவிப்புகளை இனி பார்க்கமாட்டீர்கள்"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
<skip />
- <!-- no translation found for inline_keep_showing (8945102997083836858) -->
- <skip />
- <!-- no translation found for inline_stop_button (4172980096860941033) -->
- <skip />
- <!-- no translation found for inline_keep_button (6665940297019018232) -->
- <skip />
- <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
- <skip />
- <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
- <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"இந்த அறிவிப்புகளைத் தொடர்ந்து காட்டவா?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"அறிவிப்புகளை நிறுத்து"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"அறிவிப்புகளைத் தொடர்ந்து காட்டு"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"இந்தப் பயன்பாட்டின் அறிவிப்புகளைத் தொடர்ந்து காட்டவா?"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"இந்த அறிவிப்புகளை ஆஃப் செய்ய முடியாது"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g>க்கான அறிவிப்புக் கட்டுப்பாடுகள் திறக்கப்பட்டன"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g>க்கான அறிவிப்புக் கட்டுப்பாடுகள் மூடப்பட்டன"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"இந்தச் சேனலிலிருந்து அறிவிப்புகளைப் பெறுவதை அனுமதிக்கும்"</string>
<string name="notification_more_settings" msgid="816306283396553571">"மேலும் அமைப்புகள்"</string>
- <!-- no translation found for notification_app_settings (420348114670768449) -->
- <skip />
+ <string name="notification_app_settings" msgid="420348114670768449">"தனிப்பயனாக்கு"</string>
<string name="notification_done" msgid="5279426047273930175">"முடிந்தது"</string>
- <!-- no translation found for inline_undo (558916737624706010) -->
- <skip />
+ <string name="inline_undo" msgid="558916737624706010">"செயல்தவிர்"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"அறிவிப்புக் கட்டுப்பாடுகள்"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"அறிவிப்பை உறக்கநிலையாக்கும் விருப்பங்கள்"</string>
@@ -674,7 +682,8 @@
<item msgid="1545641631806817203">"கிளிப்போர்டு"</item>
<item msgid="5742013440802239414">"விசைக்குறியீடு"</item>
<item msgid="8802889973626281575">"விசைப்பலகை மாற்றி"</item>
- <item msgid="8175437057325747277">"ஏதுமில்லை"</item>
+ <item msgid="7095517796293767867">"சுழற்சிப் பரிந்துரை"</item>
+ <item msgid="8494159969042135235">"ஏதுமில்லை"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"இயல்பானது"</item>
@@ -798,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"பேட்டரி மற்றும் தரவு உபயோக விவரங்களைக் காண, தட்டவும்"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"மொபைல் டேட்டாவை முடக்கவா?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"அனுமதிக் கோரிக்கையைப் பயன்பாடு மறைப்பதால், அமைப்புகளால் உங்கள் பதிலைச் சரிபார்க்க முடியாது."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> பயன்பாட்டை, <xliff:g id="APP_2">%2$s</xliff:g> பயன்பாட்டின் விழிப்பூட்டல்களைக் காண்பிக்க அனுமதிக்கவா?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- இது, <xliff:g id="APP">%1$s</xliff:g> பயன்பாட்டிலிருந்து தகவலைப் படிக்கும்"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- இது, <xliff:g id="APP">%1$s</xliff:g> பயன்பாட்டிற்குள் சென்று செயல்பாடுகளில் ஈடுபடும்"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"எல்லா பயன்பாட்டிலிருந்தும் விழிப்பூட்டல்களைக் காண்பிக்க, <xliff:g id="APP">%1$s</xliff:g> பயன்பாட்டை அனுமதி"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"அனுமதி"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"நிராகரி"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index f8a14d0..e143b90 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -33,13 +33,10 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"కొనసాగుతున్నవి"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"నోటిఫికేషన్లు"</string>
<string name="battery_low_title" msgid="6456385927409742437">"బ్యాటరీ తక్కువగా ఉంది"</string>
- <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
- <skip />
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"బ్యాటరీ తక్కువగా ఉంది. బ్యాటరీ సేవర్ని ఆన్ చేయండి"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది"</string>
- <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
- <skip />
- <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
- <skip />
+ <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది, మీ ఉపయోగం ఆధారంగా దాదాపు <xliff:g id="TIME">%s</xliff:g> ఉండవచ్చు"</string>
+ <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది, దాదాపు <xliff:g id="TIME">%s</xliff:g> ఉండవచ్చు"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది. బ్యాటరీ సేవర్ ఆన్లో ఉంది."</string>
<string name="invalid_charger" msgid="4549105996740522523">"USB ఛార్జింగ్కు మద్దతు లేదు.\nఅందించిన ఛార్జర్ను మాత్రమే ఉపయోగించండి."</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"USB ఛార్జింగ్కి మద్దతు లేదు."</string>
@@ -73,22 +70,15 @@
<string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ఈ పరికరానికి ప్రస్తుతం సైన్ ఇన్ చేసిన వినియోగదారు USB డీబగ్గింగ్ ఆన్ చేయలేరు. ఈ ఫీచర్ ఉపయోగించడానికి, ప్రాథమిక వినియోగదారుకి మారాలి."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"స్క్రీన్కు నింపేలా జూమ్ చేయండి"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"స్క్రీన్కు నింపేలా విస్తరించండి"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"స్క్రీన్షాట్"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"స్క్రీన్షాట్ను సేవ్ చేస్తోంది…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"స్క్రీన్షాట్ను సేవ్ చేస్తోంది…"</string>
- <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
- <skip />
- <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
- <skip />
- <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
- <skip />
- <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
- <skip />
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"స్క్రీన్షాట్ సేవ్ చేయబడుతోంది"</string>
+ <string name="screenshot_saved_title" msgid="5637073968117370753">"స్క్రీన్షాట్ సేవ్ చేయబడింది"</string>
+ <string name="screenshot_saved_text" msgid="7574667448002050363">"మీ స్క్రీన్షాట్ను వీక్షించడానికి నొక్కండి"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"స్క్రీన్షాట్ను క్యాప్చర్ చేయడం సాధ్యపడలేదు"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"స్క్రీన్షాట్ని సేవ్ చేస్తున్నప్పుడు సమస్య ఏర్పడింది"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"నిల్వ స్థలం పరిమితంగా ఉన్న కారణంగా స్క్రీన్షాట్ను సేవ్ చేయడం సాధ్యపడదు"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"స్క్రీన్షాట్లు తీయడానికి యాప్ లేదా మీ సంస్థ అనుమతించలేదు"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ఫైల్ బదిలీ ఎంపికలు"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"మీడియా ప్లేయర్గా (MTP) మౌంట్ చేయి"</string>
@@ -98,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"హోమ్"</string>
<string name="accessibility_menu" msgid="316839303324695949">"మెను"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"యాక్సెస్ సామర్థ్యం"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"స్క్రీన్ను తిప్పండి"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"అవలోకనం"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"వెతుకు"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"కెమెరా"</string>
@@ -112,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"కెమెరాను తెరువు"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"కొత్త విధి లేఅవుట్ను ఎంచుకోండి"</string>
<string name="cancel" msgid="6442560571259935130">"రద్దు చేయి"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"అనుకూలత జూమ్ బటన్."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"చిన్న స్క్రీన్ నుండి పెద్దదానికి జూమ్ చేయండి."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"బ్లూటూత్ కనెక్ట్ చేయబడింది."</string>
@@ -188,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"రింగర్ నిశ్శబ్దంలో ఉంది."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"పని మోడ్"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ని తీసివేయండి."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> తీసివేయబడింది."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"అన్ని ఇటీవలి అనువర్తనాలు తీసివేయబడ్డాయి."</string>
@@ -285,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"బ్లూటూత్ (<xliff:g id="NUMBER">%d</xliff:g> పరికరాలు)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"బ్లూటూత్ ఆఫ్లో ఉంది"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"జత చేసిన పరికరాలు ఏవీ అందుబాటులో లేవు"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> బ్యాటరీ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"ఆడియో"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"హెడ్సెట్"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ఇన్పుట్"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ప్రకాశం"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"స్వయంచాలకంగా తిప్పడం"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"స్క్రీన్ను స్వయంచాలకంగా తిప్పు"</string>
@@ -325,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"కనెక్ట్ అవుతోంది..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"టీథరింగ్"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"హాట్స్పాట్"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"నోటిఫికేషన్లు"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ఫ్లాష్లైట్"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"మొబైల్ డేటా"</string>
@@ -334,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> వినియోగించబడింది"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> పరిమితి"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> హెచ్చరిక"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"పని మోడ్"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"రాత్రి కాంతి"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"సూర్యాస్తమయానికి"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"సూర్యోదయం వరకు"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g>కి"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> వరకు"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC నిలిపివేయబడింది"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ప్రారంభించబడింది"</string>
@@ -348,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> సురక్షిత-మోడ్లో నిలిపివేయబడింది."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"అన్నీ తీసివేయి"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"విభజన స్క్రీన్ను ఉపయోగించడానికి ఇక్కడ లాగండి"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"సమతలంగా విభజించు"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"లంబంగా విభజించు"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"అనుకూలంగా విభజించు"</string>
@@ -571,27 +585,21 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ఆఫ్లో ఉన్నాయి"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"పవర్ నోటిఫికేషన్ నియంత్రణలతో, మీరు యాప్ నోటిఫికేషన్ల కోసం ప్రాముఖ్యత స్థాయిని 0 నుండి 5 వరకు సెట్ చేయవచ్చు. \n\n"<b>"స్థాయి 5"</b>" \n- నోటిఫికేషన్ జాబితా పైభాగంలో చూపబడతాయి \n- పూర్తి స్క్రీన్ అంతరాయం అనుమతించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 4"</b>\n"- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 3"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n\n"<b>"స్థాయి 2"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం మరియు వైబ్రేషన్ చేయవు \n\n"<b>"స్థాయి 1"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం లేదా వైబ్రేట్ చేయవు \n- లాక్ స్క్రీన్ మరియు స్థితి పట్టీ నుండి దాచబడతాయి \n- నోటిఫికేషన్ జాబితా దిగువ భాగంలో చూపబడతాయి \n\n"<b>"స్థాయి 0"</b>" \n- యాప్ నుండి అన్ని నోటిఫికేషన్లు బ్లాక్ చేయబడతాయి"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"నోటిఫికేషన్లు"</string>
- <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+ <string name="notification_channel_disabled" msgid="344536703863700565">"ఇకపై మీకు ఈ నోటిఫికేషన్లు కనిపించవు"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
<skip />
- <!-- no translation found for inline_keep_showing (8945102997083836858) -->
- <skip />
- <!-- no translation found for inline_stop_button (4172980096860941033) -->
- <skip />
- <!-- no translation found for inline_keep_button (6665940297019018232) -->
- <skip />
- <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
- <skip />
- <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
- <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"ఈ నోటిఫికేషన్లను చూపిస్తూ ఉండాలా?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"నోటిఫికేషన్లను ఆపివేయి"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"చూపిస్తూనే ఉండు"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"ఈ యాప్ నుండి నోటిఫికేషన్లను చూపిస్తూ ఉండాలా?"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"ఈ నోటిఫికేషన్లను ఆఫ్ చేయలేరు"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> యొక్క నోటిఫికేషన్ నియంత్రణలు తెరవబడ్డాయి"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> యొక్క నోటిఫికేషన్ నియంత్రణలు మూసివేయబడ్డాయి"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ఈ ఛానెల్ యొక్క నోటిఫికేషన్లను అనుమతించండి"</string>
<string name="notification_more_settings" msgid="816306283396553571">"మరిన్ని సెట్టింగ్లు"</string>
- <!-- no translation found for notification_app_settings (420348114670768449) -->
- <skip />
+ <string name="notification_app_settings" msgid="420348114670768449">"అనుకూలపరచండి"</string>
<string name="notification_done" msgid="5279426047273930175">"పూర్తయింది"</string>
- <!-- no translation found for inline_undo (558916737624706010) -->
- <skip />
+ <string name="inline_undo" msgid="558916737624706010">"చర్యరద్దు చేయి"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"నోటిఫికేషన్ నియంత్రణలు"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"నోటిఫికేషన్ తాత్కాలిక ఆపివేత ఎంపికలు"</string>
@@ -674,7 +682,8 @@
<item msgid="1545641631806817203">"క్లిప్బోర్డ్"</item>
<item msgid="5742013440802239414">"కీకోడ్"</item>
<item msgid="8802889973626281575">"కీబోర్డ్ స్విచర్"</item>
- <item msgid="8175437057325747277">"ఏదీ వద్దు"</item>
+ <item msgid="7095517796293767867">"భ్రమణ సూచన"</item>
+ <item msgid="8494159969042135235">"ఏదీ కాదు"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"సాధారణం"</item>
@@ -798,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"బ్యాటరీ మరియు డేటా వినియోగ వివరాల కోసం నొక్కండి"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"మొబైల్ డేటాని ఆఫ్ చేయాలా?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"అనుమతి అభ్యర్థనకు ఒక యాప్ అడ్డు తగులుతున్నందున సెట్టింగ్లు మీ ప్రతిస్పందనను ధృవీకరించలేకపోయాయి."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_2">%2$s</xliff:g> స్లైస్లను చూపించడానికి <xliff:g id="APP_0">%1$s</xliff:g>ని అనుమతించండి?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- ఇది <xliff:g id="APP">%1$s</xliff:g> నుండి సమాచారాన్ని చదువుతుంది"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- ఇది <xliff:g id="APP">%1$s</xliff:g> లోపల చర్యలు తీసుకుంటుంది"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"ఏ యాప్ నుండి అయినా స్లైస్లను చూపించడానికి <xliff:g id="APP">%1$s</xliff:g>ని అనుమతించండి"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"అనుమతించు"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"తిరస్కరించు"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 01b75e3..ac4fbc9 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"หน้าแรก"</string>
<string name="accessibility_menu" msgid="316839303324695949">"เมนู"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"ความสามารถเข้าถึงได้ง่าย"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"หมุนหน้าจอ"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"ภาพรวม"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ค้นหา"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"กล้องถ่ายรูป"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"เปิดกล้อง"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"เลือกรูปแบบงานใหม่"</string>
<string name="cancel" msgid="6442560571259935130">"ยกเลิก"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ปุ่มซูมที่ใช้งานร่วมกันได้"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ซูมหน้าจอให้มีขนาดใหญ่ขึ้น"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"เชื่อมต่อบลูทูธแล้ว"</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"เสียงเรียกเข้าแบบปิดเสียง"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"โหมดการทำงาน"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"ยกเลิก <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ถูกลบไปแล้ว"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ปิดแอปพลิเคชันล่าสุดทั้งหมดแล้ว"</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"บลูทูธ (<xliff:g id="NUMBER">%d</xliff:g> อุปกรณ์)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ปิดบลูทูธ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"ไม่มีอุปกรณ์ที่จับคู่ที่สามารถใช้ได้"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"เสียง"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"ชุดหูฟัง"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"อินพุต"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ความสว่าง"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"หมุนอัตโนมัติ"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"หมุนหน้าจออัตโนมัติ"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"กำลังเชื่อมต่อ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"การปล่อยสัญญาณ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ฮอตสปอต"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"การแจ้งเตือน"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ไฟฉาย"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"อินเทอร์เน็ตมือถือ"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"ใช้ไปแล้ว <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"ขีดจำกัด <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"คำเตือน <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"โหมดการทำงาน"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"แสงตอนกลางคืน"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"เปิดตอนพระอาทิตย์ตก"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"จนพระอาทิตย์ขึ้น"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"เปิดเวลา <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"จนถึง <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ถูกปิดใช้งาน"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"เปิดใช้งาน NFC แล้ว"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ปิดใช้ในโหมดปลอดภัย"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"ล้างทั้งหมด"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"ลากมาที่นี่เพื่อใช้การแยกหน้าจอ"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"แยกในแนวนอน"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"แยกในแนวตั้ง"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"แยกแบบกำหนดเอง"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"ส่วนควบคุมการแจ้งเตือนแบบเปิด/ปิดช่วยให้คุณตั้งค่าระดับความสำคัญสำหรับการแจ้งเตือนของแอปได้ตั้งแต่ระดับ 0-5 \n\n"<b>"ระดับ 5"</b>" \n- แสดงที่ด้านบนของรายการแจ้งเตือน \n- อนุญาตให้รบกวนแบบเต็มหน้าจอ \n- อนุญาตให้แสดงชั่วครู่ \n\n"<b>"ระดับ 4"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- แสดงชั่วครู่เสมอ \n\n"<b>"ระดับ 3"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n\n"<b>"ระดับ 2"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n- ไม่ส่งเสียงหรือสั่นเลย \n\n"<b>"ระดับ 1"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n- ไม่ส่งเสียงหรือสั่นเลย \n- ซ่อนจากหน้าจอล็อกและแถบสถานะ \n- แสดงที่ด้านล่างของรายการแจ้งเตือน \n\n"<b>"ระดับ 0"</b>" \n- บล็อกการแจ้งเตือนทั้งหมดจากแอป"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"การแจ้งเตือน"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"คุณจะไม่เห็นการแจ้งเตือนเหล่านี้อีก"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"แสดงการแจ้งเตือนเหล่านี้ต่อไปไหม"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"ปิดการแจ้งเตือน"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"แสดงต่อไป"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"คลิปบอร์ด"</item>
<item msgid="5742013440802239414">"Keycode"</item>
<item msgid="8802889973626281575">"ปุ่มสลับแป้นพิมพ์"</item>
- <item msgid="8175437057325747277">"ไม่มี"</item>
+ <item msgid="7095517796293767867">"คำแนะนำในการหมุน"</item>
+ <item msgid="8494159969042135235">"ไม่มี"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"ปกติ"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"ปิดอินเทอร์เน็ตมือถือไหม"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"เนื่องจากแอปหนึ่งได้บดบังคำขอสิทธิ์ ระบบจึงไม่สามารถยืนยันคำตอบของคุณสำหรับการตั้งค่าได้"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"อนุญาตให้ <xliff:g id="APP_0">%1$s</xliff:g> แสดงส่วนต่างๆ ของ <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- อ่านข้อมูลจาก <xliff:g id="APP">%1$s</xliff:g> ได้"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- ดำเนินการใน <xliff:g id="APP">%1$s</xliff:g> ได้"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"อนุญาตให้ <xliff:g id="APP">%1$s</xliff:g> แสดงส่วนต่างๆ จากแอปใดก็ได้"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"อนุญาต"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"ปฏิเสธ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 5352cf0..97e332b 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Home"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Pagiging Naa-access"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"I-rotate ang screen"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Overview"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Hanapin"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Camera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"buksan ang camera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Pumili ng bagong layout ng gawain"</string>
<string name="cancel" msgid="6442560571259935130">"Kanselahin"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Button ng zoom ng pagiging tugma."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Mag-zoom nang mas maliit sa mas malaking screen."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Nakakonekta ang Bluetooth."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Naka-silent ang ringer."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Work mode"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"I-dismiss ang <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Hindi pinansin ang <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Na-dismiss ang lahat ng kamakailang application."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> (na) Device)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Naka-off ang Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Walang available na mga magkapares na device"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> na baterya"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Headset"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Input"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Awtomatikong i-rotate"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Awtomatikong i-rotate ang screen"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Kumokonekta..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Nagte-tether"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Mga Notification"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ang nagamit"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ang limitasyon"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Babala sa <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work mode"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Mao-on sa sunset"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Hanggang mag-umaga"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Mao-on sa ganap na <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Hanggang <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"Naka-disable ang NFC"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"Naka-enable ang NFC"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Naka-disable ang <xliff:g id="APP">%s</xliff:g> sa safe-mode."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"I-clear lahat"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"I-drag dito upang magamit ang split screen"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Custom"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Sa pamamagitan ng mga kontrol sa notification ng power, magagawa mong itakda ang antas ng kahalagahan ng mga notification ng isang app mula 0 hanggang 5. \n\n"<b>"Antas 5"</b>" \n- Ipakita sa itaas ng listahan ng notification \n- Payagan ang pag-istorbo kapag full screen \n- Palaging sumilip \n\n"<b>"Antas 4"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Palaging sumilip \n\n"<b>"Antas 3"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n\n"<b>"Antas 2"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n- Huwag kailanman tumunog o mag-vibrate \n\n"<b>"Antas 1"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n- Huwag kailanman tumunog o mag-vibrate \n- Itago sa lock screen at status bar \n- Ipakita sa ibaba ng listahan ng notification \n\n"<b>"Antas 0"</b>" \n- I-block ang lahat ng notification mula sa app"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Mga Notification"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Hindi mo na makikita ang mga notification na ito"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Patuloy na ipakita ang mga notification na ito?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Ihinto ang mga notification"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Patuloy na ipakita"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Clipboard"</item>
<item msgid="5742013440802239414">"Keycode"</item>
<item msgid="8802889973626281575">"Keyboard switcher"</item>
- <item msgid="8175437057325747277">"Wala"</item>
+ <item msgid="7095517796293767867">"Suhestyon sa pag-rotate"</item>
+ <item msgid="8494159969042135235">"Wala"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Karaniwan"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"I-tap para sa mga detalye tungkol sa paggamit ng baterya at data"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"I-off ang mobile data?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Hindi ma-verify ng Mga Setting ang iyong tugon dahil may app na tumatakip sa isang kahilingan sa pagpapahintulot."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Payagan ang <xliff:g id="APP_0">%1$s</xliff:g> na ipakita ang mga slice ng <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Nakakabasa ito ng impormasyon mula sa <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Nakakagawa ito ng mga pagkilos sa loob ng <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Payagan ang <xliff:g id="APP">%1$s</xliff:g> na ipakita ang mga slice mula sa anumang app"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Payagan"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Tanggihan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 092cfa5..8a289be 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Ana sayfa"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menü"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Erişilebilirlik"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Ekranı döndür"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Genel Bakış"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Ara"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"kamerayı aç"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Yeni görev düzenini seçin"</string>
<string name="cancel" msgid="6442560571259935130">"İptal"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Uyumluluk zum düğmesi."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Daha büyük ekrana daha küçük yakınlaştır."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth bağlandı."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Telefon zili sessiz."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Çalışma modu"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> uygulamasını kapat."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> kaldırıldı."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tüm son uygulamalar kapatıldı."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Cihaz)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Kapalı"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Kullanılabilir eşlenmiş cihaz yok"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Pil düzeyi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Ses"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Mikrofonlu kulaklık"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Giriş"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Parlaklık"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Otomatik döndür"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Ekranı otomatik döndür"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Bağlanılıyor..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirimler"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Fener"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobil veri"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> kullanıldı"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Sınır: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> uyarısı"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Çalışma modu"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Gece Işığı"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Gün batımı açılacak"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Gün doğumuna kadar"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Şu saatte açılacak: <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Şu saate kadar: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC devre dışı"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC etkin"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>, güvenli modda devre dışıdır."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Tümünü temizle"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Ekranı bölünmüş olarak kullanmak için burayı sürükleyin"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Yatay Ayırma"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dikey Ayırma"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Özel Ayırma"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Güç bildirim kontrolleriyle, bir uygulamanın bildirimleri için 0 ile 5 arasında bir önem düzeyi ayarlayabilirsiniz. \n\n"<b>"5. Düzey"</b>" \n- Bildirim listesinin en üstünde gösterilsin \n- Tam ekran kesintisine izin verilsin \n- Ekranda her zaman kısaca belirsin \n\n"<b>"4. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda her zaman kısaca belirsin \n\n"<b>"3. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n\n"<b>"2. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman belirmesin \n- Hiçbir zaman ses çıkarmasın ve titreştirmesin \n\n"<b>"1. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n- Hiçbir zaman ses çıkarmasın veya titreştirmesin \n- Kilit ekranından ve durum çubuğundan gizlensin \n- Bildirim listesinin en altında gösterilsin \n\n"<b>"0. Düzey"</b>" \n- Uygulamadan gelen tüm bildirimler engellensin"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirimler"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Bu bildirimleri artık görmeyeceksiniz"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Bu bildirimler gösterilmeye devam edilsin mi?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Bildirimleri durdur"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Göstermeye devam et"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Pano"</item>
<item msgid="5742013440802239414">"Tuş kodu"</item>
<item msgid="8802889973626281575">"Klavye değiştirici"</item>
- <item msgid="8175437057325747277">"Yok"</item>
+ <item msgid="7095517796293767867">"Rotasyon önerisi"</item>
+ <item msgid="8494159969042135235">"Yok"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Normal"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Pil ve veri kullanımı ile ilgili ayrıntılar için dokunun"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Mobil veri kapatılsın mı?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Bir uygulama bir izin isteğinin anlaşılmasını engellediğinden, Ayarlar, yanıtınızı doğrulayamıyor."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> uygulamasının, <xliff:g id="APP_2">%2$s</xliff:g> dilimlerini göstermesine izin verilsin mi?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- <xliff:g id="APP">%1$s</xliff:g> uygulamasından bilgileri okuyabilir"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- <xliff:g id="APP">%1$s</xliff:g> uygulamasında işlem yapabilir"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> uygulamasının tüm uygulamalardan dilimleri göstermesine izin ver"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"İzin ver"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Reddet"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 0790847..f296143 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -90,6 +90,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Головна"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Меню"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Спеціальні можливості"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Обернути екран"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Огляд"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Пошук"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Камера"</string>
@@ -104,6 +105,12 @@
<string name="camera_label" msgid="7261107956054836961">"відкрити камеру"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Виберіть новий макет завдання"</string>
<string name="cancel" msgid="6442560571259935130">"Скасувати"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка масштабування сумісності."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Збільшення екрана."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth під’єднано."</string>
@@ -182,7 +189,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Дзвінок беззвучний."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Робочий режим"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Видалити додаток <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Програму <xliff:g id="APP">%s</xliff:g> закрито."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Усі останні додатки закрито."</string>
@@ -281,6 +289,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (пристроїв: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth вимкнено"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Немає спарених пристроїв"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> заряду акумулятора"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Аудіопристрій"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Гарнітура"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Джерело сигналу"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яскравість"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоматичне обертання"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Автоматично обертати екран"</string>
@@ -321,6 +333,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"З’єднання…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Режим модема"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка доступу"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Сповіщення"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ліхтарик"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобільне передавання даних"</string>
@@ -330,8 +345,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Використовується: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Обмеження: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Застереження: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Робочий режим"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Нічний режим"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Вмикається ввечері"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"До сходу сонця"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Вмикається о <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"До <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC вимкнено"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ввімкнено"</string>
@@ -344,6 +366,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Додаток <xliff:g id="APP">%s</xliff:g> вимкнено в безпечному режимі."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Очистити все"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Перетягніть сюди, щоб увімкнути режим розділеного екрана"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Розділити горизонтально"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Розділити вертикально"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Розділити (власний варіант)"</string>
@@ -568,6 +592,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"За допомогою елементів керування сповіщеннями ви можете налаштувати пріоритет сповіщень додатка – від 0 до 5 рівня. \n\n"<b>"Рівень 5"</b>\n"- Показувати сповіщення вгорі списку \n- Виводити на весь екран \n- Завжди показувати короткі сповіщення \n\n"<b>"Рівень 4"</b>\n"- Не виводити на весь екран \n- Завжди показувати короткі сповіщення \n\n"<b>"Рівень 3"</b>\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n\n"<b>"Рівень 2"</b>\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n- Вимкнути звук і вібросигнал \n\n"<b>"Рівень 1"</b>\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n- Вимкнути звук і вібросигнал \n- Не показувати на заблокованому екрані та в рядку стану \n- Показувати сповіщення внизу списку \n\n"<b>"Рівень 0"</b>\n"- Блокувати всі сповіщення з додатка"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Сповіщення"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Ви більше не бачитимете цих сповіщень"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Чи показувати ці сповіщення надалі?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Не показувати сповіщення"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Показувати надалі"</string>
@@ -666,7 +692,8 @@
<item msgid="1545641631806817203">"Буфер обміну"</item>
<item msgid="5742013440802239414">"Код клавіші"</item>
<item msgid="8802889973626281575">"Вибір клавіатури"</item>
- <item msgid="8175437057325747277">"Немає"</item>
+ <item msgid="7095517796293767867">"Пропозиція щодо обертання"</item>
+ <item msgid="8494159969042135235">"Немає"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Звичайна панель"</item>
@@ -790,4 +817,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Торкніться, щоб перевірити використання акумулятора й трафік"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Вимкнути мобільний трафік?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Не вдається підтвердити вашу відповідь у налаштуваннях, оскільки інший додаток заступає запит на дозвіл."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Дозволити додатку <xliff:g id="APP_0">%1$s</xliff:g> показувати фрагменти додатка <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Має доступ до інформації з додатка <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Може виконувати дії в додатку <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Дозволити додатку <xliff:g id="APP">%1$s</xliff:g> показувати фрагменти будь-якого додатка"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Дозволити"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Відмовити"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index ffcb60a..8099ef4 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"ہوم"</string>
<string name="accessibility_menu" msgid="316839303324695949">"مینو"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"ایکسیسبیلٹی"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"اسکرین کو گھمائیں"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"مجموعی جائزہ"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"تلاش کریں"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"کیمرا"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"کیمرا کھولیں"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"نئے کام کا لے آؤٹ منتخب کریں"</string>
<string name="cancel" msgid="6442560571259935130">"منسوخ کریں"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"مطابقت پذیری زوم بٹن۔"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"چھوٹی سے بڑی اسکرین پر زوم کریں۔"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"بلوٹوتھ مربوط ہے۔"</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"رنگر خاموش۔"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"کام موڈ"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> کو مسترد کریں۔"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> کو ہٹا دیا گیا۔"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"سبھی حالیہ ایپلیکیشنز کو برخاست کر دیا گیا۔"</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوٹوتھ (<xliff:g id="NUMBER">%d</xliff:g> آلات)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"بلوٹوتھ آف ہے"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"کوئی جوڑا بنائے ہوئے آلات دستیاب نہیں ہیں"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> بیٹری"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"آڈیو"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"ہیڈ سیٹ"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"ان پٹ"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"چمکیلا پن"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"خود کار طور پر گھمائیں"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"اسکرین کو خود کار طور پر گھمائیں"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"مربوط ہو رہا ہے…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ٹیدرنگ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ہاٹ اسپاٹ"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"اطلاعات"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"فلیش لائٹ"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"موبائل ڈیٹا"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> استعمال کردہ"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> حد"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> وارننگ"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"کام موڈ"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"نائٹ لائٹ"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"غروب آفتاب کے وقت آن ہوگی"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"طلوع آفتاب تک"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"آن ہوگی بوقت <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> بجے تک"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC غیر فعال ہے"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC فعال ہے"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"محفوظ موڈ میں <xliff:g id="APP">%s</xliff:g> غیر فعال ہوتی ہے۔"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"سبھی کو صاف کریں"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"اسپلٹ اسکرین استعمال کرنے کیلئے یہاں گھسیٹیں"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"بلحاظ افقی الگ کریں"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"بلحاظ عمودی الگ کریں"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"بلحاظ حسب ضرورت الگ کریں"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"پاور اطلاع کنٹرولز کے ساتھ آپ کسی ایپ کی اطلاعات کیلئے 0 سے 5 تک اہمیت کی سطح سیٹ کر سکتے ہیں۔ \n\n"<b>"سطح 5"</b>\n"- اطلاعات کی فہرست کے اوپر دکھائیں \n- پوری اسکرین کی مداخلت کی اجازت دیں \n- ہمیشہ جھانکنا\n\n"<b>"سطح 4"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- ہمیشہ جھانکنا\n\n"<b>"سطح 3"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n\n"<b>"سطح 2"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n- کبھی آواز اور ارتعاش پیدا نہ کرنا \n\n"<b>" سطح 1"</b>\n"- پوری اسکرین کی مداخلت کو روکنا \n- کبھی نہ جھانکنا \n- کبھی بھی آواز یا ارتعاش پیدا نہ کرنا\n- مقفل اسکرین اور اسٹیٹس بار سے چھپانا \n - اطلاع کی فہرست کی نیچے دکھانا \n\n"<b>"سطح 0"</b>\n"- ایپ سے تمام اطلاعات مسدود کریں"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"اطلاعات"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"آپ کو یہ اطلاعات مزید دکھائی نہیں دیں گی"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"یہ اطلاعات دکھانا جاری رکھیں؟"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"اطلاعات روک دیں"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"دکھانا جاری رکھیں"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"کلپ بورڈ"</item>
<item msgid="5742013440802239414">"کی کوڈ"</item>
<item msgid="8802889973626281575">"کی بورڈ سوئچر"</item>
- <item msgid="8175437057325747277">"کوئی نہیں"</item>
+ <item msgid="7095517796293767867">"گردش کی تجویز"</item>
+ <item msgid="8494159969042135235">"کوئی نہیں"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"حسب معمول"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"بیٹری اور ڈیٹا استعمال کے بارے میں تفصیلات کے لیے تھپتھپائیں"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"موبائل ڈیٹا آف کریں؟"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"چونکہ ایک ایپ اجازت کی درخواست کو مبہم کر رہی ہے، لہذا ترتیبات آپ کے جواب کی توثیق نہیں کر سکتی ہیں۔"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> کو <xliff:g id="APP_2">%2$s</xliff:g> کے سلائسز دکھانے کی اجازت دیں؟"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- یہ <xliff:g id="APP">%1$s</xliff:g> کی معلومات پڑھ سکتا ہے"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- یہ <xliff:g id="APP">%1$s</xliff:g> کے اندر کارروائیاں کر سکتا ہے"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> کو کسی بھی ایپ سے سلائسز دکھانے کی اجازت دیں"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"اجازت دیں"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"مسترد کریں"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index a8b5e54..612859b 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -75,7 +75,7 @@
<string name="screenshot_saving_title" msgid="8242282144535555697">"Skrinshot saqlanmoqda…"</string>
<string name="screenshot_saving_text" msgid="2545047868936087248">"Skrinshot saqlanmoqda"</string>
<string name="screenshot_saved_title" msgid="5637073968117370753">"Skrinshot saqlandi"</string>
- <string name="screenshot_saved_text" msgid="7574667448002050363">"Skrinshotni ko‘rish uchun bosing"</string>
+ <string name="screenshot_saved_text" msgid="7574667448002050363">"Skrinshotni ochish uchun bosing"</string>
<string name="screenshot_failed_title" msgid="9096484883063264803">"Skrinshot saqlanmadi"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Skrinshotni saqlashda muammo yuz berdi"</string>
<string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Xotirada joy kamligi uchun skrinshot saqlanmadi"</string>
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Uyga"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menyu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Maxsus imkoniyatlar"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Ekranni burish"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Umumiy nazar"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Qidirish"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Kamera"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"kamerani ochish"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Yangi vazifa tartibini tanlash"</string>
<string name="cancel" msgid="6442560571259935130">"Bekor qilish"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kattalashtirish tugmasi mosligi."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kattaroq ekran uchun kichikroqni kattalashtirish."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ulandi."</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ovozsiz qo‘ng‘iroq."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Ish rejimi"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Olib tashlash: <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> olib tashlangan."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Yaqinda ishlatilgan barcha ilovalar olib tashlandi."</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g>ta qurilma)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth o‘chirilgan"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Ulangan qurilmalar topilmadi"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"Batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Audio"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Garnitura"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Matn kiritish"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Yorqinlik"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Avtomatik burilish"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Ekranning avtomatik burilishi"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Ulanmoqda…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Modem rejimi"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirishnomalar"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Fonar"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobil internet"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ishlatilgan"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Cheklov: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Ogohlantirish: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Ish rejimi"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Tungi rejim"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Kunbotarda yoqish"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Quyosh chiqqunicha"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"<xliff:g id="TIME">%s</xliff:g> da yoqish"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"<xliff:g id="TIME">%s</xliff:g> gacha"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC o‘chiq"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC yoniq"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Xavfsiz rejimda <xliff:g id="APP">%s</xliff:g> ilovasi o‘chirib qo‘yildi."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Hammasini tozalash"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Ekranni bo‘lish xususiyatidan foydalanish uchun bu yerga torting"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gorizontal yo‘nalishda bo‘lish"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikal yo‘nalishda bo‘lish"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Boshqa usulda bo‘lish"</string>
@@ -563,12 +587,14 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"O‘chiq"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"Bildirishnomalar uchun kengaytirilgan boshqaruv yordamida ilova bildirishnomalarining muhimlik darajasini (0-5) sozlash mumkin. \n\n"<b>"5-daraja"</b>" \n- Bildirishnomani ro‘yxatning boshida ko‘rsatish \n- To‘liq ekranli bildirishnomalarni ko‘rsatish \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatish \n\n"<b>"4-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatish \n\n"<b>"3-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n\n"<b>"2-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n- Ovoz va tebranishdan foydalanmaslik \n\n"<b>"1-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n- Ovoz va tebranishdan foydalanmaslik \n- Ekran qulfi va holat qatorida ko‘rsatmaslik \n- Bildirishnomani ro‘yxatning oxirida ko‘rsatish \n\n"<b>"0-daraja"</b>" \n- Ilovadan keladigan barcha bildirishnomalarni bloklash"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirishnomalar"</string>
- <string name="notification_channel_disabled" msgid="344536703863700565">"Ushbu bildirishnomalar endi ko‘rsatilmaydi"</string>
- <string name="inline_keep_showing" msgid="8945102997083836858">"Mazkur bildirishnomalar ko‘rsatishda davom etilsinmi?"</string>
- <string name="inline_stop_button" msgid="4172980096860941033">"Bildirishnomalarni to‘xtatish"</string>
- <string name="inline_keep_button" msgid="6665940297019018232">"Ko‘rsatilsin"</string>
- <string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu ilovadan keladigan bildirishnomalar ko‘rsatishda davom etilsinmi?"</string>
- <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ushbu bildirishnomalarni o‘chirib bo‘lmaydi"</string>
+ <string name="notification_channel_disabled" msgid="344536703863700565">"Bu bildirishnomalar endi chiqmaydi"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"Mazkur bildirishnomalar chiqaversinmi?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"Chiqmasin"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"Ha"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu ilovadan keladigan bildirishnomalar chiqaversinmi?"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"Bu bildirishnomalarni chiqmaydigan qilish imkonsiz"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun bildirishnoma sozlamalari ochildi"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun bildirishnoma sozlamalari yopildi"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Bu kanaldan keladigan bildirishnomalarga ruxsat berish"</string>
@@ -658,7 +684,8 @@
<item msgid="1545641631806817203">"Vaqtinchalik xotira"</item>
<item msgid="5742013440802239414">"Tugma kodi"</item>
<item msgid="8802889973626281575">"Klaviaturani almashtirish"</item>
- <item msgid="8175437057325747277">"Hech biri"</item>
+ <item msgid="7095517796293767867">"Burilish"</item>
+ <item msgid="8494159969042135235">"Hech biri"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Odatiy"</item>
@@ -782,4 +809,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Batareya va trafik sarfi tafsilotlari uchun ustiga bosing"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Mobil internet o‘chirib qo‘yilsinmi?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Ilova ruxsatnoma so‘roviga xalaqit qilayotgani tufayli, “Sozlamalar” ilovasi javobingizni tekshira olmaydi."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"<xliff:g id="APP_0">%1$s</xliff:g> ilovasiga <xliff:g id="APP_2">%2$s</xliff:g> ilovasidan fragmentlar ko‘rsatishga ruxsat berilsinmi?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"– <xliff:g id="APP">%1$s</xliff:g> ma’lumotlarini o‘qiy oladi"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"– <xliff:g id="APP">%1$s</xliff:g> ichida amallar bajara oladi"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"<xliff:g id="APP">%1$s</xliff:g> ilovasiga boshqa ilovalardan fragmentlarni ko‘rsatishga ruxsat berish"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Ruxsat"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Rad etish"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index e5c25dc..83bcae5 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Trang chủ"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Trợ năng"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Xoay màn hình"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Tổng quan"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Tìm kiếm"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Máy ảnh"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"mở máy ảnh"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Chọn bố cục tác vụ mới"</string>
<string name="cancel" msgid="6442560571259935130">"Hủy"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Nút thu phóng khả năng tương thích."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Thu phóng màn hình lớn hơn hoặc nhỏ hơn."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Đã kết nối bluetooth."</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Chuông im lặng."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Chế độ làm việc"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Xóa bỏ <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> đã bị loại bỏ."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Đã bỏ qua tất cả các ứng dụng gần đây."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> thiết bị)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Đã tắt Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Không có thiết bị nào được ghép nối"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> pin"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Âm thanh"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Tai nghe"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Thiết bị đầu vào"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Độ sáng"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Tự động xoay"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Tự động xoay màn hình"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Đang kết nối..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Đang dùng làm điểm truy cập Internet"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Điểm phát sóng"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Thông báo"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn pin"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dữ liệu di động"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Đã sử dụng <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Giới hạn <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Cảnh báo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Chế độ làm việc"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Đèn đọc sách"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Bật khi trời tối"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Cho đến khi trời sáng"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Bật vào lúc <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Cho đến <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC đã được tắt"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC đã được bật"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> bị tắt ở chế độ an toàn."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Xóa tất cả"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Kéo vào đây để sử dụng chế độ chia đôi màn hình"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Phân tách ngang"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Phân tách dọc"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tùy chỉnh phân tách"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Với các kiểm soát thông báo nguồn, bạn có thể đặt cấp độ quan trọng từ 0 đến 5 cho các thông báo của ứng dụng. \n\n"<b>"Cấp 5"</b>" \n- Hiển thị ở đầu danh sách thông báo \n- Cho phép gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 4"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 3"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n\n"<b>"Cấp 2"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n\n"<b>"Cấp 1"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n- Ẩn khỏi màn hình khóa và thanh trạng thái \n- Hiển thị ở cuối danh sách thông báo \n\n"<b>"Cấp 0"</b>" \n- Chặn tất cả các thông báo từ ứng dụng"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Thông báo"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Bạn sẽ không thấy các thông báo này nữa"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Tiếp tục hiển thị các thông báo này?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Dừng thông báo"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Tiếp tục hiển thị"</string>
@@ -658,7 +684,8 @@
<item msgid="1545641631806817203">"Khay nhớ tạm"</item>
<item msgid="5742013440802239414">"Mã phím"</item>
<item msgid="8802889973626281575">"Trình chuyển đổi bàn phím"</item>
- <item msgid="8175437057325747277">"Không có"</item>
+ <item msgid="7095517796293767867">"Đề xuất xoay"</item>
+ <item msgid="8494159969042135235">"Không có"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Bình thường"</item>
@@ -782,4 +809,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Tắt dữ liệu di động?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Vì ứng dụng đang che khuất yêu cầu cấp quyền nên Cài đặt không thể xác minh câu trả lời của bạn."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Cho phép <xliff:g id="APP_0">%1$s</xliff:g> hiển thị các lát của <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Có thể đọc thông tin từ <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Có thể thực hiện hành động bên trong <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Cho phép <xliff:g id="APP">%1$s</xliff:g> hiển thị các lát từ mọi ứng dụng"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Cho phép"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Từ chối"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 94a9961..559b2ea 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -33,13 +33,10 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"正在进行的"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
<string name="battery_low_title" msgid="6456385927409742437">"电池电量偏低"</string>
- <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
- <skip />
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"电池电量不足,请开启省电模式"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
- <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
- <skip />
- <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
- <skip />
+ <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"剩余电量:<xliff:g id="PERCENTAGE">%s</xliff:g>;根据您的使用情况,大约还可使用 <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"剩余电量:<xliff:g id="PERCENTAGE">%s</xliff:g>;大约还可使用 <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"剩余 <xliff:g id="PERCENTAGE">%s</xliff:g>。省电模式已开启。"</string>
<string name="invalid_charger" msgid="4549105996740522523">"不支持USB充电功能。\n只能使用随附的充电器充电。"</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"不支持USB充电。"</string>
@@ -73,22 +70,15 @@
<string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"目前已登录此设备的用户无法开启 USB 调试功能。要使用此功能,请切换为主要用户的帐号。"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"缩放以填满屏幕"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"拉伸以填满屏幕"</string>
- <!-- no translation found for global_action_screenshot (8329831278085426283) -->
- <skip />
+ <string name="global_action_screenshot" msgid="8329831278085426283">"屏幕截图"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在保存屏幕截图..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"正在保存屏幕截图..."</string>
- <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
- <skip />
- <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
- <skip />
- <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
- <skip />
- <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
- <skip />
- <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
- <skip />
+ <string name="screenshot_saving_text" msgid="2545047868936087248">"正在保存屏幕截图"</string>
+ <string name="screenshot_saved_title" msgid="5637073968117370753">"已保存屏幕截图"</string>
+ <string name="screenshot_saved_text" msgid="7574667448002050363">"点按即可查看您的屏幕截图"</string>
+ <string name="screenshot_failed_title" msgid="9096484883063264803">"无法抓取屏幕截图"</string>
+ <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"保存屏幕截图时出现问题"</string>
+ <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"由于存储空间有限,无法保存屏幕截图"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"此应用或您所在的单位不允许进行屏幕截图"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB文件传输选项"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"作为媒体播放器(MTP)装载"</string>
@@ -98,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"主屏幕"</string>
<string name="accessibility_menu" msgid="316839303324695949">"菜单"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"无障碍"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"旋转屏幕"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"概览"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"搜索"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"相机"</string>
@@ -112,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"打开相机"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"选择新的任务布局"</string>
<string name="cancel" msgid="6442560571259935130">"取消"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"兼容性缩放按钮。"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"将小屏幕的图片放大在较大屏幕上显示。"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"蓝牙已连接。"</string>
@@ -188,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"振铃器静音。"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"工作模式"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"移除<xliff:g id="APP">%s</xliff:g>。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"已删除<xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"已关闭所有最近用过的应用。"</string>
@@ -285,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"蓝牙(<xliff:g id="NUMBER">%d</xliff:g> 台设备)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"蓝牙:关闭"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"没有可用的配对设备"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"电池电量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"音频"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"耳机"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"输入"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"亮度"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"自动旋转"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"自动旋转屏幕"</string>
@@ -325,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"正在连接…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"网络共享"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"热点"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"手电筒"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"移动数据"</string>
@@ -334,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"已使用<xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"上限为<xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g>警告"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"工作模式"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"夜间模式"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"在日落时开启"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"在日出时关闭"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"在<xliff:g id="TIME">%s</xliff:g> 开启"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"在<xliff:g id="TIME">%s</xliff:g> 关闭"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC 已停用"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC 已启用"</string>
@@ -348,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>已在安全模式下停用。"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"全部清除"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"在此处拖动即可使用分屏功能"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自定义分割"</string>
@@ -571,27 +585,21 @@
<string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"关闭"</string>
<string name="power_notification_controls_description" msgid="4372459941671353358">"利用高级通知设置,您可以为应用通知设置从 0 级到 5 级的重要程度等级。\n\n"<b>"5 级"</b>" \n- 在通知列表顶部显示 \n- 允许全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"4 级"</b>" \n- 禁止全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"3 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n\n"<b>"2 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n\n"<b>"1 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n- 不在锁定屏幕和状态栏中显示 \n- 在通知列表底部显示 \n\n"<b>"0 级"</b>" \n- 屏蔽应用的所有通知"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
- <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+ <string name="notification_channel_disabled" msgid="344536703863700565">"您将不会再看到这些通知"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
<skip />
- <!-- no translation found for inline_keep_showing (8945102997083836858) -->
- <skip />
- <!-- no translation found for inline_stop_button (4172980096860941033) -->
- <skip />
- <!-- no translation found for inline_keep_button (6665940297019018232) -->
- <skip />
- <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
- <skip />
- <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
- <skip />
+ <string name="inline_keep_showing" msgid="8945102997083836858">"要继续显示这些通知吗?"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"停止通知"</string>
+ <string name="inline_keep_button" msgid="6665940297019018232">"继续显示"</string>
+ <string name="inline_keep_showing_app" msgid="1723113469580031041">"要继续显示来自此应用的通知吗?"</string>
+ <string name="notification_unblockable_desc" msgid="1037434112919403708">"无法关闭这些通知"</string>
<string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g>的通知控件已打开"</string>
<string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g>的通知控件已关闭"</string>
<string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"允许接收来自此频道的通知"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多设置"</string>
- <!-- no translation found for notification_app_settings (420348114670768449) -->
- <skip />
+ <string name="notification_app_settings" msgid="420348114670768449">"自定义"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
- <!-- no translation found for inline_undo (558916737624706010) -->
- <skip />
+ <string name="inline_undo" msgid="558916737624706010">"撤消"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g><xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"通知设置"</string>
<string name="notification_menu_snooze_description" msgid="3653669438131034525">"通知延后选项"</string>
@@ -674,7 +682,8 @@
<item msgid="1545641631806817203">"剪贴板"</item>
<item msgid="5742013440802239414">"键码"</item>
<item msgid="8802889973626281575">"键盘切换器"</item>
- <item msgid="8175437057325747277">"无"</item>
+ <item msgid="7095517796293767867">"旋转建议"</item>
+ <item msgid="8494159969042135235">"无"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"一般"</item>
@@ -798,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"点按即可详细了解电量和流量消耗情况"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"要关闭移动数据网络吗?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"由于某个应用遮挡了权限请求界面,因此“设置”应用无法验证您的回应。"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"要允许“<xliff:g id="APP_0">%1$s</xliff:g>”显示“<xliff:g id="APP_2">%2$s</xliff:g>”图块吗?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- 可以读取“<xliff:g id="APP">%1$s</xliff:g>”中的信息"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- 可以在“<xliff:g id="APP">%1$s</xliff:g>”内执行操作"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"允许“<xliff:g id="APP">%1$s</xliff:g>”显示任何应用的图块"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"允许"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"拒绝"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 3e624f2..0283092 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"首頁"</string>
<string name="accessibility_menu" msgid="316839303324695949">"選單"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"無障礙功能"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"旋轉螢幕"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"概覽"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"搜尋"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"相機"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"開啟相機"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"選取新的工作版面配置"</string>
<string name="cancel" msgid="6442560571259935130">"取消"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"藍牙連線已建立。"</string>
@@ -180,7 +187,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"鈴聲靜音。"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"工作模式"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"所有最近使用的應用程式均已關閉。"</string>
@@ -277,6 +285,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 部裝置)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"藍牙關閉"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"找不到配對的裝置"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"音訊"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"耳機"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"輸入"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"亮度"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"自動旋轉"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"自動旋轉螢幕"</string>
@@ -317,6 +329,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"正在連線…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"網絡共享"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"熱點"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"閃光燈"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"流動數據"</string>
@@ -326,8 +341,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"已使用 <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"上限為 <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 警告"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"工作模式"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"夜燈模式"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"在日落時開啟"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"在日出時關閉"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"在<xliff:g id="TIME">%s</xliff:g>開啟"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"在<xliff:g id="TIME">%s</xliff:g>關閉"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC 已停用"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC 已啟用"</string>
@@ -340,6 +362,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"「<xliff:g id="APP">%s</xliff:g>」已在安全模式中停用。"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"全部清除"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"在這裡拖曳即可分割螢幕"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自訂分割"</string>
@@ -564,6 +588,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"通知控制項讓您設定應用程式通知的重要性 (0 至 5 級)。\n\n"<b>"第 5 級"</b>" \n- 在通知清單頂部顯示 \n- 允許全螢幕騷擾 \n- 一律顯示通知 \n\n"<b>"第 4 級"</b>" \n- 阻止全螢幕騷擾 \n- 一律顯示通知 \n\n"<b>"第 3 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n\n"<b>"第 2 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n- 永不發出聲響和震動 \n\n"<b>"第 1 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n- 永不發出聲響和震動 \n- 從上鎖畫面和狀態列中隱藏 \n- 在通知清單底部顯示 \n\n"<b>"第 0 級"</b>" \n- 封鎖所有應用程式通知"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"您不會再看到這些通知"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"要繼續顯示這些通知嗎?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"停止通知"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"繼續顯示"</string>
@@ -658,7 +684,8 @@
<item msgid="1545641631806817203">"剪貼簿"</item>
<item msgid="5742013440802239414">"按鍵碼"</item>
<item msgid="8802889973626281575">"鍵盤切換工具"</item>
- <item msgid="8175437057325747277">"無"</item>
+ <item msgid="7095517796293767867">"旋轉建議"</item>
+ <item msgid="8494159969042135235">"無"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"一般"</item>
@@ -782,4 +809,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"輕按即可查看電池和數據用量詳情"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"要關閉流動數據嗎?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"由於某個應用程式已阻擋權限要求畫面,因此「設定」應用程式無法驗證您的回應。"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"要允許「<xliff:g id="APP_0">%1$s</xliff:g>」顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的快訊嗎?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- 可以讀取「<xliff:g id="APP">%1$s</xliff:g>」中的資料"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- 可以在「<xliff:g id="APP">%1$s</xliff:g>」內執行操作"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"允許「<xliff:g id="APP">%1$s</xliff:g>」顯示任何應用程式的快訊"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"允許"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"拒絕"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index e6ff9d7..e08bf69 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -33,7 +33,7 @@
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"進行中"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
<string name="battery_low_title" msgid="6456385927409742437">"電池電力不足"</string>
- <string name="battery_low_title_hybrid" msgid="6268991275887381595">"電池電力不足,請開啟節約耗電量模式"</string>
+ <string name="battery_low_title_hybrid" msgid="6268991275887381595">"電池電量偏低,請開啟節約耗電量模式"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"僅剩 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"電力剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>,根據你的使用情形,剩餘時間大約還有 <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"電力剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>,剩餘時間大約還有 <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"主螢幕"</string>
<string name="accessibility_menu" msgid="316839303324695949">"選單"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"協助工具"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"旋轉螢幕"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"總覽"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"搜尋"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"相機"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"開啟攝影機"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"選取新工作版面配置"</string>
<string name="cancel" msgid="6442560571259935130">"取消"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"藍牙連線已建立。"</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"鈴聲靜音。"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"工作模式"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近使用的應用程式已全部關閉。"</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 個裝置)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"關閉藍牙"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"找不到配對的裝置"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"音訊"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"耳機"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"輸入"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"亮度"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"自動旋轉"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"自動旋轉螢幕"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"連線中..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"網路共用"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"無線基地台"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"手電筒"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"行動數據"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"已使用 <xliff:g id="DATA_USED">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"上限為 <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 警告"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"工作模式"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"夜燈"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"於日落時開啟"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"於日出時關閉"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"開啟時間:<xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"關閉時間:<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC 已停用"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC 已啟用"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"「<xliff:g id="APP">%s</xliff:g>」在安全模式中為停用狀態。"</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"全部清除"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"拖曳到這裡即可使用分割畫面"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自訂分割"</string>
@@ -562,8 +586,10 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"只要使用電源通知控制項,你就能為應用程式通知設定從 0 到 5 的重要性等級。\n\n"<b>"等級 5"</b>" \n- 顯示在通知清單頂端 \n- 允許全螢幕通知 \n- 一律允許短暫顯示通知 \n\n"<b>"等級 4"</b>" \n- 禁止全螢幕通知 \n- 一律允許短暫顯示通知 \n\n"<b>"等級 3"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n\n"<b>"等級 2"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n\n"<b>"等級 1"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n- 在鎖定畫面和狀態列中隱藏 \n- 顯示在通知清單底端 \n\n"<b>"等級 0"</b>" \n- 封鎖應用程式的所有通知"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"你不會再看到這些通知"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"要繼續顯示這些通知嗎?"</string>
- <string name="inline_stop_button" msgid="4172980096860941033">"停止通知"</string>
+ <string name="inline_stop_button" msgid="4172980096860941033">"停止顯示通知"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"繼續顯示"</string>
<string name="inline_keep_showing_app" msgid="1723113469580031041">"要繼續顯示這個應用程式的通知嗎?"</string>
<string name="notification_unblockable_desc" msgid="1037434112919403708">"無法關閉這些通知"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"剪貼簿"</item>
<item msgid="5742013440802239414">"按鍵碼"</item>
<item msgid="8802889973626281575">"鍵盤切換工具"</item>
- <item msgid="8175437057325747277">"無"</item>
+ <item msgid="7095517796293767867">"旋轉建議"</item>
+ <item msgid="8494159969042135235">"無"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"一般"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"輕觸即可查看電池和數據用量詳情"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"要關閉行動數據嗎?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"由於某個應用程式覆蓋了權限要求畫面,因此「設定」應用程式無法驗證你的回應。"</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"要允許「<xliff:g id="APP_0">%1$s</xliff:g>」顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的區塊嗎?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- 它可以讀取「<xliff:g id="APP">%1$s</xliff:g>」的資訊"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- 它可以在「<xliff:g id="APP">%1$s</xliff:g>」內執行操作"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"允許「<xliff:g id="APP">%1$s</xliff:g>」顯示任何應用程式的區塊"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"允許"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"拒絕"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index a0eb56f..a99b8cc 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -88,6 +88,7 @@
<string name="accessibility_home" msgid="8217216074895377641">"Ekhaya"</string>
<string name="accessibility_menu" msgid="316839303324695949">"Imenyu"</string>
<string name="accessibility_accessibility_button" msgid="7601252764577607915">"Ukufinyeleleka"</string>
+ <string name="accessibility_rotate_button" msgid="7402949513740253006">"Zungezisa isikrini"</string>
<string name="accessibility_recent" msgid="5208608566793607626">"Buka konke"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Sesha"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Ikhamela"</string>
@@ -102,6 +103,12 @@
<string name="camera_label" msgid="7261107956054836961">"vula ikhamera"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"Khetha isakhiwo somsebenzi omusha"</string>
<string name="cancel" msgid="6442560571259935130">"Khansela"</string>
+ <!-- no translation found for accessibility_fingerprint_dialog_fingerprint_icon (3125122495414253226) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_app_icon (3228052542929174609) -->
+ <skip />
+ <!-- no translation found for accessibility_fingerprint_dialog_help_area (5730471601819225159) -->
+ <skip />
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Inkinobho evumelekile yokusondeza"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Sondeza kancane esikrinini esikhudlwana"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ixhunyiwe"</string>
@@ -178,7 +185,8 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Isikhali sithulile."</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"Imodi yomsebenzi"</string>
+ <!-- no translation found for accessibility_work_mode (702887484664647430) -->
+ <skip />
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Cashisa i-<xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ivaliwe."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Zonke izinhlelo zokusebenza zakamuva zicashisiwe."</string>
@@ -275,6 +283,10 @@
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"I-Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> amadivayisi)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"I-Bluetooth ivaliwe"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Awekho amadivayisi abhanqiwe atholakalayo"</string>
+ <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="7106697106764717416">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g> ibhethri"</string>
+ <string name="quick_settings_bluetooth_secondary_label_audio" msgid="5673845963301132071">"Umsindo"</string>
+ <string name="quick_settings_bluetooth_secondary_label_headset" msgid="1880572731276240588">"Ihedisethi"</string>
+ <string name="quick_settings_bluetooth_secondary_label_input" msgid="2173322305072945905">"Okokufaka"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ukugqama"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Ukuphenduka okuzenzakalelayo"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Phendula iskrini ngokuzenzakalela"</string>
@@ -315,6 +327,9 @@
<string name="quick_settings_connecting" msgid="47623027419264404">"Iyaxhuma..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Ukusebenzisa njengemodemu"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"I-Hotspot"</string>
+ <!-- no translation found for quick_settings_hotspot_secondary_label_transient (7161046712706277215) -->
+ <skip />
+ <!-- no translation found for quick_settings_hotspot_secondary_label_num_devices (2324635800672199428) -->
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Izaziso"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"I-Flashlight"</string>
<string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Idatha yeselula"</string>
@@ -324,8 +339,15 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> isetshenzisiwe"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> umkhawulo"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> isexwayiso"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Imodi yomsebenzi"</string>
+ <!-- no translation found for quick_settings_work_mode_on_label (3421274215098764735) -->
+ <skip />
+ <!-- no translation found for quick_settings_work_mode_off_label (8856918707867192186) -->
+ <skip />
<string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ukukhanya kwasebusuku"</string>
+ <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="8483259341596943314">"Kuvulwe ekushoneni kwelanga"</string>
+ <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Kuze kube sekuphumeni kwelanga"</string>
+ <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"Kuvulwe ngo-<xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="quick_settings_night_secondary_label_until" msgid="8664820079774824618">"Kuze kube ngu-<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_nfc_label" msgid="9012153754816969325">"I-NFC"</string>
<string name="quick_settings_nfc_off" msgid="6883274004315134333">"I-NFC ikhutshaziwe"</string>
<string name="quick_settings_nfc_on" msgid="6680317193676884311">"I-NFC inikwe amandla"</string>
@@ -338,6 +360,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"I-<xliff:g id="APP">%s</xliff:g> ikhutshaziwe kumodi yokuphepha."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Sula konke"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Hudulela lapha ukuze usebenzise ukuhlukanisa kwesikrini"</string>
+ <!-- no translation found for recents_swipe_up_onboarding (3824607135920170001) -->
+ <skip />
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Hlukanisa okuvundlile"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Hlukanisa okumile"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Hlukanisa kwezifiso"</string>
@@ -562,6 +586,8 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Ngezilawuli zesaziso zamandla, ungasetha ileveli ebalulekile kusuka ku-0 kuya ku-5 kusuka kuzaziso zohlelo lokusebenza. \n\n"<b>"Ileveli 5"</b>" \n- Ibonisa phezulu kuhlu lwesaziso \n- Vumela ukuphazamiseka kwesikrini esigcwele \n- Ukuhlola njalo \n\n"<b>"Ileveli 4"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukuhlola njalo \n\n"<b>"Ileveli 3"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n\n"<b>"Ileveli 2"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n- Ungenzi umsindo nokudlidliza \n\n"<b>"Ileveli 1"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n- Ungenzi umsindo noma ukudlidliza \n- Fihla kusuka kusikrini sokukhiya nebha yesimo \n- Bonisa phansi kohlu lwesaziso \n\n"<b>"Ileveli 0"</b>" \n- Vimbela zonke izaziso kusuka kuhlelo lokusebenza"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Izaziso"</string>
<string name="notification_channel_disabled" msgid="344536703863700565">"Ngeke usabona lezi zaziso"</string>
+ <!-- no translation found for inline_blocking_helper (3055064577771478591) -->
+ <skip />
<string name="inline_keep_showing" msgid="8945102997083836858">"Qhubeka nokubonisa lezi zaziso?"</string>
<string name="inline_stop_button" msgid="4172980096860941033">"Misa izaziso"</string>
<string name="inline_keep_button" msgid="6665940297019018232">"Qhubeka nokubonisa"</string>
@@ -656,7 +682,8 @@
<item msgid="1545641631806817203">"Ibhodi lokumanathisela"</item>
<item msgid="5742013440802239414">"Ikhodi yokhiye"</item>
<item msgid="8802889973626281575">"Isishintshi sekhibhodi"</item>
- <item msgid="8175437057325747277">"Akunalutho"</item>
+ <item msgid="7095517796293767867">"Isiphakamiso sokuzungezisa"</item>
+ <item msgid="8494159969042135235">"Lutho"</item>
</string-array>
<string-array name="nav_bar_layouts">
<item msgid="8077901629964902399">"Okujwayelekile"</item>
@@ -780,4 +807,10 @@
<string name="running_foreground_services_msg" msgid="6326247670075574355">"Thepha ngemininingwane ekusetshenzisweni kwebhethri nedatha"</string>
<string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vala idatha yeselula?"</string>
<string name="touch_filtered_warning" msgid="8671693809204767551">"Ngoba uhlelo lokusebenza lusitha isicelo semvume, Izilungiselelo azikwazi ukuqinisekisa impendulo yakho."</string>
+ <string name="slice_permission_title" msgid="7465009437851044444">"Vumela i-<xliff:g id="APP_0">%1$s</xliff:g> ukuthi ibonise izingcezu ze-<xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_text_1" msgid="3514586565609596523">"- Ingafunda ulwazi kusukela ku-<xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_text_2" msgid="3146758297471143723">"- Ingenza izenzo ngaphakathi kwe-<xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="slice_permission_checkbox" msgid="7986504458640562900">"Vumela i-<xliff:g id="APP">%1$s</xliff:g> ukuthi ikubonise izingcezu kusukela kunoma iluphi uhlelo lokusebenza"</string>
+ <string name="slice_permission_allow" msgid="2340244901366722709">"Vumela"</string>
+ <string name="slice_permission_deny" msgid="7683681514008048807">"Yenqaba"</string>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 6768470..ae910fe 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -124,7 +124,7 @@
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
- wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night
+ wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night,alarm
</string>
<!-- The tiles to display in QuickSettings -->
@@ -348,8 +348,7 @@
<item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
<item>com.android.systemui.LatencyTester</item>
<item>com.android.systemui.globalactions.GlobalActionsComponent</item>
- <item>com.android.systemui.RoundedCorners</item>
- <item>com.android.systemui.EmulatedDisplayCutout</item>
+ <item>com.android.systemui.ScreenDecorations</item>
<item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
</string-array>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d58c725..3db79d7 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -214,9 +214,6 @@
<!-- Amount of close_handle that will NOT overlap the notification list -->
<dimen name="close_handle_underlap">32dp</dimen>
- <!-- Height of the status bar header bar -->
- <dimen name="status_bar_header_height">178dp</dimen>
-
<!-- Height of the status bar header bar in the car setting. -->
<dimen name="car_status_bar_header_height">128dp</dimen>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index edda613..f9aa821 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -96,5 +96,7 @@
<!-- For StatusBarIconContainer to tag its icon views -->
<item type="id" name="status_bar_view_state_tag" />
+
+ <item type="id" name="display_cutout" />
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6d61a0c..fadcbcd 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -739,6 +739,8 @@
<string name="quick_settings_wifi_on_label">Wi-Fi On</string>
<!-- QuickSettings: Wifi detail panel, text when there are no items [CHAR LIMIT=NONE] -->
<string name="quick_settings_wifi_detail_empty_text">No Wi-Fi networks available</string>
+ <!-- QuickSettings: Alarm title [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_alarm_title">Alarm</string>
<!-- QuickSettings: Cast title [CHAR LIMIT=NONE] -->
<string name="quick_settings_cast_title">Cast</string>
<!-- QuickSettings: Cast detail panel, status text when casting [CHAR LIMIT=NONE] -->
@@ -771,8 +773,10 @@
<string name="quick_settings_tethering_label">Tethering</string>
<!-- QuickSettings: Hotspot. [CHAR LIMIT=NONE] -->
<string name="quick_settings_hotspot_label">Hotspot</string>
+ <!-- QuickSettings: Hotspot. Secondary label shown when the hotspot is being enabled [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_hotspot_secondary_label_transient">Turning on...</string>
<!-- QuickSettings: Hotspot: Secondary label for how many devices are connected to the hotspot [CHAR LIMIT=NONE] -->
- <plurals name="quick_settings_hotspot_num_devices">
+ <plurals name="quick_settings_hotspot_secondary_label_num_devices">
<item quantity="one">%d device</item>
<item quantity="other">%d devices</item>
</plurals>
@@ -1270,16 +1274,30 @@
<!-- Content description for accessibility (not shown on the screen): volume dialog collapse button. [CHAR LIMIT=NONE] -->
<string name="accessibility_volume_collapse">Collapse</string>
+ <!-- content description for audio output chooser [CHAR LIMIT=NONE]-->
+ <string name="accessibility_output_chooser">Switch output device</string>
+
<!-- Screen pinning dialog title. -->
<string name="screen_pinning_title">Screen is pinned</string>
<!-- Screen pinning dialog description. -->
<string name="screen_pinning_description">This keeps it in view until you unpin. Touch & hold Back and Overview to unpin.</string>
+ <string name="screen_pinning_description_recents_invisible">This keeps it in view until you unpin. Touch & hold Back and Home to unpin.</string>
<!-- Screen pinning dialog description. -->
<string name="screen_pinning_description_accessible">This keeps it in view until you unpin. Touch & hold Overview to unpin.</string>
+ <string name="screen_pinning_description_recents_invisible_accessible">This keeps it in view until you unpin. Touch & hold Home to unpin.</string>
+ <!-- Notify use that they are in Lock-to-app -->
+ <string name="screen_pinning_toast">To unpin this screen, touch & hold Back and Overview
+ buttons</string>
+ <string name="screen_pinning_toast_recents_invisible">To unpin this screen, touch & hold Back
+ and Home buttons</string>
<!-- Screen pinning positive response. -->
<string name="screen_pinning_positive">Got it</string>
<!-- Screen pinning negative response. -->
<string name="screen_pinning_negative">No thanks</string>
+ <!-- Enter/Exiting screen pinning indication. -->
+ <string name="screen_pinning_start">Screen pinned</string>
+ <string name="screen_pinning_exit">Screen unpinned</string>
+
<!-- Hide quick settings tile confirmation title -->
<string name="quick_settings_reset_confirmation_title">Hide <xliff:g id="tile_label" example="Hotspot">%1$s</xliff:g>?</string>
diff --git a/packages/SystemUI/shared/Android.mk b/packages/SystemUI/shared/Android.mk
index 5f75f7d..21b0ed8 100644
--- a/packages/SystemUI/shared/Android.mk
+++ b/packages/SystemUI/shared/Android.mk
@@ -30,7 +30,7 @@
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := SystemUISharedLib
+LOCAL_PACKAGE_NAME := SysUISharedLib
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_LIBRARIES := SystemUISharedLib
@@ -39,4 +39,4 @@
include $(BUILD_PACKAGE)
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index cc4bc58..98ede4e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -29,4 +29,14 @@
*/
GraphicBufferCompat screenshot(in Rect sourceCrop, int width, int height, int minLayer,
int maxLayer, boolean useIdentityTransform, int rotation);
+
+ /**
+ * Begins screen pinning on the provided {@param taskId}.
+ */
+ void startScreenPinning(int taskId);
+
+ /**
+ * Called when the overview service has started the recents animation.
+ */
+ void onRecentsAnimationStarted();
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index c9a6ea9..f9e1069 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -32,6 +32,7 @@
import android.app.IAssistDataReceiver;
import android.app.WindowConfiguration.ActivityType;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -48,7 +49,10 @@
import android.os.UserHandle;
import android.util.IconDrawableFactory;
import android.util.Log;
+import android.view.IRecentsAnimationController;
+import android.view.IRecentsAnimationRunner;
+import android.view.RemoteAnimationTarget;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -243,10 +247,9 @@
/**
* Starts the recents activity. The caller should manage the thread on which this is called.
*/
- public void startRecentsActivity(AssistDataReceiverCompat assistDataReceiver, Bundle options,
- ActivityOptions opts, int userId, Consumer<Boolean> resultCallback,
+ public void startRecentsActivity(Intent intent, AssistDataReceiver assistDataReceiver,
+ RecentsAnimationListener animationHandler, Consumer<Boolean> resultCallback,
Handler resultCallbackHandler) {
- Bundle activityOptions = opts != null ? opts.toBundle() : null;
try {
IAssistDataReceiver receiver = null;
if (assistDataReceiver != null) {
@@ -259,8 +262,24 @@
}
};
}
- ActivityManager.getService().startRecentsActivity(receiver, options, activityOptions,
- userId);
+ IRecentsAnimationRunner runner = null;
+ if (animationHandler != null) {
+ runner = new IRecentsAnimationRunner.Stub() {
+ public void onAnimationStart(IRecentsAnimationController controller,
+ RemoteAnimationTarget[] apps) {
+ final RecentsAnimationControllerCompat controllerCompat =
+ new RecentsAnimationControllerCompat(controller);
+ final RemoteAnimationTargetCompat[] appsCompat =
+ RemoteAnimationTargetCompat.wrap(apps);
+ animationHandler.onAnimationStart(controllerCompat, appsCompat);
+ }
+
+ public void onAnimationCanceled() {
+ animationHandler.onAnimationCanceled();
+ }
+ };
+ }
+ ActivityManager.getService().startRecentsActivity(intent, receiver, runner);
if (resultCallback != null) {
resultCallbackHandler.post(new Runnable() {
@Override
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiverCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiver.java
similarity index 80%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiverCompat.java
rename to packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiver.java
index cd943f6..7cd6c51 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiverCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiver.java
@@ -22,7 +22,7 @@
/**
* Abstract class for assist data receivers.
*/
-public abstract class AssistDataReceiverCompat {
- public abstract void onHandleAssistData(Bundle resultData);
- public abstract void onHandleAssistScreenshot(Bitmap screenshot);
+public abstract class AssistDataReceiver {
+ public void onHandleAssistData(Bundle resultData) {}
+ public void onHandleAssistScreenshot(Bitmap screenshot) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
similarity index 70%
rename from packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
rename to packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
index db4f988..38b8ae8 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.pip.phone;
+package com.android.systemui.shared.system;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
+import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
import android.os.Binder;
import android.os.IBinder;
@@ -29,11 +30,12 @@
import android.view.InputEvent;
import android.view.IWindowManager;
import android.view.MotionEvent;
+import android.view.WindowManagerGlobal;
import java.io.PrintWriter;
/**
- * Manages the input consumer that allows the SystemUI to control the PiP.
+ * Manages the input consumer that allows the SystemUI to directly receive touch input.
*/
public class InputConsumerController {
@@ -55,12 +57,12 @@
}
/**
- * Input handler used for the PiP input consumer. Input events are batched and consumed with the
+ * Input handler used for the input consumer. Input events are batched and consumed with the
* SurfaceFlinger vsync.
*/
- private final class PipInputEventReceiver extends BatchedInputEventReceiver {
+ private final class InputEventReceiver extends BatchedInputEventReceiver {
- public PipInputEventReceiver(InputChannel inputChannel, Looper looper) {
+ public InputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper, Choreographer.getSfInstance());
}
@@ -68,7 +70,6 @@
public void onInputEvent(InputEvent event, int displayId) {
boolean handled = true;
try {
- // To be implemented for input handling over Pip windows
if (mListener != null && event instanceof MotionEvent) {
MotionEvent ev = (MotionEvent) event;
handled = mListener.onTouchEvent(ev);
@@ -81,15 +82,35 @@
private final IWindowManager mWindowManager;
private final IBinder mToken;
+ private final String mName;
- private PipInputEventReceiver mInputEventReceiver;
+ private InputEventReceiver mInputEventReceiver;
private TouchListener mListener;
private RegistrationListener mRegistrationListener;
- public InputConsumerController(IWindowManager windowManager) {
+ /**
+ * @param name the name corresponding to the input consumer that is defined in the system.
+ */
+ public InputConsumerController(IWindowManager windowManager, String name) {
mWindowManager = windowManager;
mToken = new Binder();
- registerInputConsumer();
+ mName = name;
+ }
+
+ /**
+ * @return A controller for the pip input consumer.
+ */
+ public static InputConsumerController getPipInputConsumer() {
+ return new InputConsumerController(WindowManagerGlobal.getWindowManagerService(),
+ INPUT_CONSUMER_PIP);
+ }
+
+ /**
+ * @return A controller for the recents animation input consumer.
+ */
+ public static InputConsumerController getRecentsAnimationInputConsumer() {
+ return new InputConsumerController(WindowManagerGlobal.getWindowManagerService(),
+ INPUT_CONSUMER_RECENTS_ANIMATION);
}
/**
@@ -125,12 +146,12 @@
if (mInputEventReceiver == null) {
final InputChannel inputChannel = new InputChannel();
try {
- mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
- mWindowManager.createInputConsumer(mToken, INPUT_CONSUMER_PIP, inputChannel);
+ mWindowManager.destroyInputConsumer(mName);
+ mWindowManager.createInputConsumer(mToken, mName, inputChannel);
} catch (RemoteException e) {
- Log.e(TAG, "Failed to create PIP input consumer", e);
+ Log.e(TAG, "Failed to create input consumer", e);
}
- mInputEventReceiver = new PipInputEventReceiver(inputChannel, Looper.myLooper());
+ mInputEventReceiver = new InputEventReceiver(inputChannel, Looper.myLooper());
if (mRegistrationListener != null) {
mRegistrationListener.onRegistrationChanged(true /* isRegistered */);
}
@@ -143,9 +164,9 @@
public void unregisterInputConsumer() {
if (mInputEventReceiver != null) {
try {
- mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
+ mWindowManager.destroyInputConsumer(mName);
} catch (RemoteException e) {
- Log.e(TAG, "Failed to destroy PIP input consumer", e);
+ Log.e(TAG, "Failed to destroy input consumer", e);
}
mInputEventReceiver.dispose();
mInputEventReceiver = null;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
new file mode 100644
index 0000000..9a7abf8
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -0,0 +1,61 @@
+/*
+ * 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.shared.system;
+
+import android.app.ActivityManager.TaskSnapshot;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.IRecentsAnimationController;
+
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
+public class RecentsAnimationControllerCompat {
+
+ private static final String TAG = RecentsAnimationControllerCompat.class.getSimpleName();
+
+ private IRecentsAnimationController mAnimationController;
+
+ public RecentsAnimationControllerCompat(IRecentsAnimationController animationController) {
+ mAnimationController = animationController;
+ }
+
+ public ThumbnailData screenshotTask(int taskId) {
+ try {
+ TaskSnapshot snapshot = mAnimationController.screenshotTask(taskId);
+ return snapshot != null ? new ThumbnailData(snapshot) : new ThumbnailData();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to screenshot task", e);
+ return new ThumbnailData();
+ }
+ }
+
+ public void setInputConsumerEnabled(boolean enabled) {
+ try {
+ mAnimationController.setInputConsumerEnabled(enabled);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to set input consumer enabled state", e);
+ }
+ }
+
+ public void finish(boolean toHome) {
+ try {
+ mAnimationController.finish(toHome);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to finish recents animation", e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiverCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
similarity index 60%
copy from packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiverCompat.java
copy to packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
index cd943f6..bf6179d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/AssistDataReceiverCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
@@ -16,13 +16,16 @@
package com.android.systemui.shared.system;
-import android.graphics.Bitmap;
-import android.os.Bundle;
+public interface RecentsAnimationListener {
-/**
- * Abstract class for assist data receivers.
- */
-public abstract class AssistDataReceiverCompat {
- public abstract void onHandleAssistData(Bundle resultData);
- public abstract void onHandleAssistScreenshot(Bitmap screenshot);
-}
+ /**
+ * Called when the animation into Recents can start. This call is made on the binder thread.
+ */
+ void onAnimationStart(RecentsAnimationControllerCompat controller,
+ RemoteAnimationTargetCompat[] apps);
+
+ /**
+ * Called when the animation into Recents was canceled. This call is made on the binder thread.
+ */
+ void onAnimationCanceled();
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
index cb5afec..b8a07cd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
@@ -16,14 +16,18 @@
package com.android.keyguard;
+import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.view.View;
+import android.view.WindowManager;
import android.widget.Button;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionInfo;
@@ -50,8 +54,17 @@
if (ACTION_DISABLE_ESIM.equals(intent.getAction())) {
int resultCode = getResultCode();
if (resultCode != EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK) {
- // TODO (b/62680294): Surface more info. to the end users for this failure.
Log.e(TAG, "Error disabling esim, result code = " + resultCode);
+ AlertDialog.Builder builder =
+ new AlertDialog.Builder(mContext)
+ .setMessage(R.string.error_disable_esim_msg)
+ .setTitle(R.string.error_disable_esim_title)
+ .setCancelable(false /* cancelable */)
+ .setNeutralButton(R.string.ok, null /* listener */);
+ AlertDialog alertDialog = builder.create();
+ alertDialog.getWindow().setType(
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ alertDialog.show();
}
}
}
@@ -101,14 +114,13 @@
@Override
public void onClick(View v) {
- Intent intent = new Intent(mContext, KeyguardEsimArea.class);
- intent.setAction(ACTION_DISABLE_ESIM);
+ Intent intent = new Intent(ACTION_DISABLE_ESIM);
intent.setPackage(mContext.getPackageName());
- PendingIntent callbackIntent = PendingIntent.getBroadcast(
+ PendingIntent callbackIntent = PendingIntent.getBroadcastAsUser(
mContext,
0 /* requestCode */,
intent,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT, UserHandle.SYSTEM);
mEuiccManager
.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID, callbackIntent);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index e7432ba..703b205 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -131,7 +131,7 @@
}
if (isEsimLocked) {
- msg = msg + " " + rez.getString(R.string.kg_sim_lock_instructions_esim);
+ msg = rez.getString(R.string.kg_sim_lock_esim_instructions, msg);
}
mSecurityMessageDisplay.setMessage(msg);
@@ -187,6 +187,10 @@
msgId = isDefault ? R.string.kg_sim_pin_instructions : R.string.kg_password_pin_failed;
displayMessage = getContext().getString(msgId);
}
+ if (KeyguardEsimArea.isEsimLocked(mContext, mSubId)) {
+ displayMessage = getResources()
+ .getString(R.string.kg_sim_lock_esim_instructions, displayMessage);
+ }
if (DEBUG) Log.d(LOG_TAG, "getPinPasswordErrorMessage:"
+ " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
return displayMessage;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index afee8ec..347c979 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -181,7 +181,7 @@
}
}
if (isEsimLocked) {
- msg = msg + " " + rez.getString(R.string.kg_sim_lock_instructions_esim);
+ msg = rez.getString(R.string.kg_sim_lock_esim_instructions, msg);
}
mSecurityMessageDisplay.setMessage(msg);
mSimImageView.setImageTintList(ColorStateList.valueOf(color));
@@ -231,6 +231,10 @@
R.string.kg_password_puk_failed;
displayMessage = getContext().getString(msgId);
}
+ if (KeyguardEsimArea.isEsimLocked(mContext, mSubId)) {
+ displayMessage = getResources()
+ .getString(R.string.kg_sim_lock_esim_instructions, displayMessage);
+ }
if (DEBUG) Log.d(LOG_TAG, "getPukPasswordErrorMessage:"
+ " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
return displayMessage;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index cb732c4..5d1bdab 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -20,9 +20,7 @@
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.Observer;
import android.content.Context;
-import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.Settings;
@@ -43,7 +41,6 @@
import com.android.systemui.keyguard.KeyguardSliceProvider;
import com.android.systemui.tuner.TunerService;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
@@ -160,8 +157,7 @@
} else {
mRow.removeView(button);
}
- button.setHasDivider(i < subItemsCount - 1);
- mRow.addView(button, i);
+ mRow.addView(button);
PendingIntent pendingIntent = null;
if (rc.getContentIntent() != null) {
@@ -317,51 +313,20 @@
/**
* Representation of an item that appears under the clock on main keyguard message.
- * Shows optional separator.
*/
private class KeyguardSliceButton extends Button {
- private static final float SEPARATOR_HEIGHT = 0.7f;
- private final Paint mPaint;
- private boolean mHasDivider;
-
public KeyguardSliceButton(Context context) {
- super(context, null /* attrs */,
+ super(context, null /* attrs */, 0 /* styleAttr */,
com.android.keyguard.R.style.TextAppearance_Keyguard_Secondary);
- mPaint = new Paint();
- mPaint.setStyle(Paint.Style.STROKE);
- float dividerWidth = context.getResources()
- .getDimension(R.dimen.widget_separator_thickness);
- mPaint.setStrokeWidth(dividerWidth);
int horizontalPadding = (int) context.getResources()
.getDimension(R.dimen.widget_horizontal_padding);
- setPadding(horizontalPadding, 0, horizontalPadding, 0);
+ setPadding(horizontalPadding / 2, 0, horizontalPadding / 2, 0);
setCompoundDrawablePadding((int) context.getResources()
.getDimension(R.dimen.widget_icon_padding));
setMaxWidth(KeyguardSliceView.this.getWidth() / 2);
setMaxLines(1);
setEllipsize(TruncateAt.END);
}
-
- public void setHasDivider(boolean hasDivider) {
- mHasDivider = hasDivider;
- }
-
- @Override
- public void setTextColor(int color) {
- super.setTextColor(color);
- mPaint.setColor(color);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mHasDivider) {
- final int lineX = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : getWidth();
- final int height = (int) (getHeight() * SEPARATOR_HEIGHT);
- final int startY = getHeight() / 2 - height / 2;
- canvas.drawLine(lineX, startY, lineX, startY + height, mPaint);
- }
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 8666b0c..1ae06d7 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -119,18 +119,10 @@
addView(mBatteryIconView, mlp);
updateShowPercent();
-
- Context dualToneDarkTheme = new ContextThemeWrapper(context,
- Utils.getThemeAttr(context, R.attr.darkIconTheme));
- Context dualToneLightTheme = new ContextThemeWrapper(context,
- Utils.getThemeAttr(context, R.attr.lightIconTheme));
- mDarkModeBackgroundColor = Utils.getColorAttr(dualToneDarkTheme, R.attr.backgroundColor);
- mDarkModeFillColor = Utils.getColorAttr(dualToneDarkTheme, R.attr.fillColor);
- mLightModeBackgroundColor = Utils.getColorAttr(dualToneLightTheme, R.attr.backgroundColor);
- mLightModeFillColor = Utils.getColorAttr(dualToneLightTheme, R.attr.fillColor);
-
+ setColorsFromContext(context);
// Init to not dark at all.
onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
+
mUserTracker = new CurrentUserTracker(mContext) {
@Override
public void onUserSwitched(int newUserId) {
@@ -148,6 +140,21 @@
updateShowPercent();
}
+ public void setColorsFromContext(Context context) {
+ if (context == null) {
+ return;
+ }
+
+ Context dualToneDarkTheme = new ContextThemeWrapper(context,
+ Utils.getThemeAttr(context, R.attr.darkIconTheme));
+ Context dualToneLightTheme = new ContextThemeWrapper(context,
+ Utils.getThemeAttr(context, R.attr.lightIconTheme));
+ mDarkModeBackgroundColor = Utils.getColorAttr(dualToneDarkTheme, R.attr.backgroundColor);
+ mDarkModeFillColor = Utils.getColorAttr(dualToneDarkTheme, R.attr.fillColor);
+ mLightModeBackgroundColor = Utils.getColorAttr(dualToneLightTheme, R.attr.backgroundColor);
+ mLightModeFillColor = Utils.getColorAttr(dualToneLightTheme, R.attr.fillColor);
+ }
+
@Override
public boolean hasOverlappingRendering() {
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java b/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java
deleted file mode 100644
index 5d2e4d0..0000000
--- a/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui;
-
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PixelFormat;
-import android.view.DisplayCutout;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-
-/**
- * Emulates a display cutout by drawing its shape in an overlay as supplied by
- * {@link DisplayCutout}.
- */
-public class EmulatedDisplayCutout extends SystemUI implements ConfigurationListener {
- private View mOverlay;
- private boolean mAttached;
- private WindowManager mWindowManager;
-
- @Override
- public void start() {
- Dependency.get(ConfigurationController.class).addCallback(this);
-
- mWindowManager = mContext.getSystemService(WindowManager.class);
- updateAttached();
- }
-
- @Override
- public void onOverlayChanged() {
- updateAttached();
- }
-
- private void updateAttached() {
- boolean shouldAttach = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout);
- setAttached(shouldAttach);
- }
-
- private void setAttached(boolean attached) {
- if (attached && !mAttached) {
- if (mOverlay == null) {
- mOverlay = new CutoutView(mContext);
- mOverlay.setLayoutParams(getLayoutParams());
- }
- mWindowManager.addView(mOverlay, mOverlay.getLayoutParams());
- mAttached = true;
- } else if (!attached && mAttached) {
- mWindowManager.removeView(mOverlay);
- mAttached = false;
- }
- }
-
- private WindowManager.LayoutParams getLayoutParams() {
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
- | WindowManager.LayoutParams.FLAG_SLIPPERY
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR,
- PixelFormat.TRANSLUCENT);
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS
- | WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
- lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- lp.setTitle("EmulatedDisplayCutout");
- lp.gravity = Gravity.TOP;
- return lp;
- }
-
- private static class CutoutView extends View {
- private final Paint mPaint = new Paint();
- private final Path mBounds = new Path();
-
- CutoutView(Context context) {
- super(context);
- }
-
- @Override
- public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mBounds.reset();
- if (insets.getDisplayCutout() != null) {
- insets.getDisplayCutout().getBounds().getBoundaryPath(mBounds);
- }
- invalidate();
- return insets.consumeDisplayCutout();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- if (!mBounds.isEmpty()) {
- mPaint.setColor(Color.BLACK);
- mPaint.setStyle(Paint.Style.FILL);
-
- canvas.drawPath(mBounds, mPaint);
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 244c1b9..8d8b726 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -37,6 +37,7 @@
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.GraphicBufferCompat;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.CallbackController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
@@ -67,6 +68,7 @@
private int mConnectionBackoffAttempts;
private ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
+
public GraphicBufferCompat screenshot(Rect sourceCrop, int width, int height, int minLayer,
int maxLayer, boolean useIdentityTransform, int rotation) {
long token = Binder.clearCallingIdentity();
@@ -77,6 +79,32 @@
Binder.restoreCallingIdentity(token);
}
}
+
+ public void startScreenPinning(int taskId) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mHandler.post(() -> {
+ StatusBar statusBar = ((SystemUIApplication) mContext).getComponent(
+ StatusBar.class);
+ if (statusBar != null) {
+ statusBar.showScreenPinningRequest(taskId, false /* allowCancel */);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public void onRecentsAnimationStarted() {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mHandler.post(() -> {
+ notifyRecentsAnimationStarted();
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
};
private final BroadcastReceiver mLauncherAddedReceiver = new BroadcastReceiver() {
@@ -214,6 +242,12 @@
}
}
+ private void notifyRecentsAnimationStarted() {
+ for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+ mConnectionCallbacks.get(i).onRecentsAnimationStarted();
+ }
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(TAG_OPS + " state:");
@@ -224,6 +258,7 @@
}
public interface OverviewProxyListener {
- void onConnectionChanged(boolean isConnected);
+ default void onConnectionChanged(boolean isConnected) {}
+ default void onRecentsAnimationStarted() {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
deleted file mode 100644
index c960fa1..0000000
--- a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui;
-
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-
-import static com.android.systemui.tuner.TunablePadding.FLAG_START;
-import static com.android.systemui.tuner.TunablePadding.FLAG_END;
-
-import android.app.Fragment;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.PixelFormat;
-import android.provider.Settings.Secure;
-import android.support.annotation.VisibleForTesting;
-import android.util.DisplayMetrics;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnLayoutChangeListener;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowManager;
-import android.widget.ImageView;
-
-import com.android.systemui.R.id;
-import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
-import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.qs.SecureSetting;
-import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
-import com.android.systemui.statusbar.phone.NavigationBarFragment;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.tuner.TunablePadding;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.tuner.TunerService.Tunable;
-
-public class RoundedCorners extends SystemUI implements Tunable {
- public static final String SIZE = "sysui_rounded_size";
- public static final String PADDING = "sysui_rounded_content_padding";
-
- private int mRoundedDefault;
- private View mOverlay;
- private View mBottomOverlay;
- private float mDensity;
- private TunablePadding mQsPadding;
- private TunablePadding mStatusBarPadding;
- private TunablePadding mNavBarPadding;
-
- @Override
- public void start() {
- mRoundedDefault = mContext.getResources().getDimensionPixelSize(
- R.dimen.rounded_corner_radius);
- if (mRoundedDefault != 0) {
- setupRounding();
- }
- int padding = mContext.getResources().getDimensionPixelSize(
- R.dimen.rounded_corner_content_padding);
- if (padding != 0) {
- setupPadding(padding);
- }
- }
-
- private void setupRounding() {
- mOverlay = LayoutInflater.from(mContext)
- .inflate(R.layout.rounded_corners, null);
- mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
- mOverlay.setAlpha(0);
- mOverlay.findViewById(R.id.right).setRotation(90);
-
- mContext.getSystemService(WindowManager.class)
- .addView(mOverlay, getWindowLayoutParams());
- mBottomOverlay = LayoutInflater.from(mContext)
- .inflate(R.layout.rounded_corners, null);
- mBottomOverlay.setAlpha(0);
- mBottomOverlay.findViewById(R.id.right).setRotation(180);
- mBottomOverlay.findViewById(R.id.left).setRotation(270);
- WindowManager.LayoutParams layoutParams = getWindowLayoutParams();
- layoutParams.gravity = Gravity.BOTTOM;
- mContext.getSystemService(WindowManager.class)
- .addView(mBottomOverlay, layoutParams);
-
- DisplayMetrics metrics = new DisplayMetrics();
- mContext.getSystemService(WindowManager.class)
- .getDefaultDisplay().getMetrics(metrics);
- mDensity = metrics.density;
-
- Dependency.get(TunerService.class).addTunable(this, SIZE);
-
- // Watch color inversion and invert the overlay as needed.
- SecureSetting setting = new SecureSetting(mContext, Dependency.get(Dependency.MAIN_HANDLER),
- Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
- @Override
- protected void handleValueChanged(int value, boolean observedChange) {
- int tint = value != 0 ? Color.WHITE : Color.BLACK;
- ColorStateList tintList = ColorStateList.valueOf(tint);
- ((ImageView) mOverlay.findViewById(id.left)).setImageTintList(tintList);
- ((ImageView) mOverlay.findViewById(id.right)).setImageTintList(tintList);
- ((ImageView) mBottomOverlay.findViewById(id.left)).setImageTintList(tintList);
- ((ImageView) mBottomOverlay.findViewById(id.right)).setImageTintList(tintList);
- }
- };
- setting.setListening(true);
- setting.onChange(false);
-
- mOverlay.addOnLayoutChangeListener(new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft,
- int oldTop, int oldRight, int oldBottom) {
- mOverlay.removeOnLayoutChangeListener(this);
- mOverlay.animate()
- .alpha(1)
- .setDuration(1000)
- .start();
- mBottomOverlay.animate()
- .alpha(1)
- .setDuration(1000)
- .start();
- }
- });
- }
-
- private void setupPadding(int padding) {
- // Add some padding to all the content near the edge of the screen.
- StatusBar sb = getComponent(StatusBar.class);
- View statusBar = (sb != null ? sb.getStatusBarWindow() : null);
- if (statusBar != null) {
- TunablePadding.addTunablePadding(statusBar.findViewById(R.id.keyguard_header), PADDING,
- padding, FLAG_END);
-
- FragmentHostManager fragmentHostManager = FragmentHostManager.get(statusBar);
- fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG,
- new TunablePaddingTagListener(padding, R.id.status_bar));
- fragmentHostManager.addTagListener(QS.TAG,
- new TunablePaddingTagListener(padding, R.id.header));
- }
- }
-
- private WindowManager.LayoutParams getWindowLayoutParams() {
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- LayoutParams.WRAP_CONTENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
- | WindowManager.LayoutParams.FLAG_SLIPPERY
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
- PixelFormat.TRANSLUCENT);
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS
- | WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
- lp.setTitle("RoundedOverlay");
- lp.gravity = Gravity.TOP;
- lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- return lp;
- }
-
-
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (mOverlay == null) return;
- if (SIZE.equals(key)) {
- int size = mRoundedDefault;
- try {
- size = (int) (Integer.parseInt(newValue) * mDensity);
- } catch (Exception e) {
- }
- setSize(mOverlay.findViewById(R.id.left), size);
- setSize(mOverlay.findViewById(R.id.right), size);
- setSize(mBottomOverlay.findViewById(R.id.left), size);
- setSize(mBottomOverlay.findViewById(R.id.right), size);
- }
- }
-
- private void setSize(View view, int pixelSize) {
- LayoutParams params = view.getLayoutParams();
- params.width = pixelSize;
- params.height = pixelSize;
- view.setLayoutParams(params);
- }
-
- @VisibleForTesting
- static class TunablePaddingTagListener implements FragmentListener {
-
- private final int mPadding;
- private final int mId;
- private TunablePadding mTunablePadding;
-
- public TunablePaddingTagListener(int padding, int id) {
- mPadding = padding;
- mId = id;
- }
-
- @Override
- public void onFragmentViewCreated(String tag, Fragment fragment) {
- if (mTunablePadding != null) {
- mTunablePadding.destroy();
- }
- View view = fragment.getView();
- if (mId != 0) {
- view = view.findViewById(mId);
- }
- mTunablePadding = TunablePadding.addTunablePadding(view, PADDING, mPadding,
- FLAG_START | FLAG_END);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
new file mode 100644
index 0000000..0b3e9e5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
+import static com.android.systemui.tuner.TunablePadding.FLAG_START;
+import static com.android.systemui.tuner.TunablePadding.FLAG_END;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.provider.Settings.Secure;
+import android.support.annotation.VisibleForTesting;
+import android.util.DisplayMetrics;
+import android.view.DisplayCutout;
+import android.view.DisplayInfo;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnLayoutChangeListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.tuner.TunablePadding;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+/**
+ * An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
+ * for antialiasing and emulation purposes.
+ */
+public class ScreenDecorations extends SystemUI implements Tunable {
+ public static final String SIZE = "sysui_rounded_size";
+ public static final String PADDING = "sysui_rounded_content_padding";
+
+ private int mRoundedDefault;
+ private View mOverlay;
+ private View mBottomOverlay;
+ private float mDensity;
+ private WindowManager mWindowManager;
+ private boolean mLandscape;
+
+ @Override
+ public void start() {
+ mWindowManager = mContext.getSystemService(WindowManager.class);
+ mRoundedDefault = mContext.getResources().getDimensionPixelSize(
+ R.dimen.rounded_corner_radius);
+ if (mRoundedDefault != 0 || shouldDrawCutout()) {
+ setupDecorations();
+ }
+ int padding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.rounded_corner_content_padding);
+ if (padding != 0) {
+ setupPadding(padding);
+ }
+ }
+
+ private void setupDecorations() {
+ mOverlay = LayoutInflater.from(mContext)
+ .inflate(R.layout.rounded_corners, null);
+ ((ViewGroup)mOverlay).addView(new DisplayCutoutView(mContext, true,
+ this::updateWindowVisibilities));
+ mBottomOverlay = LayoutInflater.from(mContext)
+ .inflate(R.layout.rounded_corners, null);
+ ((ViewGroup)mBottomOverlay).addView(new DisplayCutoutView(mContext, false,
+ this::updateWindowVisibilities));
+
+ mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ mOverlay.setAlpha(0);
+
+ mBottomOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ mBottomOverlay.setAlpha(0);
+
+ updateViews();
+
+ mWindowManager.addView(mOverlay, getWindowLayoutParams());
+ mWindowManager.addView(mBottomOverlay, getBottomLayoutParams());
+
+ DisplayMetrics metrics = new DisplayMetrics();
+ mWindowManager.getDefaultDisplay().getMetrics(metrics);
+ mDensity = metrics.density;
+
+ Dependency.get(TunerService.class).addTunable(this, SIZE);
+
+ // Watch color inversion and invert the overlay as needed.
+ SecureSetting setting = new SecureSetting(mContext, Dependency.get(Dependency.MAIN_HANDLER),
+ Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
+ @Override
+ protected void handleValueChanged(int value, boolean observedChange) {
+ int tint = value != 0 ? Color.WHITE : Color.BLACK;
+ ColorStateList tintList = ColorStateList.valueOf(tint);
+ ((ImageView) mOverlay.findViewById(R.id.left)).setImageTintList(tintList);
+ ((ImageView) mOverlay.findViewById(R.id.right)).setImageTintList(tintList);
+ ((ImageView) mBottomOverlay.findViewById(R.id.left)).setImageTintList(tintList);
+ ((ImageView) mBottomOverlay.findViewById(R.id.right)).setImageTintList(tintList);
+ }
+ };
+ setting.setListening(true);
+ setting.onChange(false);
+
+ mOverlay.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ mOverlay.removeOnLayoutChangeListener(this);
+ mOverlay.animate()
+ .alpha(1)
+ .setDuration(1000)
+ .start();
+ mBottomOverlay.animate()
+ .alpha(1)
+ .setDuration(1000)
+ .start();
+ }
+ });
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ boolean newLanscape = newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
+ if (newLanscape != mLandscape) {
+ mLandscape = newLanscape;
+
+ if (mOverlay != null) {
+ updateLayoutParams();
+ updateViews();
+ }
+ }
+ if (shouldDrawCutout() && mOverlay == null) {
+ setupDecorations();
+ }
+ }
+
+ private void updateViews() {
+ View topLeft = mOverlay.findViewById(R.id.left);
+ View topRight = mOverlay.findViewById(R.id.right);
+ View bottomLeft = mBottomOverlay.findViewById(R.id.left);
+ View bottomRight = mBottomOverlay.findViewById(R.id.right);
+ if (mLandscape) {
+ // Flip corners
+ View tmp = topRight;
+ topRight = bottomLeft;
+ bottomLeft = tmp;
+ }
+ updateView(topLeft, Gravity.TOP | Gravity.LEFT, 0);
+ updateView(topRight, Gravity.TOP | Gravity.RIGHT, 90);
+ updateView(bottomLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
+ updateView(bottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
+
+ updateWindowVisibilities();
+ }
+
+ private void updateView(View v, int gravity, int rotation) {
+ ((FrameLayout.LayoutParams)v.getLayoutParams()).gravity = gravity;
+ v.setRotation(rotation);
+ }
+
+ private void updateWindowVisibilities() {
+ updateWindowVisibility(mOverlay);
+ updateWindowVisibility(mBottomOverlay);
+ }
+
+ private void updateWindowVisibility(View overlay) {
+ boolean visibleForCutout = shouldDrawCutout()
+ && overlay.findViewById(R.id.display_cutout).getVisibility() == View.VISIBLE;
+ boolean visibleForRoundedCorners = mRoundedDefault > 0;
+ overlay.setVisibility(visibleForCutout || visibleForRoundedCorners
+ ? View.VISIBLE : View.GONE);
+ }
+
+ private boolean shouldDrawCutout() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout);
+ }
+
+ private void setupPadding(int padding) {
+ // Add some padding to all the content near the edge of the screen.
+ StatusBar sb = getComponent(StatusBar.class);
+ View statusBar = (sb != null ? sb.getStatusBarWindow() : null);
+ if (statusBar != null) {
+ TunablePadding.addTunablePadding(statusBar.findViewById(R.id.keyguard_header), PADDING,
+ padding, FLAG_END);
+
+ FragmentHostManager fragmentHostManager = FragmentHostManager.get(statusBar);
+ fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG,
+ new TunablePaddingTagListener(padding, R.id.status_bar));
+ fragmentHostManager.addTagListener(QS.TAG,
+ new TunablePaddingTagListener(padding, R.id.header));
+ }
+ }
+
+ @VisibleForTesting
+ WindowManager.LayoutParams getWindowLayoutParams() {
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_SLIPPERY
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ PixelFormat.TRANSLUCENT);
+ lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS
+ | WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
+ lp.setTitle("ScreenDecorOverlay");
+ lp.gravity = Gravity.TOP | Gravity.LEFT;
+ lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ if (mLandscape) {
+ lp.width = WRAP_CONTENT;
+ lp.height = MATCH_PARENT;
+ }
+ return lp;
+ }
+
+ private WindowManager.LayoutParams getBottomLayoutParams() {
+ WindowManager.LayoutParams lp = getWindowLayoutParams();
+ lp.setTitle("ScreenDecorOverlayBottom");
+ lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+ return lp;
+ }
+
+ private void updateLayoutParams() {
+ mWindowManager.updateViewLayout(mOverlay, getWindowLayoutParams());
+ mWindowManager.updateViewLayout(mBottomOverlay, getBottomLayoutParams());
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (mOverlay == null) return;
+ if (SIZE.equals(key)) {
+ int size = mRoundedDefault;
+ try {
+ size = (int) (Integer.parseInt(newValue) * mDensity);
+ } catch (Exception e) {
+ }
+ setSize(mOverlay.findViewById(R.id.left), size);
+ setSize(mOverlay.findViewById(R.id.right), size);
+ setSize(mBottomOverlay.findViewById(R.id.left), size);
+ setSize(mBottomOverlay.findViewById(R.id.right), size);
+ }
+ }
+
+ private void setSize(View view, int pixelSize) {
+ LayoutParams params = view.getLayoutParams();
+ params.width = pixelSize;
+ params.height = pixelSize;
+ view.setLayoutParams(params);
+ }
+
+ @VisibleForTesting
+ static class TunablePaddingTagListener implements FragmentListener {
+
+ private final int mPadding;
+ private final int mId;
+ private TunablePadding mTunablePadding;
+
+ public TunablePaddingTagListener(int padding, int id) {
+ mPadding = padding;
+ mId = id;
+ }
+
+ @Override
+ public void onFragmentViewCreated(String tag, Fragment fragment) {
+ if (mTunablePadding != null) {
+ mTunablePadding.destroy();
+ }
+ View view = fragment.getView();
+ if (mId != 0) {
+ view = view.findViewById(mId);
+ }
+ mTunablePadding = TunablePadding.addTunablePadding(view, PADDING, mPadding,
+ FLAG_START | FLAG_END);
+ }
+ }
+
+ public static class DisplayCutoutView extends View implements DisplayManager.DisplayListener {
+
+ private final DisplayInfo mInfo = new DisplayInfo();
+ private final Paint mPaint = new Paint();
+ private final Rect mBoundingRect = new Rect();
+ private final Path mBoundingPath = new Path();
+ private final int[] mLocation = new int[2];
+ private final boolean mStart;
+ private final Runnable mVisibilityChangedListener;
+
+ public DisplayCutoutView(Context context, boolean start,
+ Runnable visibilityChangedListener) {
+ super(context);
+ mStart = start;
+ mVisibilityChangedListener = visibilityChangedListener;
+ setId(R.id.display_cutout);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mContext.getSystemService(DisplayManager.class).registerDisplayListener(this,
+ getHandler());
+ update();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ getLocationOnScreen(mLocation);
+ canvas.translate(-mLocation[0], -mLocation[1]);
+ if (!mBoundingPath.isEmpty()) {
+ mPaint.setColor(Color.BLACK);
+ mPaint.setStyle(Paint.Style.FILL);
+ canvas.drawPath(mBoundingPath, mPaint);
+ }
+ }
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId == getDisplay().getDisplayId()) {
+ update();
+ }
+ }
+
+ private void update() {
+ requestLayout();
+ getDisplay().getDisplayInfo(mInfo);
+ mBoundingRect.setEmpty();
+ mBoundingPath.reset();
+ int newVisible;
+ if (hasCutout()) {
+ mBoundingRect.set(mInfo.displayCutout.getBoundingRect());
+ mInfo.displayCutout.getBounds().getBoundaryPath(mBoundingPath);
+ newVisible = VISIBLE;
+ } else {
+ newVisible = GONE;
+ }
+ if (newVisible != getVisibility()) {
+ setVisibility(newVisible);
+ mVisibilityChangedListener.run();
+ }
+ }
+
+ private boolean hasCutout() {
+ if (mInfo.displayCutout == null) {
+ return false;
+ }
+ DisplayCutout displayCutout = mInfo.displayCutout.calculateRelativeTo(
+ new Rect(0, 0, mInfo.logicalWidth, mInfo.logicalHeight));
+ if (mStart) {
+ return displayCutout.getSafeInsetLeft() > 0
+ || displayCutout.getSafeInsetTop() > 0;
+ } else {
+ return displayCutout.getSafeInsetRight() > 0
+ || displayCutout.getSafeInsetBottom() > 0;
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (mBoundingRect.isEmpty()) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ return;
+ }
+ setMeasuredDimension(
+ resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0),
+ resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0));
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SysUIToast.java b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
index 89bc82f..43b918d 100644
--- a/packages/SystemUI/src/com/android/systemui/SysUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
@@ -15,13 +15,19 @@
*/
package com.android.systemui;
+import android.annotation.StringRes;
import android.content.Context;
import android.view.WindowManager;
import android.widget.Toast;
+import static android.widget.Toast.Duration;
public class SysUIToast {
- public static Toast makeText(Context context, CharSequence text, int duration) {
+ public static Toast makeText(Context context, @StringRes int resId, @Duration int duration) {
+ return makeText(context, context.getString(resId), duration);
+ }
+
+ public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
Toast toast = Toast.makeText(context, text, duration);
toast.getWindowParams().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
index 174584d..245d240 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
@@ -18,23 +18,9 @@
import android.content.Context;
import android.util.ArrayMap;
-import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.Dependency;
import com.android.systemui.Dependency.DependencyProvider;
-import com.android.systemui.ForegroundServiceController;
import com.android.systemui.SystemUIFactory;
-import com.android.systemui.UiOffloadThread;
-import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.statusbar.NotificationEntryManager;
-import com.android.systemui.statusbar.NotificationGutsManager;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.volume.car.CarVolumeDialogController;
/**
* Class factory to provide car specific SystemUI components.
@@ -44,7 +30,6 @@
public void injectDependencies(ArrayMap<Object, DependencyProvider> providers,
Context context) {
super.injectDependencies(providers, context);
- providers.put(VolumeDialogController.class, () -> new CarVolumeDialogController(context));
providers.put(NotificationEntryManager.class,
() -> new CarNotificationEntryManager(context));
}
diff --git a/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
deleted file mode 100644
index 085ece7..0000000
--- a/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.chooser;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.util.Log;
-
-import com.android.systemui.R;
-
-import java.lang.Thread;
-import java.util.ArrayList;
-
-public final class ChooserActivity extends Activity {
-
- private static final String TAG = "ChooserActivity";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- ChooserHelper.onChoose(this);
- finish();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java b/packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java
deleted file mode 100644
index ac22568..0000000
--- a/packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.chooser;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.util.Log;
-
-import com.android.systemui.R;
-
-public class ChooserHelper {
-
- private static final String TAG = "ChooserHelper";
-
- static void onChoose(Activity activity) {
- final Intent thisIntent = activity.getIntent();
- final Bundle thisExtras = thisIntent.getExtras();
- final Intent chosenIntent = thisIntent.getParcelableExtra(Intent.EXTRA_INTENT);
- final Bundle options = thisIntent.getParcelableExtra(ActivityManager.EXTRA_OPTIONS);
- final IBinder permissionToken =
- thisExtras.getBinder(ActivityManager.EXTRA_PERMISSION_TOKEN);
- final boolean ignoreTargetSecurity =
- thisIntent.getBooleanExtra(ActivityManager.EXTRA_IGNORE_TARGET_SECURITY, false);
- final int userId = thisIntent.getIntExtra(Intent.EXTRA_USER_ID, -1);
- activity.startActivityAsCaller(
- chosenIntent, options, permissionToken, ignoreTargetSecurity, userId);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 0f34513..c28b7ee 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -147,6 +147,7 @@
private boolean mHasTelephony;
private boolean mHasVibrator;
private boolean mHasLogoutButton;
+ private boolean mHasLockdownButton;
private final boolean mShowSilentToggle;
private final EmergencyAffordanceManager mEmergencyAffordanceManager;
private final ScreenshotHelper mScreenshotHelper;
@@ -311,6 +312,7 @@
ArraySet<String> addedKeys = new ArraySet<String>();
mHasLogoutButton = false;
+ mHasLockdownButton = false;
for (int i = 0; i < defaultActions.length; i++) {
String actionKey = defaultActions[i];
if (addedKeys.contains(actionKey)) {
@@ -341,6 +343,7 @@
Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0
&& shouldDisplayLockdown()) {
mItems.add(getLockdownAction());
+ mHasLockdownButton = true;
}
} else if (GLOBAL_ACTION_KEY_VOICEASSIST.equals(actionKey)) {
mItems.add(getVoiceAssistAction());
@@ -587,9 +590,9 @@
// switching user
mHandler.postDelayed(() -> {
try {
+ int currentUserId = getCurrentUser().id;
ActivityManager.getService().switchUser(UserHandle.USER_SYSTEM);
- ActivityManager.getService().stopUser(getCurrentUser().id, true /*force*/,
- null);
+ ActivityManager.getService().stopUser(currentUserId, true /*force*/, null);
} catch (RemoteException re) {
Log.e(TAG, "Couldn't logout user " + re);
}
@@ -871,10 +874,9 @@
public View getView(int position, View convertView, ViewGroup parent) {
Action action = getItem(position);
View view = action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
- // When there is no logout button, only power off and restart should be in white
- // background, thus setting division view at third item; with logout button being the
- // third item, set the division view at fourth item instead.
- if (position == (mHasLogoutButton ? 3 : 2)) {
+ // Power off, restart, logout (if present) and lockdown (if present) should be in white
+ // background. Set the division based on which buttons are currently being displayed.
+ if (position == 2 + (mHasLogoutButton ? 1 : 0) + (mHasLockdownButton ? 1 : 0)) {
HardwareUiLayout.get(parent).setDivisionView(view);
}
return view;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 8501519..653e500 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -707,10 +707,6 @@
&& !mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser()),
mSecondaryDisplayShowing, true /* forceCallbacks */);
- } else {
- // The system's keyguard is disabled or missing.
- setShowingLocked(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()),
- mSecondaryDisplayShowing, true);
}
mStatusBarKeyguardViewManager =
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 36531bb..24d0126 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -16,12 +16,10 @@
package com.android.systemui.pip.phone;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.INPUT_CONSUMER_PIP;
import android.app.ActivityManager;
-import android.app.ActivityManager.StackInfo;
import android.app.IActivityManager;
import android.content.ComponentName;
import android.content.Context;
@@ -43,6 +41,7 @@
import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.InputConsumerController;
import java.io.PrintWriter;
@@ -174,7 +173,8 @@
}
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
- mInputConsumerController = new InputConsumerController(mWindowManager);
+ mInputConsumerController = InputConsumerController.getPipInputConsumer();
+ mInputConsumerController.registerInputConsumer();
mMediaController = new PipMediaController(context, mActivityManager);
mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController,
mInputConsumerController);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 9fb201b..26fced3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -23,7 +23,6 @@
import android.app.ActivityOptions;
import android.app.IActivityManager;
import android.app.RemoteAction;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
@@ -43,6 +42,7 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.component.HidePipMenuEvent;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
+import com.android.systemui.shared.system.InputConsumerController;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index c0fed34..b253517 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -46,6 +46,7 @@
import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.policy.PipSnapAlgorithm;
import com.android.systemui.R;
+import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.statusbar.FlingAnimationUtils;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index b43e99b..e661fa7 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -44,6 +44,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
@@ -242,7 +243,9 @@
}
// Show the correct version of low battery warning if needed
- maybeShowBatteryWarning(plugged, oldPlugged, oldBucket, bucket);
+ ThreadUtils.postOnBackgroundThread(() -> {
+ maybeShowBatteryWarning(plugged, oldPlugged, oldBucket, bucket);
+ });
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mScreenOffTime = SystemClock.elapsedRealtime();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
index f960dc5..2a2bc09 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
@@ -51,10 +51,11 @@
public AutoAddTracker(Context context) {
mContext = context;
mAutoAdded = new ArraySet<>(getAdded());
+ // TODO: remove migration code and shared preferences keys after P release
for (String[] convertPref : CONVERT_PREFS) {
if (Prefs.getBoolean(context, convertPref[0], false)) {
setTileAdded(convertPref[1]);
- Prefs.putBoolean(context, convertPref[0], false);
+ Prefs.remove(context, convertPref[0]);
}
}
mContext.getContentResolver().registerContentObserver(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 95185c0..001b409 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -44,7 +44,11 @@
public static final float EXPANDED_TILE_DELAY = .86f;
private final ArrayList<View> mAllViews = new ArrayList<>();
- private final ArrayList<View> mTopFiveQs = new ArrayList<>();
+ /**
+ * List of {@link View}s representing Quick Settings that are being animated from the quick QS
+ * position to the normal QS panel.
+ */
+ private final ArrayList<View> mQuickQsViews = new ArrayList<>();
private final QuickQSPanel mQuickQsPanel;
private final QSPanel mQsPanel;
private final QS mQs;
@@ -157,7 +161,7 @@
clearAnimationState();
mAllViews.clear();
- mTopFiveQs.clear();
+ mQuickQsViews.clear();
QSTileLayout tileLayout = mQsPanel.getTileLayout();
mAllViews.add((View) tileLayout);
@@ -198,7 +202,7 @@
translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
translationYBuilder.addFloat(tileView, "translationY", -yDiff, 0);
- mTopFiveQs.add(tileView.getIcon());
+ mQuickQsViews.add(tileView.getIconWithBackground());
mAllViews.add(tileView.getIcon());
mAllViews.add(quickTileView);
} else if (mFullRows && isIconInAnimatedRow(count)) {
@@ -322,9 +326,9 @@
@Override
public void onAnimationAtEnd() {
mQuickQsPanel.setVisibility(View.INVISIBLE);
- final int N = mTopFiveQs.size();
+ final int N = mQuickQsViews.size();
for (int i = 0; i < N; i++) {
- mTopFiveQs.get(i).setVisibility(View.VISIBLE);
+ mQuickQsViews.get(i).setVisibility(View.VISIBLE);
}
}
@@ -332,9 +336,9 @@
public void onAnimationStarted() {
mQuickQsPanel.setVisibility(mOnKeyguard ? View.INVISIBLE : View.VISIBLE);
if (mOnFirstPage) {
- final int N = mTopFiveQs.size();
+ final int N = mQuickQsViews.size();
for (int i = 0; i < N; i++) {
- mTopFiveQs.get(i).setVisibility(View.INVISIBLE);
+ mQuickQsViews.get(i).setVisibility(View.INVISIBLE);
}
}
}
@@ -348,9 +352,9 @@
v.setTranslationX(0);
v.setTranslationY(0);
}
- final int N2 = mTopFiveQs.size();
+ final int N2 = mQuickQsViews.size();
for (int i = 0; i < N2; i++) {
- mTopFiveQs.get(i).setVisibility(View.VISIBLE);
+ mQuickQsViews.get(i).setVisibility(View.VISIBLE);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index 92475da..76baee4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -84,6 +84,8 @@
protected View mEdit;
private TouchAnimator mAnimator;
+ private View mActionsContainer;
+
public QSFooterImpl(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -107,6 +109,8 @@
mMultiUserSwitch = findViewById(R.id.multi_user_switch);
mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
+ mActionsContainer = findViewById(R.id.qs_footer_actions_container);
+
// RenderThread is doing more harm than good when touching the header (to expand quick
// settings), so disable it for this view
((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
@@ -158,10 +162,8 @@
@Nullable
private TouchAnimator createSettingsAlphaAnimator() {
return new TouchAnimator.Builder()
- .addFloat(mEdit, "alpha", 0, 1)
- .addFloat(mMultiUserSwitch, "alpha", 0, 1)
.addFloat(mCarrierText, "alpha", 0, 1)
- .addFloat(mSettingsButton, "alpha", 0, 1)
+ .addFloat(mActionsContainer, "alpha", 0, 1)
.build();
}
@@ -269,6 +271,11 @@
@Override
public void onClick(View v) {
+ // Don't do anything until view are unhidden
+ if (!mExpanded) {
+ return;
+ }
+
if (v == mSettingsButton) {
if (!Dependency.get(DeviceProvisionedController.class).isCurrentUserSetup()) {
// If user isn't setup just unlock the device and dump them back at SUW.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 29a8f16..d8e1051 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -69,7 +69,7 @@
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
Bundle savedInstanceState) {
- inflater =inflater.cloneInContext(new ContextThemeWrapper(getContext(), R.style.qs_theme));
+ inflater = inflater.cloneInContext(new ContextThemeWrapper(getContext(), R.style.qs_theme));
return inflater.inflate(R.layout.qs_panel, container, false);
}
@@ -285,17 +285,22 @@
int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom()
+ mFooter.getHeight();
mQSPanel.setTranslationY(translationScaleY * heightDiff);
- mQSDetail.setFullyExpanded(expansion == 1);
+ boolean fullyExpanded = expansion == 1;
+ mQSDetail.setFullyExpanded(fullyExpanded);
+ if (fullyExpanded) {
+ // Always draw within the bounds of the view when fully expanded.
+ mQSPanel.setClipBounds(null);
+ } else {
+ // Set bounds on the QS panel so it doesn't run over the header when animating.
+ mQsBounds.top = (int) -mQSPanel.getTranslationY();
+ mQsBounds.right = mQSPanel.getWidth();
+ mQsBounds.bottom = mQSPanel.getHeight();
+ mQSPanel.setClipBounds(mQsBounds);
+ }
if (mQSAnimator != null) {
mQSAnimator.setPosition(expansion);
}
-
- // Set bounds on the QS panel so it doesn't run over the header.
- mQsBounds.top = (int) -mQSPanel.getTranslationY();
- mQsBounds.right = mQSPanel.getWidth();
- mQsBounds.bottom = mQSPanel.getHeight();
- mQSPanel.setClipBounds(mQsBounds);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 17ede65..4d7333b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -97,7 +97,6 @@
mIconManager.setTint(fillColor);
BatteryMeterView battery = findViewById(R.id.battery);
- battery.setFillColor(Color.WHITE);
battery.setForceShowPercent(true);
mActivityStarter = Dependency.get(ActivityStarter.class);
@@ -166,7 +165,8 @@
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
mHeaderQsPanel.setDisabledByPolicy(disabled);
- final int rawHeight = (int) getResources().getDimension(R.dimen.status_bar_header_height);
+ final int rawHeight = (int) getResources().getDimension(
+ com.android.internal.R.dimen.quick_qs_total_height);
getLayoutParams().height = disabled ? (rawHeight - mHeaderQsPanel.getHeight()) : rawHeight;
}
@@ -215,6 +215,11 @@
//host.setHeaderView(mExpandIndicator);
mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
mHeaderQsPanel.setHost(host, null /* No customization in header */);
+
+ // Use SystemUI context to get battery meter colors, and let it use the default tint (white)
+ BatteryMeterView battery = findViewById(R.id.battery);
+ battery.setColorsFromContext(mHost.getContext());
+ battery.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
}
public void setCallback(Callback qsPanelCallback) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 77c3bfa..bf9746e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -23,6 +23,7 @@
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tiles.AirplaneModeTile;
+import com.android.systemui.qs.tiles.AlarmTile;
import com.android.systemui.qs.tiles.BatterySaverTile;
import com.android.systemui.qs.tiles.BluetoothTile;
import com.android.systemui.qs.tiles.CastTile;
@@ -69,6 +70,7 @@
else if (tileSpec.equals("saver")) return new DataSaverTile(mHost);
else if (tileSpec.equals("night")) return new NightDisplayTile(mHost);
else if (tileSpec.equals("nfc")) return new NfcTile(mHost);
+ else if (tileSpec.equals("alarm")) return new AlarmTile(mHost);
// Intent tiles.
else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(mHost, tileSpec);
else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(mHost, tileSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index b4cfda6..c9c678c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -236,6 +236,10 @@
return mIcon;
}
+ public View getIconWithBackground() {
+ return mIconFrame;
+ }
+
@Override
public boolean performClick() {
mClicked = true;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.java
new file mode 100644
index 0000000..ff3fe73
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.java
@@ -0,0 +1,102 @@
+/*
+ * 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.qs.tiles;
+
+import static android.service.quicksettings.Tile.STATE_ACTIVE;
+import static android.service.quicksettings.Tile.STATE_UNAVAILABLE;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.QS_ALARM;
+import static com.android.systemui.keyguard.KeyguardSliceProvider.formatNextAlarm;
+
+import android.app.AlarmManager.AlarmClockInfo;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.provider.AlarmClock;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+
+public class AlarmTile extends QSTileImpl implements NextAlarmChangeCallback {
+ private final NextAlarmController mController;
+ private String mNextAlarm;
+ private PendingIntent mIntent;
+
+ public AlarmTile(QSTileHost host) {
+ super(host);
+ mController = Dependency.get(NextAlarmController.class);
+ }
+
+ @Override
+ public State newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ if (mIntent != null) {
+ Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(mIntent);
+ }
+ }
+
+ @Override
+ protected void handleUpdateState(State state, Object arg) {
+ state.state = mNextAlarm != null ? STATE_ACTIVE : STATE_UNAVAILABLE;
+ state.label = getTileLabel();
+ state.secondaryLabel = mNextAlarm;
+ state.icon = ResourceIcon.get(R.drawable.stat_sys_alarm);
+ ((BooleanState) state).value = mNextAlarm != null;
+ }
+
+ @Override
+ public void onNextAlarmChanged(AlarmClockInfo nextAlarm) {
+ if (nextAlarm != null) {
+ mNextAlarm = formatNextAlarm(mContext, nextAlarm);
+ mIntent = nextAlarm.getShowIntent();
+ } else {
+ mNextAlarm = null;
+ mIntent = null;
+ }
+ refreshState();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return QS_ALARM;
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return new Intent(AlarmClock.ACTION_SET_ALARM);
+ }
+
+ @Override
+ protected void handleSetListening(boolean listening) {
+ if (listening) {
+ mController.addCallback(this);
+ } else {
+ mController.removeCallback(this);
+ }
+ }
+
+ @Override
+ public CharSequence getTileLabel() {
+ return mContext.getString(R.string.status_bar_alarm);
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index eb2e519..aaf6ef5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -76,9 +76,6 @@
private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE";
private static final String EXTRA_VISIBLE = "visible";
- private static final QSTile.Icon TOTAL_SILENCE =
- ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence);
-
private final ZenModeController mController;
private final DndDetailAdapter mDetailAdapter;
@@ -201,25 +198,22 @@
state.slash.isSlashed = !state.value;
state.label = getTileLabel();
state.secondaryLabel = getSecondaryLabel(zen != Global.ZEN_MODE_OFF);
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);
switch (zen) {
case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
- state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_dnd_priority_on);
break;
case Global.ZEN_MODE_NO_INTERRUPTIONS:
- state.icon = TOTAL_SILENCE;
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_dnd_none_on);
break;
case ZEN_MODE_ALARMS:
- state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_dnd_alarms_on);
break;
default:
- state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_dnd);
break;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index e1b58fe..080e320 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -113,11 +113,11 @@
if (state.slash == null) {
state.slash = new SlashState();
}
- state.label = mContext.getString(R.string.quick_settings_hotspot_label);
-
- checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING);
final int numConnectedDevices;
+ final boolean isTransient = mController.isHotspotTransient();
+
+ checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING);
if (arg instanceof CallbackInfo) {
CallbackInfo info = (CallbackInfo) arg;
state.value = info.enabled;
@@ -127,11 +127,11 @@
numConnectedDevices = mController.getNumConnectedDevices();
}
- state.secondaryLabel = getSecondaryLabel(state.value, numConnectedDevices);
-
state.icon = mEnabledStatic;
+ state.label = mContext.getString(R.string.quick_settings_hotspot_label);
+ state.secondaryLabel = getSecondaryLabel(state.value, isTransient, numConnectedDevices);
state.isAirplaneMode = mAirplaneMode.getValue() != 0;
- state.isTransient = mController.isHotspotTransient();
+ state.isTransient = isTransient;
state.slash.isSlashed = !state.value && !state.isTransient;
if (state.isTransient) {
state.icon = ResourceIcon.get(R.drawable.ic_hotspot_transient_animation);
@@ -143,10 +143,13 @@
}
@Nullable
- private String getSecondaryLabel(boolean enabled, int numConnectedDevices) {
- if (numConnectedDevices > 0 && enabled) {
+ private String getSecondaryLabel(
+ boolean enabled, boolean isTransient, int numConnectedDevices) {
+ if (isTransient) {
+ return mContext.getString(R.string.quick_settings_hotspot_secondary_label_transient);
+ } else if (numConnectedDevices > 0 && enabled) {
return mContext.getResources().getQuantityString(
- R.plurals.quick_settings_hotspot_num_devices,
+ R.plurals.quick_settings_hotspot_secondary_label_num_devices,
numConnectedDevices,
numConnectedDevices);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 316ad16..57f7818 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -23,15 +23,12 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Configuration;
import android.graphics.PixelFormat;
-import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Binder;
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.view.Gravity;
-import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -43,6 +40,9 @@
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.phone.NavigationBarView;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.leak.RotationUtils;
import java.util.ArrayList;
@@ -233,11 +233,30 @@
.setVisibility(View.INVISIBLE);
}
+ StatusBar statusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
+ NavigationBarView navigationBarView = statusBar.getNavigationBarView();
+ final boolean recentsVisible = navigationBarView != null
+ && navigationBarView.isRecentsButtonVisible();
boolean touchExplorationEnabled = mAccessibilityService.isTouchExplorationEnabled();
+ int descriptionStringResId;
+ if (recentsVisible) {
+ mLayout.findViewById(R.id.screen_pinning_recents_group).setVisibility(VISIBLE);
+ mLayout.findViewById(R.id.screen_pinning_home_bg_light).setVisibility(INVISIBLE);
+ mLayout.findViewById(R.id.screen_pinning_home_bg).setVisibility(INVISIBLE);
+ descriptionStringResId = touchExplorationEnabled
+ ? R.string.screen_pinning_description_accessible
+ : R.string.screen_pinning_description;
+ } else {
+ mLayout.findViewById(R.id.screen_pinning_recents_group).setVisibility(INVISIBLE);
+ mLayout.findViewById(R.id.screen_pinning_home_bg_light).setVisibility(VISIBLE);
+ mLayout.findViewById(R.id.screen_pinning_home_bg).setVisibility(VISIBLE);
+ descriptionStringResId = touchExplorationEnabled
+ ? R.string.screen_pinning_description_recents_invisible_accessible
+ : R.string.screen_pinning_description_recents_invisible;
+ }
+
((TextView) mLayout.findViewById(R.id.screen_pinning_description))
- .setText(touchExplorationEnabled
- ? R.string.screen_pinning_description_accessible
- : R.string.screen_pinning_description);
+ .setText(descriptionStringResId);
final int backBgVisibility = touchExplorationEnabled ? View.INVISIBLE : View.VISIBLE;
mLayout.findViewById(R.id.screen_pinning_back_bg).setVisibility(backBgVisibility);
mLayout.findViewById(R.id.screen_pinning_back_bg_light).setVisibility(backBgVisibility);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SwipeUpOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/SwipeUpOnboarding.java
index 0494e1b..b2472bf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SwipeUpOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SwipeUpOnboarding.java
@@ -73,7 +73,6 @@
private final RippleDrawable mLightRipple;
private boolean mTaskListenerRegistered;
- private ComponentName mLauncherComponent;
private boolean mLayoutAttachedToWindow;
private boolean mBackgroundIsLight;
@@ -92,15 +91,7 @@
Prefs.putInt(mContext, Prefs.Key.NUM_APPS_LAUNCHED, numAppsLaunched);
}
} else {
- String runningPackage = info.topActivity.getPackageName();
- // TODO: use callback from the overview proxy service to handle this case
- if (runningPackage.equals(mLauncherComponent.getPackageName())
- && activityType == ACTIVITY_TYPE_RECENTS) {
- Prefs.putBoolean(mContext, Prefs.Key.HAS_SWIPED_UP_FOR_RECENTS, true);
- onDisconnectedFromLauncher();
- } else {
- hide(false);
- }
+ hide(false);
}
}
};
@@ -127,8 +118,8 @@
final Resources res = context.getResources();
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mLayout = LayoutInflater.from(mContext).inflate(R.layout.recents_swipe_up_onboarding, null);
- mTextView = (TextView) mLayout.findViewById(R.id.onboarding_text);
- mDismissView = (ImageView) mLayout.findViewById(R.id.dismiss);
+ mTextView = mLayout.findViewById(R.id.onboarding_text);
+ mDismissView = mLayout.findViewById(R.id.dismiss);
mDarkBackgroundColor = res.getColor(android.R.color.background_dark);
mLightBackgroundColor = res.getColor(android.R.color.background_light);
mDarkContentColor = res.getColor(R.color.primary_text_default_material_light);
@@ -149,13 +140,7 @@
}
}
- public void onConnectedToLauncher(ComponentName launcherComponent) {
- // TODO: re-enable this once we have the proper callback for when a swipe up was performed.
- final boolean disableOnboarding = true;
- if (disableOnboarding) {
- return;
- }
- mLauncherComponent = launcherComponent;
+ public void onConnectedToLauncher() {
boolean alreadyLearnedSwipeUpForRecents = Prefs.getBoolean(mContext,
Prefs.Key.HAS_SWIPED_UP_FOR_RECENTS, false);
if (!mTaskListenerRegistered && !alreadyLearnedSwipeUpForRecents) {
@@ -164,6 +149,15 @@
}
}
+ public void onRecentsAnimationStarted() {
+ boolean alreadyLearnedSwipeUpForRecents = Prefs.getBoolean(mContext,
+ Prefs.Key.HAS_SWIPED_UP_FOR_RECENTS, false);
+ if (!alreadyLearnedSwipeUpForRecents) {
+ Prefs.putBoolean(mContext, Prefs.Key.HAS_SWIPED_UP_FOR_RECENTS, true);
+ onDisconnectedFromLauncher();
+ }
+ }
+
public void onDisconnectedFromLauncher() {
if (mTaskListenerRegistered) {
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskListener);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 0132fa8..bf4a225 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -293,6 +293,7 @@
sharingIntent.setType("image/png");
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
+ sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Create a share action for the notification. Note, we proxy the call to
// ScreenshotActionReceiver because RemoteViews currently forces an activity options
@@ -310,7 +311,9 @@
Intent editIntent = new Intent(Intent.ACTION_EDIT);
editIntent.setType("image/png");
- editIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ editIntent.setData(uri);
+ editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Create a edit action for the notification the same way.
PendingIntent editAction = PendingIntent.getBroadcast(context, 1,
@@ -902,6 +905,7 @@
Intent chooserIntent = Intent.createChooser(sharingIntent, null,
chooseAction.getIntentSender())
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+
ActivityOptions opts = ActivityOptions.makeBasic();
opts.setDisallowEnterPictureInPictureWhileLaunching(true);
context.startActivityAsUser(chooserIntent, opts.toBundle(), UserHandle.CURRENT);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 15e92f4..406eef8 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -81,7 +81,7 @@
private volatile boolean mIsVrModeEnabled;
private boolean mListening;
private boolean mExternalChange;
- private boolean mControlInitialized;
+ private boolean mControlValueInitialized;
private ValueAnimator mSliderAnimator;
@@ -337,6 +337,7 @@
mBackgroundHandler.post(mStopListeningRunnable);
mListening = false;
+ mControlValueInitialized = false;
}
@Override
@@ -428,10 +429,10 @@
}
private void animateSliderTo(int target) {
- if (!mControlInitialized) {
+ if (!mControlValueInitialized) {
// Don't animate the first value since it's default state isn't meaningful to users.
mControl.setValue(target);
- mControlInitialized = true;
+ mControlValueInitialized = true;
}
if (mSliderAnimator != null && mSliderAnimator.isStarted()) {
mSliderAnimator.cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 79e9f7b..f5f62b85 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -24,6 +24,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.RemoteException;
import android.support.annotation.VisibleForTesting;
import android.util.Pair;
@@ -90,6 +91,8 @@
private static final int MSG_FINGERPRINT_ERROR = 42 << MSG_SHIFT;
private static final int MSG_FINGERPRINT_HIDE = 43 << MSG_SHIFT;
private static final int MSG_SHOW_CHARGING_ANIMATION = 44 << MSG_SHIFT;
+ private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
+ private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -148,6 +151,8 @@
default void clickTile(ComponentName tile) { }
default void handleSystemKey(int arg1) { }
+ default void showPinningEnterExitToast(boolean entering) { }
+ default void showPinningEscapeToast() { }
default void handleShowGlobalActionsMenu() { }
default void handleShowShutdownUi(boolean isReboot, String reason) { }
@@ -453,6 +458,21 @@
}
@Override
+ public void showPinningEnterExitToast(boolean entering) {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_SHOW_PINNING_TOAST_ENTER_EXIT, entering).sendToTarget();
+ }
+ }
+
+ @Override
+ public void showPinningEscapeToast() {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_SHOW_PINNING_TOAST_ESCAPE).sendToTarget();
+ }
+ }
+
+
+ @Override
public void showGlobalActionsMenu() {
synchronized (mLock) {
mHandler.removeMessages(MSG_SHOW_GLOBAL_ACTIONS);
@@ -767,6 +787,16 @@
mCallbacks.get(i).showChargingAnimation(msg.arg1);
}
break;
+ case MSG_SHOW_PINNING_TOAST_ENTER_EXIT:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showPinningEnterExitToast(msg.arg1 != 0);
+ }
+ break;
+ case MSG_SHOW_PINNING_TOAST_ESCAPE:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showPinningEscapeToast();
+ }
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 1056ecc..b3f68d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1472,7 +1472,6 @@
return mPrivateLayout.getActiveRemoteInputText();
}
-
public void animateTranslateNotification(final float leftTarget) {
if (mTranslateAnim != null) {
mTranslateAnim.cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 8325df7..cad956c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -802,10 +802,6 @@
updateRelativeOffset();
}
- public void setDarkOffsetX(int offsetX) {
- mShelfIcons.setDarkOffsetX(offsetX);
- }
-
private class ShelfState extends ExpandableViewState {
private float openedAmount;
private boolean hasItemsInStableShelf;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 3ebeb4d..3dfb913 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -379,7 +379,7 @@
// Because space is usually constrained in the auto use-case, there should not be a
// pinned notification when the shade has been expanded. Ensure this by removing all heads-
// up notifications.
- mHeadsUpManager.removeAllHeadsUpEntries();
+ mHeadsUpManager.releaseAllImmediately();
super.animateExpandNotificationsPanel();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 8336d29..11d20b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.graphics.Matrix;
import android.graphics.Rect;
@@ -35,10 +36,11 @@
import com.android.systemui.Interpolators;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationListContainer;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowView;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import java.util.function.Consumer;
@@ -54,19 +56,25 @@
public static final long ANIMATION_DELAY_ICON_FADE_IN = ANIMATION_DURATION -
CollapsedStatusBarFragment.FADE_IN_DURATION - CollapsedStatusBarFragment.FADE_IN_DELAY
- 16;
+ private static final long LAUNCH_TIMEOUT = 500;
private final NotificationPanelView mNotificationPanel;
private final NotificationListContainer mNotificationContainer;
private final StatusBarWindowView mStatusBarWindow;
- private final Consumer<Boolean> mPanelCollapser;
+ private StatusBar mStatusBar;
+ private final Runnable mTimeoutRunnable = () -> {
+ setAnimationPending(false);
+ mStatusBar.collapsePanel(true /* animate */);
+ };
+ private boolean mAnimationPending;
public ActivityLaunchAnimator(StatusBarWindowView statusBarWindow,
- Consumer<Boolean> panelCollapser,
+ StatusBar statusBar,
NotificationPanelView notificationPanel,
NotificationListContainer container) {
mNotificationPanel = notificationPanel;
mNotificationContainer = container;
mStatusBarWindow = statusBarWindow;
- mPanelCollapser = panelCollapser;
+ mStatusBar = statusBar;
}
public ActivityOptions getLaunchAnimation(
@@ -76,6 +84,26 @@
new RemoteAnimationAdapter(animationRunner, 1000 /* Duration */, 0 /* delay */));
}
+ public boolean isAnimationPending() {
+ return mAnimationPending;
+ }
+
+ public void setLaunchResult(int launchResult) {
+ setAnimationPending((launchResult == ActivityManager.START_TASK_TO_FRONT
+ || launchResult == ActivityManager.START_SUCCESS)
+ && mStatusBar.getBarState() == StatusBarState.SHADE);
+ }
+
+ private void setAnimationPending(boolean pending) {
+ mAnimationPending = pending;
+ mStatusBarWindow.setExpandAnimationPending(pending);
+ if (pending) {
+ mStatusBarWindow.postDelayed(mTimeoutRunnable, LAUNCH_TIMEOUT);
+ } else {
+ mStatusBarWindow.removeCallbacks(mTimeoutRunnable);
+ }
+ }
+
class AnimationRunner extends IRemoteAnimationRunner.Stub {
private final ExpandableNotificationRow mSourceNotification;
@@ -94,7 +122,6 @@
IRemoteAnimationFinishedCallback iRemoteAnimationFinishedCallback)
throws RemoteException {
mSourceNotification.post(() -> {
- boolean first = true;
for (RemoteAnimationTarget app : remoteAnimationTargets) {
if (app.mode == RemoteAnimationTarget.MODE_OPENING) {
setExpandAnimationRunning(true);
@@ -139,7 +166,7 @@
public void onAnimationEnd(Animator animation) {
setExpandAnimationRunning(false);
if (mInstantCollapsePanel) {
- mPanelCollapser.accept(false /* animate */);
+ mStatusBar.collapsePanel(false /* animate */);
}
try {
iRemoteAnimationFinishedCallback.onAnimationFinished();
@@ -152,6 +179,7 @@
break;
}
}
+ setAnimationPending(false);
});
}
@@ -198,6 +226,10 @@
@Override
public void onAnimationCancelled() throws RemoteException {
+ mSourceNotification.post(() -> {
+ setAnimationPending(false);
+ mStatusBar.onLaunchAnimationCancelled();
+ });
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
index 3491f81..c214171 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RowInflaterTask.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.support.v4.view.AsyncLayoutInflater;
+import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -30,15 +31,23 @@
* An inflater task that asynchronously inflates a ExpandableNotificationRow
*/
public class RowInflaterTask implements InflationTask, AsyncLayoutInflater.OnInflateFinishedListener {
+
+ private static final String TAG = "RowInflaterTask";
+ private static final boolean TRACE_ORIGIN = true;
+
private RowInflationFinishedListener mListener;
private NotificationData.Entry mEntry;
private boolean mCancelled;
+ private Throwable mInflateOrigin;
/**
* Inflates a new notificationView. This should not be called twice on this object
*/
public void inflate(Context context, ViewGroup parent, NotificationData.Entry entry,
RowInflationFinishedListener listener) {
+ if (TRACE_ORIGIN) {
+ mInflateOrigin = new Throwable("inflate requested here");
+ }
mListener = listener;
AsyncLayoutInflater inflater = new AsyncLayoutInflater(context);
mEntry = entry;
@@ -54,8 +63,16 @@
@Override
public void onInflateFinished(View view, int resid, ViewGroup parent) {
if (!mCancelled) {
- mEntry.onInflationTaskFinished();
- mListener.onInflationFinished((ExpandableNotificationRow) view);
+ try {
+ mEntry.onInflationTaskFinished();
+ mListener.onInflationFinished((ExpandableNotificationRow) view);
+ } catch (Throwable t) {
+ if (mInflateOrigin != null) {
+ Log.e(TAG, "Error in inflation finished listener: " + t, mInflateOrigin);
+ t.addSuppressed(mInflateOrigin);
+ }
+ throw t;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 36f9f6b..b220686 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -14,16 +14,13 @@
package com.android.systemui.statusbar.phone;
+import android.app.AlarmManager.AlarmClockInfo;
import android.content.Context;
import android.os.Handler;
-import android.os.Looper;
import android.provider.Settings.Secure;
-
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ColorDisplayController;
import com.android.systemui.Dependency;
-import com.android.systemui.Prefs;
-import com.android.systemui.Prefs.Key;
import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.SecureSetting;
@@ -31,27 +28,37 @@
import com.android.systemui.statusbar.policy.DataSaverController.Listener;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController.Callback;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
/**
* Manages which tiles should be automatically added to QS.
*/
public class AutoTileManager {
-
public static final String HOTSPOT = "hotspot";
public static final String SAVER = "saver";
public static final String INVERSION = "inversion";
public static final String WORK = "work";
public static final String NIGHT = "night";
+ public static final String ALARM = "alarm";
+
private final Context mContext;
private final QSTileHost mHost;
private final Handler mHandler;
private final AutoAddTracker mAutoTracker;
public AutoTileManager(Context context, QSTileHost host) {
- mAutoTracker = new AutoAddTracker(context);
+ this(context, new AutoAddTracker(context), host,
+ new Handler(Dependency.get(Dependency.BG_LOOPER)));
+ }
+
+ @VisibleForTesting
+ AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host,
+ Handler handler) {
+ mAutoTracker = autoAddTracker;
mContext = context;
mHost = host;
- mHandler = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER));
+ mHandler = handler;
if (!mAutoTracker.isAdded(HOTSPOT)) {
Dependency.get(HotspotController.class).addCallback(mHotspotCallback);
}
@@ -76,20 +83,25 @@
if (!mAutoTracker.isAdded(WORK)) {
Dependency.get(ManagedProfileController.class).addCallback(mProfileCallback);
}
-
if (!mAutoTracker.isAdded(NIGHT)
- && ColorDisplayController.isAvailable(mContext)) {
+ && ColorDisplayController.isAvailable(mContext)) {
Dependency.get(ColorDisplayController.class).setListener(mColorDisplayCallback);
}
+ if (!mAutoTracker.isAdded(ALARM)) {
+ Dependency.get(NextAlarmController.class).addCallback(mNextAlarmChangeCallback);
+ }
}
public void destroy() {
- mColorsSetting.setListening(false);
+ if (mColorsSetting != null) {
+ mColorsSetting.setListening(false);
+ }
mAutoTracker.destroy();
Dependency.get(HotspotController.class).removeCallback(mHotspotCallback);
Dependency.get(DataSaverController.class).removeCallback(mDataSaverListener);
Dependency.get(ManagedProfileController.class).removeCallback(mProfileCallback);
Dependency.get(ColorDisplayController.class).setListener(null);
+ Dependency.get(NextAlarmController.class).removeCallback(mNextAlarmChangeCallback);
}
private final ManagedProfileController.Callback mProfileCallback =
@@ -138,6 +150,19 @@
}
};
+ private final NextAlarmChangeCallback mNextAlarmChangeCallback = new NextAlarmChangeCallback() {
+ @Override
+ public void onNextAlarmChanged(AlarmClockInfo nextAlarm) {
+ if (mAutoTracker.isAdded(ALARM)) return;
+ if (nextAlarm != null) {
+ mHost.addTile(ALARM);
+ mAutoTracker.setTileAdded(ALARM);
+ mHandler.post(() -> Dependency.get(NextAlarmController.class)
+ .removeCallback(mNextAlarmChangeCallback));
+ }
+ }
+ };
+
@VisibleForTesting
final ColorDisplayController.Callback mColorDisplayCallback =
new ColorDisplayController.Callback() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
new file mode 100644
index 0000000..c45c538
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -0,0 +1,455 @@
+/*
+ * 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.phone;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v4.util.ArraySet;
+import android.util.Log;
+import android.util.Pools;
+import android.view.View;
+import android.view.ViewTreeObserver;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dumpable;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Stack;
+
+/**
+ * A implementation of HeadsUpManager for phone and car.
+ */
+public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
+ ViewTreeObserver.OnComputeInternalInsetsListener, VisualStabilityManager.Callback,
+ OnHeadsUpChangedListener {
+ private static final String TAG = "HeadsUpManagerPhone";
+ private static final boolean DEBUG = false;
+
+ private final View mStatusBarWindowView;
+ private final int mStatusBarHeight;
+ private final NotificationGroupManager mGroupManager;
+ private final StatusBar mBar;
+ private final VisualStabilityManager mVisualStabilityManager;
+
+ private boolean mReleaseOnExpandFinish;
+ private boolean mTrackingHeadsUp;
+ private HashSet<String> mSwipedOutKeys = new HashSet<>();
+ private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>();
+ private ArraySet<NotificationData.Entry> mEntriesToRemoveWhenReorderingAllowed
+ = new ArraySet<>();
+ private boolean mIsExpanded;
+ private int[] mTmpTwoArray = new int[2];
+ private boolean mHeadsUpGoingAway;
+ private boolean mWaitingOnCollapseWhenGoingAway;
+ private boolean mIsObserving;
+ private int mStatusBarState;
+
+ private final Pools.Pool<HeadsUpEntryPhone> mEntryPool = new Pools.Pool<HeadsUpEntryPhone>() {
+ private Stack<HeadsUpEntryPhone> mPoolObjects = new Stack<>();
+
+ @Override
+ public HeadsUpEntryPhone acquire() {
+ if (!mPoolObjects.isEmpty()) {
+ return mPoolObjects.pop();
+ }
+ return new HeadsUpEntryPhone();
+ }
+
+ @Override
+ public boolean release(@NonNull HeadsUpEntryPhone instance) {
+ instance.reset();
+ mPoolObjects.push(instance);
+ return true;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // Constructor:
+
+ public HeadsUpManagerPhone(@NonNull final Context context, @NonNull View statusBarWindowView,
+ @NonNull NotificationGroupManager groupManager, @NonNull StatusBar bar,
+ @NonNull VisualStabilityManager visualStabilityManager) {
+ super(context);
+
+ mStatusBarWindowView = statusBarWindowView;
+ mGroupManager = groupManager;
+ mBar = bar;
+ mVisualStabilityManager = visualStabilityManager;
+
+ Resources resources = mContext.getResources();
+ mStatusBarHeight = resources.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+
+ addListener(new OnHeadsUpChangedListener() {
+ @Override
+ public void onHeadsUpPinnedModeChanged(boolean hasPinnedNotification) {
+ if (DEBUG) Log.w(TAG, "onHeadsUpPinnedModeChanged");
+ updateTouchableRegionListener();
+ }
+ });
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // Public methods:
+
+ /**
+ * Decides whether a click is invalid for a notification, i.e it has not been shown long enough
+ * that a user might have consciously clicked on it.
+ *
+ * @param key the key of the touched notification
+ * @return whether the touch is invalid and should be discarded
+ */
+ public boolean shouldSwallowClick(@NonNull String key) {
+ HeadsUpManager.HeadsUpEntry entry = getHeadsUpEntry(key);
+ if (entry != null && mClock.currentTimeMillis() < entry.postTime) {
+ return true;
+ }
+ return false;
+ }
+
+ public void onExpandingFinished() {
+ if (mReleaseOnExpandFinish) {
+ releaseAllImmediately();
+ mReleaseOnExpandFinish = false;
+ } else {
+ for (NotificationData.Entry entry : mEntriesToRemoveAfterExpand) {
+ if (isHeadsUp(entry.key)) {
+ // Maybe the heads-up was removed already
+ removeHeadsUpEntry(entry);
+ }
+ }
+ }
+ mEntriesToRemoveAfterExpand.clear();
+ }
+
+ /**
+ * Sets the tracking-heads-up flag. If the flag is true, HeadsUpManager doesn't remove the entry
+ * from the list even after a Heads Up Notification is gone.
+ */
+ public void setTrackingHeadsUp(boolean trackingHeadsUp) {
+ mTrackingHeadsUp = trackingHeadsUp;
+ }
+
+ /**
+ * Notify that the status bar panel gets expanded or collapsed.
+ *
+ * @param isExpanded True to notify expanded, false to notify collapsed.
+ */
+ public void setIsPanelExpanded(boolean isExpanded) {
+ if (isExpanded != mIsExpanded) {
+ mIsExpanded = isExpanded;
+ if (isExpanded) {
+ // make sure our state is sane
+ mWaitingOnCollapseWhenGoingAway = false;
+ mHeadsUpGoingAway = false;
+ updateTouchableRegionListener();
+ }
+ }
+ }
+
+ /**
+ * Set the current state of the statusbar.
+ */
+ public void setStatusBarState(int statusBarState) {
+ mStatusBarState = statusBarState;
+ }
+
+ /**
+ * Set that we are exiting the headsUp pinned mode, but some notifications might still be
+ * animating out. This is used to keep the touchable regions in a sane state.
+ */
+ public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
+ if (headsUpGoingAway != mHeadsUpGoingAway) {
+ mHeadsUpGoingAway = headsUpGoingAway;
+ if (!headsUpGoingAway) {
+ waitForStatusBarLayout();
+ }
+ updateTouchableRegionListener();
+ }
+ }
+
+ /**
+ * Notifies that a remote input textbox in notification gets active or inactive.
+ * @param entry The entry of the target notification.
+ * @param remoteInputActive True to notify active, False to notify inactive.
+ */
+ public void setRemoteInputActive(
+ @NonNull NotificationData.Entry entry, boolean remoteInputActive) {
+ HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(entry.key);
+ if (headsUpEntry != null && headsUpEntry.remoteInputActive != remoteInputActive) {
+ headsUpEntry.remoteInputActive = remoteInputActive;
+ if (remoteInputActive) {
+ headsUpEntry.removeAutoRemovalCallbacks();
+ } else {
+ headsUpEntry.updateEntry(false /* updatePostTime */);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ public void removeMinimumDisplayTimeForTesting() {
+ mMinimumDisplayTime = 1;
+ mHeadsUpNotificationDecay = 1;
+ mTouchAcceptanceDelay = 1;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // HeadsUpManager public methods overrides:
+
+ @Override
+ public boolean isTrackingHeadsUp() {
+ return mTrackingHeadsUp;
+ }
+
+ @Override
+ public void snooze() {
+ super.snooze();
+ mReleaseOnExpandFinish = true;
+ }
+
+ /**
+ * React to the removal of the notification in the heads up.
+ *
+ * @return true if the notification was removed and false if it still needs to be kept around
+ * for a bit since it wasn't shown long enough
+ */
+ @Override
+ public boolean removeNotification(@NonNull String key, boolean ignoreEarliestRemovalTime) {
+ if (wasShownLongEnough(key) || ignoreEarliestRemovalTime) {
+ return super.removeNotification(key, ignoreEarliestRemovalTime);
+ } else {
+ HeadsUpEntryPhone entry = getHeadsUpEntryPhone(key);
+ entry.removeAsSoonAsPossible();
+ return false;
+ }
+ }
+
+ public void addSwipedOutNotification(@NonNull String key) {
+ mSwipedOutKeys.add(key);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // Dumpable overrides:
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("HeadsUpManagerPhone state:");
+ dumpInternal(fd, pw, args);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // ViewTreeObserver.OnComputeInternalInsetsListener overrides:
+
+ /**
+ * Overridden from TreeObserver.
+ */
+ @Override
+ public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
+ if (mIsExpanded || mBar.isBouncerShowing()) {
+ // The touchable region is always the full area when expanded
+ return;
+ }
+ if (hasPinnedHeadsUp()) {
+ ExpandableNotificationRow topEntry = getTopEntry().row;
+ if (topEntry.isChildInGroup()) {
+ final ExpandableNotificationRow groupSummary
+ = mGroupManager.getGroupSummary(topEntry.getStatusBarNotification());
+ if (groupSummary != null) {
+ topEntry = groupSummary;
+ }
+ }
+ topEntry.getLocationOnScreen(mTmpTwoArray);
+ int minX = mTmpTwoArray[0];
+ int maxX = mTmpTwoArray[0] + topEntry.getWidth();
+ int maxY = topEntry.getIntrinsicHeight();
+
+ info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+ info.touchableRegion.set(minX, 0, maxX, maxY);
+ } else if (mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway) {
+ info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+ info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // VisualStabilityManager.Callback overrides:
+
+ @Override
+ public void onReorderingAllowed() {
+ mBar.getNotificationScrollLayout().setHeadsUpGoingAwayAnimationsAllowed(false);
+ for (NotificationData.Entry entry : mEntriesToRemoveWhenReorderingAllowed) {
+ if (isHeadsUp(entry.key)) {
+ // Maybe the heads-up was removed already
+ removeHeadsUpEntry(entry);
+ }
+ }
+ mEntriesToRemoveWhenReorderingAllowed.clear();
+ mBar.getNotificationScrollLayout().setHeadsUpGoingAwayAnimationsAllowed(true);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // HeadsUpManager utility (protected) methods overrides:
+
+ @Override
+ protected HeadsUpEntry createHeadsUpEntry() {
+ return mEntryPool.acquire();
+ }
+
+ @Override
+ protected void releaseHeadsUpEntry(HeadsUpEntry entry) {
+ mEntryPool.release((HeadsUpEntryPhone) entry);
+ }
+
+ @Override
+ protected boolean shouldHeadsUpBecomePinned(NotificationData.Entry entry) {
+ return mStatusBarState != StatusBarState.KEYGUARD && !mIsExpanded
+ || super.shouldHeadsUpBecomePinned(entry);
+ }
+
+ @Override
+ protected void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
+ super.dumpInternal(fd, pw, args);
+ pw.print(" mStatusBarState="); pw.println(mStatusBarState);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // Protected utility methods:
+
+ @Nullable
+ protected HeadsUpEntryPhone getHeadsUpEntryPhone(@NonNull String key) {
+ return (HeadsUpEntryPhone) getHeadsUpEntry(key);
+ }
+
+ @Nullable
+ protected HeadsUpEntryPhone getTopHeadsUpEntryPhone() {
+ return (HeadsUpEntryPhone) getTopHeadsUpEntry();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // Private utility methods:
+
+ private boolean wasShownLongEnough(@NonNull String key) {
+ if (mSwipedOutKeys.contains(key)) {
+ // We always instantly dismiss views being manually swiped out.
+ mSwipedOutKeys.remove(key);
+ return true;
+ }
+
+ HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(key);
+ HeadsUpEntryPhone topEntry = getTopHeadsUpEntryPhone();
+ if (headsUpEntry != topEntry) {
+ return true;
+ }
+ return headsUpEntry.wasShownLongEnough();
+ }
+
+ /**
+ * We need to wait on the whole panel to collapse, before we can remove the touchable region
+ * listener.
+ */
+ private void waitForStatusBarLayout() {
+ mWaitingOnCollapseWhenGoingAway = true;
+ mStatusBarWindowView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ if (mStatusBarWindowView.getHeight() <= mStatusBarHeight) {
+ mStatusBarWindowView.removeOnLayoutChangeListener(this);
+ mWaitingOnCollapseWhenGoingAway = false;
+ updateTouchableRegionListener();
+ }
+ }
+ });
+ }
+
+ private void updateTouchableRegionListener() {
+ boolean shouldObserve = hasPinnedHeadsUp() || mHeadsUpGoingAway
+ || mWaitingOnCollapseWhenGoingAway;
+ if (shouldObserve == mIsObserving) {
+ return;
+ }
+ if (shouldObserve) {
+ mStatusBarWindowView.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
+ mStatusBarWindowView.requestLayout();
+ } else {
+ mStatusBarWindowView.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
+ }
+ mIsObserving = shouldObserve;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // HeadsUpEntryPhone:
+
+ protected class HeadsUpEntryPhone extends HeadsUpManager.HeadsUpEntry {
+ public void setEntry(@NonNull final NotificationData.Entry entry) {
+ Runnable removeHeadsUpRunnable = () -> {
+ if (!mVisualStabilityManager.isReorderingAllowed()) {
+ mEntriesToRemoveWhenReorderingAllowed.add(entry);
+ mVisualStabilityManager.addReorderingAllowedCallback(
+ HeadsUpManagerPhone.this);
+ } else if (!mTrackingHeadsUp) {
+ removeHeadsUpEntry(entry);
+ } else {
+ mEntriesToRemoveAfterExpand.add(entry);
+ }
+ };
+
+ super.setEntry(entry, removeHeadsUpRunnable);
+ }
+
+ public boolean wasShownLongEnough() {
+ return earliestRemovaltime < mClock.currentTimeMillis();
+ }
+
+ @Override
+ public void updateEntry(boolean updatePostTime) {
+ super.updateEntry(updatePostTime);
+
+ if (mEntriesToRemoveAfterExpand.contains(entry)) {
+ mEntriesToRemoveAfterExpand.remove(entry);
+ }
+ if (mEntriesToRemoveWhenReorderingAllowed.contains(entry)) {
+ mEntriesToRemoveWhenReorderingAllowed.remove(entry);
+ }
+ }
+
+ @Override
+ public void expanded(boolean expanded) {
+ if (this.expanded == expanded) {
+ return;
+ }
+
+ this.expanded = expanded;
+ if (expanded) {
+ removeAutoRemovalCallbacks();
+ } else {
+ updateEntry(false /* updatePostTime */);
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index c85571c..2bfdefe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -23,7 +23,7 @@
import com.android.systemui.Gefingerpoken;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
/**
@@ -31,7 +31,7 @@
*/
public class HeadsUpTouchHelper implements Gefingerpoken {
- private HeadsUpManager mHeadsUpManager;
+ private HeadsUpManagerPhone mHeadsUpManager;
private NotificationStackScrollLayout mStackScroller;
private int mTrackingPointer;
private float mTouchSlop;
@@ -43,7 +43,7 @@
private NotificationPanelView mPanel;
private ExpandableNotificationRow mPickedChild;
- public HeadsUpTouchHelper(HeadsUpManager headsUpManager,
+ public HeadsUpTouchHelper(HeadsUpManagerPhone headsUpManager,
NotificationStackScrollLayout stackScroller,
NotificationPanelView notificationPanelView) {
mHeadsUpManager = headsUpManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index da809c1..09acf3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -115,7 +115,7 @@
lp = (MarginLayoutParams) mSystemIconsSuperContainer.getLayoutParams();
lp.height = getResources().getDimensionPixelSize(
- R.dimen.status_bar_header_height);
+ com.android.internal.R.dimen.quick_qs_total_height);
lp.setMarginStart(getResources().getDimensionPixelSize(
R.dimen.system_icons_super_container_margin_start));
mSystemIconsSuperContainer.setLayoutParams(lp);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 5401e74..242be71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -22,11 +22,13 @@
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions;
+import static com.android.systemui.OverviewProxyService.OverviewProxyListener;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.annotation.IdRes;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -69,6 +71,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
+import android.widget.Button;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -153,6 +156,18 @@
private Animator mRotateShowAnimator;
private Animator mRotateHideAnimator;
+ private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
+ @Override
+ public void onConnectionChanged(boolean isConnected) {
+ mNavigationBarView.onOverviewProxyConnectionChanged(isConnected);
+ updateScreenPinningGestures();
+ }
+
+ @Override
+ public void onRecentsAnimationStarted() {
+ mNavigationBarView.setRecentsAnimationStarted(true);
+ }
+ };
// ----- Fragment Lifecycle Callbacks -----
@@ -239,12 +254,14 @@
filter.addAction(Intent.ACTION_SCREEN_ON);
getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
notifyNavigationBarScreenOn();
+ mOverviewProxyService.addCallback(mOverviewProxyListener);
}
@Override
public void onDestroyView() {
super.onDestroyView();
mNavigationBarView.getLightTransitionsController().destroy(getContext());
+ mOverviewProxyService.removeCallback(mOverviewProxyListener);
getContext().unregisterReceiver(mBroadcastReceiver);
}
@@ -409,7 +426,7 @@
if (visible) { // Appear and change
rotBtn.setVisibility(View.VISIBLE);
- mNavigationBarView.notifyAccessibilitySubtreeChanged();
+ mNavigationBarView.notifySubtreeAccessibilityStateChangedIfNeeded();
if (skipAnim) {
currentView.setAlpha(1f);
@@ -437,7 +454,7 @@
if (skipAnim) {
rotBtn.setVisibility(View.INVISIBLE);
- mNavigationBarView.notifyAccessibilitySubtreeChanged();
+ mNavigationBarView.notifySubtreeAccessibilityStateChangedIfNeeded();
return;
}
@@ -454,7 +471,7 @@
@Override
public void onAnimationEnd(Animator animation) {
rotBtn.setVisibility(View.INVISIBLE);
- mNavigationBarView.notifyAccessibilitySubtreeChanged();
+ mNavigationBarView.notifySubtreeAccessibilityStateChangedIfNeeded();
}
});
@@ -514,6 +531,7 @@
if (masked != mDisabledFlags1) {
mDisabledFlags1 = masked;
if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state1);
+ updateScreenPinningGestures();
}
}
@@ -528,7 +546,7 @@
private boolean shouldDisableNavbarGestures() {
return !mStatusBar.isDeviceProvisioned()
|| (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0
- || mOverviewProxyService.getProxy() != null;
+ || mNavigationBarView.getRecentsButton().getVisibility() != View.VISIBLE;
}
private void repositionNavigationBar() {
@@ -540,6 +558,24 @@
((View) mNavigationBarView.getParent()).getLayoutParams());
}
+ private void updateScreenPinningGestures() {
+ if (mNavigationBarView == null) {
+ return;
+ }
+
+ // Change the cancel pin gesture to home and back if recents button is invisible
+ boolean recentsVisible = mNavigationBarView.isRecentsButtonVisible();
+ ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
+ ButtonDispatcher backButton = mNavigationBarView.getBackButton();
+ if (recentsVisible) {
+ homeButton.setOnLongClickListener(this::onHomeLongClick);
+ backButton.setOnLongClickListener(this::onLongPressBackRecents);
+ } else {
+ homeButton.setOnLongClickListener(this::onLongPressBackHome);
+ backButton.setOnLongClickListener(this::onLongPressBackHome);
+ }
+ }
+
private void notifyNavigationBarScreenOn() {
mNavigationBarView.notifyScreenOn();
}
@@ -649,20 +685,29 @@
mCommandQueue.toggleRecentApps();
}
+ private boolean onLongPressBackHome(View v) {
+ return onLongPressNavigationButtons(v, R.id.back, R.id.home);
+ }
+
+ private boolean onLongPressBackRecents(View v) {
+ return onLongPressNavigationButtons(v, R.id.back, R.id.recent_apps);
+ }
+
/**
- * This handles long-press of both back and recents. They are
- * handled together to capture them both being long-pressed
+ * This handles long-press of both back and recents/home. Back is the common button with
+ * combination of recents if it is visible or home if recents is invisible.
+ * They are handled together to capture them both being long-pressed
* at the same time to exit screen pinning (lock task).
*
- * When accessibility mode is on, only a long-press from recents
+ * When accessibility mode is on, only a long-press from recents/home
* is required to exit.
*
* In all other circumstances we try to pass through long-press events
* for Back, so that apps can still use it. Which can be from two things.
* 1) Not currently in screen pinning (lock task).
- * 2) Back is long-pressed without recents.
+ * 2) Back is long-pressed without recents/home.
*/
- private boolean onLongPressBackRecents(View v) {
+ private boolean onLongPressNavigationButtons(View v, @IdRes int btnId1, @IdRes int btnId2) {
try {
boolean sendBackLongPress = false;
IActivityManager activityManager = ActivityManagerNative.getDefault();
@@ -670,6 +715,7 @@
boolean inLockTaskMode = activityManager.isInLockTaskMode();
if (inLockTaskMode && !touchExplorationEnabled) {
long time = System.currentTimeMillis();
+
// If we recently long-pressed the other button then they were
// long-pressed 'together'
if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) {
@@ -677,26 +723,32 @@
// When exiting refresh disabled flags.
mNavigationBarView.setDisabledFlags(mDisabledFlags1, true);
return true;
- } else if ((v.getId() == R.id.back)
- && !mNavigationBarView.getRecentsButton().getCurrentView().isPressed()) {
- // If we aren't pressing recents right now then they presses
- // won't be together, so send the standard long-press action.
- sendBackLongPress = true;
+ } else if (v.getId() == btnId1) {
+ ButtonDispatcher button = btnId2 == R.id.recent_apps
+ ? mNavigationBarView.getRecentsButton()
+ : mNavigationBarView.getHomeButton();
+ if (!button.getCurrentView().isPressed()) {
+ // If we aren't pressing recents/home right now then they presses
+ // won't be together, so send the standard long-press action.
+ sendBackLongPress = true;
+ }
}
mLastLockToAppLongPress = time;
} else {
// If this is back still need to handle sending the long-press event.
- if (v.getId() == R.id.back) {
+ if (v.getId() == btnId1) {
sendBackLongPress = true;
} else if (touchExplorationEnabled && inLockTaskMode) {
- // When in accessibility mode a long press that is recents (not back)
+ // When in accessibility mode a long press that is recents/home (not back)
// should stop lock task.
activityManager.stopSystemLockTaskMode();
// When exiting refresh disabled flags.
mNavigationBarView.setDisabledFlags(mDisabledFlags1, true);
return true;
- } else if (v.getId() == R.id.recent_apps) {
- return onLongPressRecents();
+ } else if (v.getId() == btnId2) {
+ return btnId2 == R.id.recent_apps
+ ? onLongPressRecents()
+ : onHomeLongClick(mNavigationBarView.getHomeButton().getCurrentView());
}
}
if (sendBackLongPress) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index 0954fd0..0d36efd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -308,8 +308,13 @@
}
public boolean onTouchEvent(MotionEvent event) {
+ // The same down event was just sent on intercept and therefore can be ignored here
+ boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
+ && mOverviewEventSender.getProxy() != null;
boolean result = mStatusBar.isPresenterFullyCollapsed()
- && (mQuickScrubController.onTouchEvent(event) || proxyMotionEvents(event));
+ && (mQuickScrubController.onTouchEvent(event)
+ || ignoreProxyDownEvent
+ || proxyMotionEvents(event));
if (mDockWindowEnabled) {
result |= handleDockWindowEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index b8b309b..9d20e4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -220,6 +220,11 @@
newLayout = getDefaultLayout();
}
String[] sets = newLayout.split(GRAVITY_SEPARATOR, 3);
+ if (sets.length != 3) {
+ Log.d(TAG, "Invalid layout.");
+ newLayout = getDefaultLayout();
+ sets = newLayout.split(GRAVITY_SEPARATOR, 3);
+ }
String[] start = sets[0].split(BUTTON_SEPARATOR);
String[] center = sets[1].split(BUTTON_SEPARATOR);
String[] end = sets[2].split(BUTTON_SEPARATOR);
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 9f4d35e..cd220a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -104,6 +104,7 @@
private DeadZone mDeadZone;
private final NavigationBarTransitions mBarTransitions;
private final OverviewProxyService mOverviewProxyService;
+ private boolean mRecentsAnimationStarted;
// workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
final static boolean WORKAROUND_INVALID_LAYOUT = true;
@@ -206,12 +207,6 @@
}
}
- private final OverviewProxyListener mOverviewProxyListener = isConnected -> {
- updateSlippery();
- setDisabledFlags(mDisabledFlags, true);
- setUpSwipeUpOnboarding(isConnected);
- };
-
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -268,17 +263,44 @@
notifyVerticalChangedListener(mVertical);
}
+ public void setRecentsAnimationStarted(boolean started) {
+ mRecentsAnimationStarted = started;
+ if (mSwipeUpOnboarding != null) {
+ mSwipeUpOnboarding.onRecentsAnimationStarted();
+ }
+ }
+
+ public void onConnectionChanged(boolean isConnected) {
+ updateSlippery();
+ setDisabledFlags(mDisabledFlags, true);
+ setUpSwipeUpOnboarding(isConnected);
+ }
+
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mGestureHelper.onTouchEvent(event)) {
return true;
}
- return super.onTouchEvent(event);
+ return mRecentsAnimationStarted || super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
- return mGestureHelper.onInterceptTouchEvent(event);
+ int action = event.getActionMasked();
+ if (action == MotionEvent.ACTION_DOWN) {
+ mRecentsAnimationStarted = false;
+ } else if (action == MotionEvent.ACTION_UP) {
+ // If the overview proxy service has not started the recents animation then clean up
+ // after it to ensure that the nav bar buttons still work
+ if (mOverviewProxyService.getProxy() != null && !mRecentsAnimationStarted) {
+ try {
+ ActivityManager.getService().cancelRecentsAnimation();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not cancel recents animation");
+ }
+ }
+ }
+ return mRecentsAnimationStarted || mGestureHelper.onInterceptTouchEvent(event);
}
public void abortCurrentGesture() {
@@ -327,6 +349,10 @@
return mButtonDispatchers;
}
+ public boolean isRecentsButtonVisible() {
+ return getRecentsButton().getVisibility() == View.VISIBLE;
+ }
+
private void updateCarModeIcons(Context ctx) {
mBackCarModeIcon = getDrawable(ctx,
R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
@@ -587,6 +613,9 @@
final ViewGroup navbarView = ((ViewGroup) getParent());
final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView
.getLayoutParams();
+ if (lp == null) {
+ return;
+ }
if (slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) == 0) {
lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
changed = true;
@@ -650,6 +679,12 @@
}
}
+ public void onOverviewProxyConnectionChanged(boolean isConnected) {
+ setSlippery(!isConnected);
+ setDisabledFlags(mDisabledFlags, true);
+ setUpSwipeUpOnboarding(isConnected);
+ }
+
@Override
protected void onDraw(Canvas canvas) {
mGestureHelper.onDraw(canvas);
@@ -847,7 +882,6 @@
onPluginDisconnected(null); // Create default gesture helper
Dependency.get(PluginManager.class).addPluginListener(this,
NavGesture.class, false /* Only one */);
- mOverviewProxyService.addCallback(mOverviewProxyListener);
setUpSwipeUpOnboarding(mOverviewProxyService.getProxy() != null);
}
@@ -858,13 +892,12 @@
if (mGestureHelper != null) {
mGestureHelper.destroy();
}
- mOverviewProxyService.removeCallback(mOverviewProxyListener);
setUpSwipeUpOnboarding(false);
}
private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
if (connectedToOverviewProxy) {
- mSwipeUpOnboarding.onConnectedToLauncher(mOverviewProxyService.getLauncherComponent());
+ mSwipeUpOnboarding.onConnectedToLauncher();
} else {
mSwipeUpOnboarding.onDisconnectedFromLauncher();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 91cae0a..5cf4c4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -120,7 +120,6 @@
private boolean mDisallowNextAnimation;
private boolean mAnimationsEnabled = true;
private ArrayMap<String, ArrayList<StatusBarIcon>> mReplacingIcons;
- private int mDarkOffsetX;
// Keep track of the last visible icon so collapsed container can report on its location
private IconState mLastVisibleIconState;
@@ -378,14 +377,6 @@
iconState.xTranslation = getWidth() - iconState.xTranslation - view.getWidth();
}
}
-
- if (mDark && mDarkOffsetX != 0) {
- for (int i = 0; i < childCount; i++) {
- View view = getChildAt(i);
- IconState iconState = mIconStates.get(view);
- iconState.xTranslation += mDarkOffsetX;
- }
- }
}
private float getLayoutEnd() {
@@ -534,10 +525,6 @@
mAnimationsEnabled = enabled;
}
- public void setDarkOffsetX(int offsetX) {
- mDarkOffsetX = offsetX;
- }
-
public void setReplacingIcons(ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons) {
mReplacingIcons = replacingIcons;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 31b8159..52d005c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -47,6 +47,7 @@
import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.keyguard.KeyguardStatusView;
@@ -67,14 +68,11 @@
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackStateAnimator;
-import java.util.Collection;
import java.util.List;
public class NotificationPanelView extends PanelView implements
@@ -482,7 +480,7 @@
mTopPaddingAdjustment = mClockPositionResult.stackScrollerPaddingAdjustment;
}
mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
- mNotificationStackScroller.setDarkShelfOffsetX(mClockPositionResult.clockX);
+ mNotificationStackScroller.setAntiBurnInOffsetX(mClockPositionResult.clockX);
mKeyguardBottomArea.setBurnInXOffset(mClockPositionResult.clockX);
requestScrollerTopPaddingUpdate(animate);
}
@@ -1571,7 +1569,7 @@
private void updatePanelExpanded() {
boolean isExpanded = !isFullyCollapsed();
if (mPanelExpanded != isExpanded) {
- mHeadsUpManager.setIsExpanded(isExpanded);
+ mHeadsUpManager.setIsPanelExpanded(isExpanded);
mStatusBar.setPanelExpanded(isExpanded);
mPanelExpanded = isExpanded;
}
@@ -2338,7 +2336,7 @@
}
@Override
- public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+ public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
super.setHeadsUpManager(headsUpManager);
mHeadsUpTouchHelper = new HeadsUpTouchHelper(headsUpManager, mNotificationStackScroller,
this);
@@ -2630,8 +2628,8 @@
}
}
- public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
- mKeyguardStatusView.setPulsing(pulsing != null);
+ public void setPulsing(boolean pulsing) {
+ mKeyguardStatusView.setPulsing(pulsing);
positionClockAndNotifications();
mNotificationStackScroller.setPulsing(pulsing, mKeyguardStatusView.getLocationOnScreen()[1]
+ mKeyguardStatusView.getClockBottom());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index a62a424..6daabed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -50,7 +50,7 @@
import com.android.systemui.doze.DozeLog;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -75,7 +75,7 @@
}
protected StatusBar mStatusBar;
- protected HeadsUpManager mHeadsUpManager;
+ protected HeadsUpManagerPhone mHeadsUpManager;
private float mPeekHeight;
private float mHintDistance;
@@ -950,7 +950,7 @@
}
public boolean isCollapsing() {
- return mClosing;
+ return mClosing || mLaunchingNotification;
}
public boolean isTracking() {
@@ -1252,7 +1252,7 @@
*/
protected abstract int getClearAllHeight();
- public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+ public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
mHeadsUpManager = headsUpManager;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 20b5018..6444cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -407,17 +407,17 @@
int iconId = R.drawable.stat_sys_data_bluetooth;
String contentDescription =
mContext.getString(R.string.accessibility_quick_settings_bluetooth_on);
- boolean bluetoothEnabled = false;
+ boolean bluetoothVisible = false;
if (mBluetooth != null) {
- bluetoothEnabled = mBluetooth.isBluetoothEnabled();
if (mBluetooth.isBluetoothConnected()) {
iconId = R.drawable.stat_sys_data_bluetooth_connected;
contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
+ bluetoothVisible = mBluetooth.isBluetoothEnabled();
}
}
mIconController.setIcon(mSlotBluetooth, iconId, contentDescription);
- mIconController.setIconVisibility(mSlotBluetooth, bluetoothEnabled);
+ mIconController.setIconVisibility(mSlotBluetooth, bluetoothVisible);
}
private final void updateTTY() {
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
similarity index 70%
rename from services/core/java/com/android/server/am/LockTaskNotify.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
index 1dcb0ad..0d07ad9 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.am;
+package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.os.SystemClock;
@@ -22,36 +22,37 @@
import android.view.WindowManager;
import android.widget.Toast;
-import com.android.internal.R;
+import com.android.systemui.R;
+import com.android.systemui.SysUIToast;
/**
* Helper to manage showing/hiding a image to notify them that they are entering or exiting screen
* pinning mode. All exposed methods should be called from a handler thread.
*/
-public class LockTaskNotify {
- private static final String TAG = "LockTaskNotify";
+public class ScreenPinningNotify {
+ private static final String TAG = "ScreenPinningNotify";
private static final long SHOW_TOAST_MINIMUM_INTERVAL = 1000;
private final Context mContext;
private Toast mLastToast;
private long mLastShowToastTime;
- public LockTaskNotify(Context context) {
+ public ScreenPinningNotify(Context context) {
mContext = context;
}
/** Show "Screen pinned" toast. */
void showPinningStartToast() {
- makeAllUserToastAndShow(R.string.lock_to_app_start);
+ makeAllUserToastAndShow(R.string.screen_pinning_start);
}
/** Show "Screen unpinned" toast. */
void showPinningExitToast() {
- makeAllUserToastAndShow(R.string.lock_to_app_exit);
+ makeAllUserToastAndShow(R.string.screen_pinning_exit);
}
/** Show a toast that describes the gesture the user should use to escape pinned mode. */
- void showEscapeToast() {
+ void showEscapeToast(boolean isRecentsButtonVisible) {
long showToastTime = SystemClock.elapsedRealtime();
if ((showToastTime - mLastShowToastTime) < SHOW_TOAST_MINIMUM_INTERVAL) {
Slog.i(TAG, "Ignore toast since it is requested in very short interval.");
@@ -60,14 +61,14 @@
if (mLastToast != null) {
mLastToast.cancel();
}
- mLastToast = makeAllUserToastAndShow(R.string.lock_to_app_toast);
+ mLastToast = makeAllUserToastAndShow(isRecentsButtonVisible
+ ? R.string.screen_pinning_toast
+ : R.string.screen_pinning_toast_recents_invisible);
mLastShowToastTime = showToastTime;
}
private Toast makeAllUserToastAndShow(int resId) {
- Toast toast = Toast.makeText(mContext, resId, Toast.LENGTH_LONG);
- toast.getWindowParams().privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ Toast toast = SysUIToast.makeText(mContext, resId, Toast.LENGTH_LONG);
toast.show();
return toast;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 7d84550..3777a6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -100,7 +100,6 @@
import android.service.notification.StatusBarNotification;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
-import android.text.SpannedString;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -209,6 +208,7 @@
import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -220,6 +220,7 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
@@ -405,6 +406,13 @@
protected NotificationEntryManager mEntryManager;
protected NotificationViewHierarchyManager mViewHierarchyManager;
+ /**
+ * Helper that is responsible for showing the right toast when a disallowed activity operation
+ * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
+ * fully locked mode we only show that unlocking is blocked.
+ */
+ private ScreenPinningNotify mScreenPinningNotify;
+
// for disabling the status bar
private int mDisabled1 = 0;
private int mDisabled2 = 0;
@@ -589,7 +597,7 @@
private NavigationBarFragment mNavigationBar;
private View mNavigationBarView;
- private ActivityLaunchAnimator mActivityLaunchAnimator;
+ protected ActivityLaunchAnimator mActivityLaunchAnimator;
@Override
public void start() {
@@ -760,7 +768,7 @@
mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);
mActivityLaunchAnimator = new ActivityLaunchAnimator(mStatusBarWindow,
- this::collapsePanel,
+ this,
mNotificationPanel,
mStackScroller);
mGutsManager.setUpWithPresenter(this, mEntryManager, mStackScroller, mCheckSaveListener,
@@ -803,15 +811,14 @@
.commit();
mIconController = Dependency.get(StatusBarIconController.class);
- mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow, mGroupManager);
- mHeadsUpManager.setBar(this);
+ mHeadsUpManager = new HeadsUpManagerPhone(context, mStatusBarWindow, mGroupManager, this,
+ mVisualStabilityManager);
mHeadsUpManager.addListener(this);
mHeadsUpManager.addListener(mNotificationPanel);
mHeadsUpManager.addListener(mGroupManager);
mHeadsUpManager.addListener(mVisualStabilityManager);
mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
mGroupManager.setHeadsUpManager(mHeadsUpManager);
- mHeadsUpManager.setVisualStabilityManager(mVisualStabilityManager);
putComponent(HeadsUpManager.class, mHeadsUpManager);
mEntryManager.setUpWithPresenter(this, mStackScroller, this, mHeadsUpManager);
@@ -831,7 +838,7 @@
} catch (RemoteException ex) {
// no window manager? good luck with that
}
-
+ mScreenPinningNotify = new ScreenPinningNotify(mContext);
mStackScroller.setLongPressListener(mEntryManager.getNotificationLongClicker());
mStackScroller.setStatusBar(this);
mStackScroller.setGroupManager(mGroupManager);
@@ -1342,7 +1349,8 @@
@Override
public void onPerformRemoveNotification(StatusBarNotification n) {
- if (mStackScroller.hasPulsingNotifications() && mHeadsUpManager.getAllEntries().isEmpty()) {
+ if (mStackScroller.hasPulsingNotifications() &&
+ !mHeadsUpManager.hasHeadsUpNotifications()) {
// We were showing a pulse for a notification, but no notifications are pulsing anymore.
// Finish the pulse.
mDozeScrimController.pulseOutNow();
@@ -2054,6 +2062,12 @@
}
}
+ public void onLaunchAnimationCancelled() {
+ if (!isCollapsing()) {
+ onClosingFinished();
+ }
+ }
+
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
@@ -2085,9 +2099,8 @@
}
public void maybeEscalateHeadsUp() {
- Collection<HeadsUpManager.HeadsUpEntry> entries = mHeadsUpManager.getAllEntries();
- for (HeadsUpManager.HeadsUpEntry entry : entries) {
- final StatusBarNotification sbn = entry.entry.notification;
+ mHeadsUpManager.getAllEntries().forEach(entry -> {
+ final StatusBarNotification sbn = entry.notification;
final Notification notification = sbn.getNotification();
if (notification.fullScreenIntent != null) {
if (DEBUG) {
@@ -2097,11 +2110,11 @@
EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION,
sbn.getKey());
notification.fullScreenIntent.send();
- entry.entry.notifyFullScreenIntentLaunched();
+ entry.notifyFullScreenIntentLaunched();
} catch (PendingIntent.CanceledException e) {
}
}
- }
+ });
mHeadsUpManager.releaseAllImmediately();
}
@@ -2136,6 +2149,21 @@
}
+ @Override
+ public void showPinningEnterExitToast(boolean entering) {
+ if (entering) {
+ mScreenPinningNotify.showPinningStartToast();
+ } else {
+ mScreenPinningNotify.showPinningExitToast();
+ }
+ }
+
+ @Override
+ public void showPinningEscapeToast() {
+ mScreenPinningNotify.showEscapeToast(getNavigationBarView() == null
+ || getNavigationBarView().isRecentsButtonVisible());
+ }
+
boolean panelsEnabled() {
return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0
&& (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0
@@ -2651,6 +2679,10 @@
if (mStatusBarView != null) {
dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions());
}
+ pw.println(" StatusBarWindowView: ");
+ if (mStatusBarWindow != null) {
+ mStatusBarWindow.dump(fd, pw, args);
+ }
pw.println(" mMediaManager: ");
if (mMediaManager != null) {
@@ -3418,7 +3450,7 @@
}
public boolean isCollapsing() {
- return mNotificationPanel.isCollapsing();
+ return mNotificationPanel.isCollapsing() || mActivityLaunchAnimator.isAnimationPending();
}
public void addPostCollapseAction(Runnable r) {
@@ -4627,24 +4659,22 @@
@Override
public void onPulseStarted() {
callback.onPulseStarted();
- Collection<HeadsUpManager.HeadsUpEntry> pulsingEntries =
- mHeadsUpManager.getAllEntries();
- if (!pulsingEntries.isEmpty()) {
+ if (mHeadsUpManager.hasHeadsUpNotifications()) {
// Only pulse the stack scroller if there's actually something to show.
// Otherwise just show the always-on screen.
- setPulsing(pulsingEntries);
+ setPulsing(true);
}
}
@Override
public void onPulseFinished() {
callback.onPulseFinished();
- setPulsing(null);
+ setPulsing(false);
}
- private void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+ private void setPulsing(boolean pulsing) {
mNotificationPanel.setPulsing(pulsing);
- mVisualStabilityManager.setPulsing(pulsing != null);
+ mVisualStabilityManager.setPulsing(pulsing);
mIgnoreTouchWhilePulsing = false;
}
}, reason);
@@ -4792,7 +4822,7 @@
// for heads up notifications
- protected HeadsUpManager mHeadsUpManager;
+ protected HeadsUpManagerPhone mHeadsUpManager;
private AboveShelfObserver mAboveShelfObserver;
@@ -4895,7 +4925,7 @@
// Release the HUN notification to the shade.
if (isPresenterFullyCollapsed()) {
- HeadsUpManager.setIsClickedNotification(row, true);
+ HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
}
//
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
@@ -4959,6 +4989,7 @@
try {
launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
null, null, getActivityOptions(row));
+ mActivityLaunchAnimator.setLaunchResult(launchResult);
} catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here.
// Just log the exception message.
@@ -4970,7 +5001,7 @@
mAssistManager.hideAssist();
}
}
- if (shouldCollapse(launchResult)) {
+ if (shouldCollapse()) {
if (Looper.getMainLooper().isCurrentThread()) {
collapsePanel();
} else {
@@ -5003,17 +5034,8 @@
}, afterKeyguardGone);
}
- private boolean shouldCollapse(int launchResult) {
- return mState != StatusBarState.SHADE
- || (launchResult != ActivityManager.START_TASK_TO_FRONT
- && launchResult != ActivityManager.START_SUCCESS);
- }
-
- public void onExpandAnimationFinished() {
- if (!isPresenterFullyCollapsed()) {
- instantCollapseNotificationPanel();
- visibilityChanged(false);
- }
+ private boolean shouldCollapse() {
+ return mState != StatusBarState.SHADE || !mActivityLaunchAnimator.isAnimationPending();
}
public void collapsePanel(boolean animate) {
@@ -5128,7 +5150,8 @@
.addNextIntentWithParentStack(intent)
.startActivities(getActivityOptions(row),
new UserHandle(UserHandle.getUserId(appUid)));
- if (shouldCollapse(launchResult)) {
+ mActivityLaunchAnimator.setLaunchResult(launchResult);
+ if (shouldCollapse()) {
// Putting it back on the main thread, since we're touching views
mStatusBarWindow.post(() -> animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index f7d0967..a79a41b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -62,6 +62,9 @@
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
public class StatusBarWindowView extends FrameLayout {
public static final String TAG = "StatusBarWindowView";
@@ -89,6 +92,7 @@
private boolean mTouchCancelled;
private boolean mTouchActive;
private boolean mExpandAnimationRunning;
+ private boolean mExpandAnimationPending;
public StatusBarWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -268,7 +272,7 @@
|| ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
setTouchActive(false);
}
- if (mTouchCancelled || mExpandAnimationRunning) {
+ if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) {
return false;
}
mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());
@@ -393,6 +397,17 @@
mExpandAnimationRunning = expandAnimationRunning;
}
+ public void setExpandAnimationPending(boolean pending) {
+ mExpandAnimationPending = pending;
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.print(" mExpandAnimationPending="); pw.println(mExpandAnimationPending);
+ pw.print(" mExpandAnimationRunning="); pw.println(mExpandAnimationRunning);
+ pw.print(" mTouchCancelled="); pw.println(mTouchCancelled);
+ pw.print(" mTouchActive="); pw.println(mTouchActive);
+ }
+
public class LayoutParams extends FrameLayout.LayoutParams {
public boolean ignoreRightInset;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
index 6a573f5..d85e18c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
@@ -14,10 +14,14 @@
package com.android.systemui.statusbar.policy;
+import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
+import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
+import java.util.List;
+
/**
* For mocking because AccessibilityManager is final for some reason...
*/
@@ -39,4 +43,27 @@
public void removeCallback(AccessibilityServicesStateChangeListener listener) {
mAccessibilityManager.removeAccessibilityServicesStateChangeListener(listener);
}
+
+ public void addAccessibilityStateChangeListener(
+ AccessibilityManager.AccessibilityStateChangeListener listener) {
+ mAccessibilityManager.addAccessibilityStateChangeListener(listener);
+ }
+
+ public void removeAccessibilityStateChangeListener(
+ AccessibilityManager.AccessibilityStateChangeListener listener) {
+ mAccessibilityManager.removeAccessibilityStateChangeListener(listener);
+ }
+
+ public boolean isEnabled() {
+ return mAccessibilityManager.isEnabled();
+ }
+
+ public void sendAccessibilityEvent(AccessibilityEvent event) {
+ mAccessibilityManager.sendAccessibilityEvent(event);
+ }
+
+ public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(
+ int feedbackTypeFlags) {
+ return mAccessibilityManager.getEnabledAccessibilityServiceList(feedbackTypeFlags);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 53dfb24..a2b896d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -16,118 +16,68 @@
package com.android.systemui.statusbar.policy;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.os.SystemClock;
import android.os.Handler;
import android.os.Looper;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.support.v4.util.ArraySet;
import android.util.ArrayMap;
+import android.provider.Settings;
import android.util.Log;
-import android.util.Pools;
-import android.view.View;
-import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.StatusBar;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Iterator;
+import java.util.stream.Stream;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Stack;
/**
* A manager which handles heads up notifications which is a special mode where
* they simply peek from the top of the screen.
*/
-public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsListener,
- VisualStabilityManager.Callback {
+public class HeadsUpManager {
private static final String TAG = "HeadsUpManager";
private static final boolean DEBUG = false;
private static final String SETTING_HEADS_UP_SNOOZE_LENGTH_MS = "heads_up_snooze_length_ms";
- private static final int TAG_CLICKED_NOTIFICATION = R.id.is_clicked_heads_up_tag;
- private final int mHeadsUpNotificationDecay;
- private final int mMinimumDisplayTime;
+ protected final Clock mClock = new Clock();
+ protected final Context mContext;
+ protected final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>();
+ protected final Handler mHandler = new Handler(Looper.getMainLooper());
- private final int mTouchAcceptanceDelay;
+ protected int mHeadsUpNotificationDecay;
+ protected int mMinimumDisplayTime;
+ protected int mTouchAcceptanceDelay;
+ protected int mSnoozeLengthMs;
+ protected boolean mHasPinnedNotification;
+ protected int mUser;
+
+ private final HashMap<String, HeadsUpEntry> mHeadsUpEntries = new HashMap<>();
private final ArrayMap<String, Long> mSnoozedPackages;
- private final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>();
- private final int mDefaultSnoozeLengthMs;
- private final Handler mHandler = new Handler(Looper.getMainLooper());
- private final Pools.Pool<HeadsUpEntry> mEntryPool = new Pools.Pool<HeadsUpEntry>() {
+ private final ContentObserver mSettingsObserver;
- private Stack<HeadsUpEntry> mPoolObjects = new Stack<>();
-
- @Override
- public HeadsUpEntry acquire() {
- if (!mPoolObjects.isEmpty()) {
- return mPoolObjects.pop();
- }
- return new HeadsUpEntry();
- }
-
- @Override
- public boolean release(HeadsUpEntry instance) {
- instance.reset();
- mPoolObjects.push(instance);
- return true;
- }
- };
-
- private final View mStatusBarWindowView;
- private final int mStatusBarHeight;
- private final Context mContext;
- private final NotificationGroupManager mGroupManager;
- private StatusBar mBar;
- private int mSnoozeLengthMs;
- private ContentObserver mSettingsObserver;
- private HashMap<String, HeadsUpEntry> mHeadsUpEntries = new HashMap<>();
- private HashSet<String> mSwipedOutKeys = new HashSet<>();
- private int mUser;
- private Clock mClock;
- private boolean mReleaseOnExpandFinish;
- private boolean mTrackingHeadsUp;
- private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>();
- private ArraySet<NotificationData.Entry> mEntriesToRemoveWhenReorderingAllowed
- = new ArraySet<>();
- private boolean mIsExpanded;
- private boolean mHasPinnedNotification;
- private int[] mTmpTwoArray = new int[2];
- private boolean mHeadsUpGoingAway;
- private boolean mWaitingOnCollapseWhenGoingAway;
- private boolean mIsObserving;
- private boolean mRemoteInputActive;
- private float mExpandedHeight;
- private VisualStabilityManager mVisualStabilityManager;
- private int mStatusBarState;
-
- public HeadsUpManager(final Context context, View statusBarWindowView,
- NotificationGroupManager groupManager) {
+ public HeadsUpManager(@NonNull final Context context) {
mContext = context;
- Resources resources = mContext.getResources();
- mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
- mSnoozedPackages = new ArrayMap<>();
- mDefaultSnoozeLengthMs = resources.getInteger(R.integer.heads_up_default_snooze_length_ms);
- mSnoozeLengthMs = mDefaultSnoozeLengthMs;
+ Resources resources = context.getResources();
mMinimumDisplayTime = resources.getInteger(R.integer.heads_up_notification_minimum_time);
mHeadsUpNotificationDecay = resources.getInteger(R.integer.heads_up_notification_decay);
- mClock = new Clock();
+ mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
+ mSnoozedPackages = new ArrayMap<>();
+ int defaultSnoozeLengthMs =
+ resources.getInteger(R.integer.heads_up_default_snooze_length_ms);
mSnoozeLengthMs = Settings.Global.getInt(context.getContentResolver(),
- SETTING_HEADS_UP_SNOOZE_LENGTH_MS, mDefaultSnoozeLengthMs);
+ SETTING_HEADS_UP_SNOOZE_LENGTH_MS, defaultSnoozeLengthMs);
mSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
@@ -142,47 +92,26 @@
context.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false,
mSettingsObserver);
- mStatusBarWindowView = statusBarWindowView;
- mGroupManager = groupManager;
- mStatusBarHeight = resources.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
}
- private void updateTouchableRegionListener() {
- boolean shouldObserve = mHasPinnedNotification || mHeadsUpGoingAway
- || mWaitingOnCollapseWhenGoingAway;
- if (shouldObserve == mIsObserving) {
- return;
- }
- if (shouldObserve) {
- mStatusBarWindowView.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
- mStatusBarWindowView.requestLayout();
- } else {
- mStatusBarWindowView.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
- }
- mIsObserving = shouldObserve;
- }
-
- public void setBar(StatusBar bar) {
- mBar = bar;
- }
-
- public void addListener(OnHeadsUpChangedListener listener) {
+ /**
+ * Adds an OnHeadUpChangedListener to observe events.
+ */
+ public void addListener(@NonNull OnHeadsUpChangedListener listener) {
mListeners.add(listener);
}
- public void removeListener(OnHeadsUpChangedListener listener) {
+ /**
+ * Removes the OnHeadUpChangedListener from the observer list.
+ */
+ public void removeListener(@NonNull OnHeadsUpChangedListener listener) {
mListeners.remove(listener);
}
- public StatusBar getBar() {
- return mBar;
- }
-
/**
* Called when posting a new notification to the heads up.
*/
- public void showNotification(NotificationData.Entry headsUp) {
+ public void showNotification(@NonNull NotificationData.Entry headsUp) {
if (DEBUG) Log.v(TAG, "showNotification");
addHeadsUpEntry(headsUp);
updateNotification(headsUp, true);
@@ -192,7 +121,7 @@
/**
* Called when updating or posting a notification to the heads up.
*/
- public void updateNotification(NotificationData.Entry headsUp, boolean alert) {
+ public void updateNotification(@NonNull NotificationData.Entry headsUp, boolean alert) {
if (DEBUG) Log.v(TAG, "updateNotification");
headsUp.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
@@ -204,14 +133,13 @@
// with the groupmanager
return;
}
- headsUpEntry.updateEntry();
+ headsUpEntry.updateEntry(true /* updatePostTime */);
setEntryPinned(headsUpEntry, shouldHeadsUpBecomePinned(headsUp));
}
}
- private void addHeadsUpEntry(NotificationData.Entry entry) {
- HeadsUpEntry headsUpEntry = mEntryPool.acquire();
-
+ private void addHeadsUpEntry(@NonNull NotificationData.Entry entry) {
+ HeadsUpEntry headsUpEntry = createHeadsUpEntry();
// This will also add the entry to the sortedList
headsUpEntry.setEntry(entry);
mHeadsUpEntries.put(entry.key, headsUpEntry);
@@ -223,16 +151,17 @@
entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
}
- private boolean shouldHeadsUpBecomePinned(NotificationData.Entry entry) {
- return mStatusBarState != StatusBarState.KEYGUARD
- && !mIsExpanded || hasFullScreenIntent(entry);
+ protected boolean shouldHeadsUpBecomePinned(@NonNull NotificationData.Entry entry) {
+ return hasFullScreenIntent(entry);
}
- private boolean hasFullScreenIntent(NotificationData.Entry entry) {
+ protected boolean hasFullScreenIntent(@NonNull NotificationData.Entry entry) {
return entry.notification.getNotification().fullScreenIntent != null;
}
- private void setEntryPinned(HeadsUpEntry headsUpEntry, boolean isPinned) {
+ protected void setEntryPinned(
+ @NonNull HeadsUpManager.HeadsUpEntry headsUpEntry, boolean isPinned) {
+ if (DEBUG) Log.v(TAG, "setEntryPinned: " + isPinned);
ExpandableNotificationRow row = headsUpEntry.entry.row;
if (row.isPinned() != isPinned) {
row.setPinned(isPinned);
@@ -247,33 +176,35 @@
}
}
- private void removeHeadsUpEntry(NotificationData.Entry entry) {
+ protected void removeHeadsUpEntry(NotificationData.Entry entry) {
HeadsUpEntry remove = mHeadsUpEntries.remove(entry.key);
+ onHeadsUpEntryRemoved(remove);
+ releaseHeadsUpEntry(remove);
+ }
+
+ protected void onHeadsUpEntryRemoved(HeadsUpEntry remove) {
+ NotificationData.Entry entry = remove.entry;
entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
entry.row.setHeadsUp(false);
setEntryPinned(remove, false /* isPinned */);
for (OnHeadsUpChangedListener listener : mListeners) {
listener.onHeadsUpStateChanged(entry, false);
}
- mEntryPool.release(remove);
}
- public void removeAllHeadsUpEntries() {
- for (String key : mHeadsUpEntries.keySet()) {
- removeHeadsUpEntry(mHeadsUpEntries.get(key).entry);
- }
- }
-
- private void updatePinnedMode() {
+ protected void updatePinnedMode() {
boolean hasPinnedNotification = hasPinnedNotificationInternal();
if (hasPinnedNotification == mHasPinnedNotification) {
return;
}
+ if (DEBUG) {
+ Log.v(TAG, "Pinned mode changed: " + mHasPinnedNotification + " -> " +
+ hasPinnedNotification);
+ }
mHasPinnedNotification = hasPinnedNotification;
if (mHasPinnedNotification) {
MetricsLogger.count(mContext, "note_peek", 1);
}
- updateTouchableRegionListener();
for (OnHeadsUpChangedListener listener : mListeners) {
listener.onHeadsUpPinnedModeChanged(hasPinnedNotification);
}
@@ -285,47 +216,36 @@
* @return true if the notification was removed and false if it still needs to be kept around
* for a bit since it wasn't shown long enough
*/
- public boolean removeNotification(String key, boolean ignoreEarliestRemovalTime) {
- if (DEBUG) Log.v(TAG, "remove");
- if (wasShownLongEnough(key) || ignoreEarliestRemovalTime) {
- releaseImmediately(key);
- return true;
- } else {
- getHeadsUpEntry(key).removeAsSoonAsPossible();
- return false;
- }
+ public boolean removeNotification(@NonNull String key, boolean ignoreEarliestRemovalTime) {
+ if (DEBUG) Log.v(TAG, "removeNotification");
+ releaseImmediately(key);
+ return true;
}
- private boolean wasShownLongEnough(String key) {
- HeadsUpEntry headsUpEntry = getHeadsUpEntry(key);
- HeadsUpEntry topEntry = getTopEntry();
- if (mSwipedOutKeys.contains(key)) {
- // We always instantly dismiss views being manually swiped out.
- mSwipedOutKeys.remove(key);
- return true;
- }
- if (headsUpEntry != topEntry) {
- return true;
- }
- return headsUpEntry.wasShownLongEnough();
- }
-
+ /**
+ * Returns if the given notification is in the Heads Up Notification list or not.
+ */
public boolean isHeadsUp(String key) {
return mHeadsUpEntries.containsKey(key);
}
/**
- * Push any current Heads Up notification down into the shade.
+ * Pushes any current Heads Up notification down into the shade.
*/
public void releaseAllImmediately() {
if (DEBUG) Log.v(TAG, "releaseAllImmediately");
- ArrayList<String> keys = new ArrayList<>(mHeadsUpEntries.keySet());
- for (String key : keys) {
- releaseImmediately(key);
+ Iterator<HeadsUpEntry> iterator = mHeadsUpEntries.values().iterator();
+ while (iterator.hasNext()) {
+ HeadsUpEntry entry = iterator.next();
+ iterator.remove();
+ onHeadsUpEntryRemoved(entry);
}
}
- public void releaseImmediately(String key) {
+ /**
+ * Pushes the given Heads Up notification down into the shade.
+ */
+ public void releaseImmediately(@NonNull String key) {
HeadsUpEntry headsUpEntry = getHeadsUpEntry(key);
if (headsUpEntry == null) {
return;
@@ -334,11 +254,14 @@
removeHeadsUpEntry(shadeEntry);
}
- public boolean isSnoozed(String packageName) {
+ /**
+ * Returns if the given notification is snoozed or not.
+ */
+ public boolean isSnoozed(@NonNull String packageName) {
final String key = snoozeKey(packageName, mUser);
Long snoozedUntil = mSnoozedPackages.get(key);
if (snoozedUntil != null) {
- if (snoozedUntil > SystemClock.elapsedRealtime()) {
+ if (snoozedUntil > mClock.currentTimeMillis()) {
if (DEBUG) Log.v(TAG, key + " snoozed");
return true;
}
@@ -347,33 +270,61 @@
return false;
}
+ /**
+ * Snoozes all current Heads Up Notifications.
+ */
public void snooze() {
for (String key : mHeadsUpEntries.keySet()) {
HeadsUpEntry entry = mHeadsUpEntries.get(key);
String packageName = entry.entry.notification.getPackageName();
mSnoozedPackages.put(snoozeKey(packageName, mUser),
- SystemClock.elapsedRealtime() + mSnoozeLengthMs);
+ mClock.currentTimeMillis() + mSnoozeLengthMs);
}
- mReleaseOnExpandFinish = true;
}
- private static String snoozeKey(String packageName, int user) {
+ private static String snoozeKey(@NonNull String packageName, int user) {
return user + "," + packageName;
}
- private HeadsUpEntry getHeadsUpEntry(String key) {
+ protected HeadsUpEntry getHeadsUpEntry(@NonNull String key) {
return mHeadsUpEntries.get(key);
}
- public NotificationData.Entry getEntry(String key) {
- return mHeadsUpEntries.get(key).entry;
+ /**
+ * Returns the entry of given Heads Up Notification.
+ *
+ * @param key Key of heads up notification
+ */
+ public NotificationData.Entry getEntry(@NonNull String key) {
+ HeadsUpEntry entry = mHeadsUpEntries.get(key);
+ return entry != null ? entry.entry : null;
}
- public Collection<HeadsUpEntry> getAllEntries() {
- return mHeadsUpEntries.values();
+ /**
+ * Returns the stream of all current Heads Up Notifications.
+ */
+ @NonNull
+ public Stream<NotificationData.Entry> getAllEntries() {
+ return mHeadsUpEntries.values().stream().map(headsUpEntry -> headsUpEntry.entry);
}
- public HeadsUpEntry getTopEntry() {
+ /**
+ * Returns the top Heads Up Notification, which appeares to show at first.
+ */
+ @Nullable
+ public NotificationData.Entry getTopEntry() {
+ HeadsUpEntry topEntry = getTopHeadsUpEntry();
+ return (topEntry != null) ? topEntry.entry : null;
+ }
+
+ /**
+ * Returns if any heads up notification is available or not.
+ */
+ public boolean hasHeadsUpNotifications() {
+ return !mHeadsUpEntries.isEmpty();
+ }
+
+ protected HeadsUpEntry getTopHeadsUpEntry() {
if (mHeadsUpEntries.isEmpty()) {
return null;
}
@@ -387,56 +338,21 @@
}
/**
- * Decides whether a click is invalid for a notification, i.e it has not been shown long enough
- * that a user might have consciously clicked on it.
- *
- * @param key the key of the touched notification
- * @return whether the touch is invalid and should be discarded
+ * Sets the current user.
*/
- public boolean shouldSwallowClick(String key) {
- HeadsUpEntry entry = mHeadsUpEntries.get(key);
- if (entry != null && mClock.currentTimeMillis() < entry.postTime) {
- return true;
- }
- return false;
- }
-
- public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
- if (mIsExpanded || mBar.isBouncerShowing()) {
- // The touchable region is always the full area when expanded
- return;
- }
- if (mHasPinnedNotification) {
- ExpandableNotificationRow topEntry = getTopEntry().entry.row;
- if (topEntry.isChildInGroup()) {
- final ExpandableNotificationRow groupSummary
- = mGroupManager.getGroupSummary(topEntry.getStatusBarNotification());
- if (groupSummary != null) {
- topEntry = groupSummary;
- }
- }
- topEntry.getLocationOnScreen(mTmpTwoArray);
- int minX = mTmpTwoArray[0];
- int maxX = mTmpTwoArray[0] + topEntry.getWidth();
- int maxY = topEntry.getIntrinsicHeight();
-
- info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
- info.touchableRegion.set(minX, 0, maxX, maxY);
- } else if (mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway) {
- info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
- info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
- }
- }
-
public void setUser(int user) {
mUser = user;
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("HeadsUpManager state:");
+ dumpInternal(fd, pw, args);
+ }
+
+ protected void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print(" mTouchAcceptanceDelay="); pw.println(mTouchAcceptanceDelay);
pw.print(" mSnoozeLengthMs="); pw.println(mSnoozeLengthMs);
- pw.print(" now="); pw.println(SystemClock.elapsedRealtime());
+ pw.print(" now="); pw.println(mClock.currentTimeMillis());
pw.print(" mUser="); pw.println(mUser);
for (HeadsUpEntry entry: mHeadsUpEntries.values()) {
pw.print(" HeadsUpEntry="); pw.println(entry.entry);
@@ -449,6 +365,9 @@
}
}
+ /**
+ * Returns if there are any pinned Heads Up Notifications or not.
+ */
public boolean hasPinnedHeadsUp() {
return mHasPinnedNotification;
}
@@ -464,14 +383,8 @@
}
/**
- * Notifies that a notification was swiped out and will be removed.
- *
- * @param key the notification key
+ * Unpins all pinned Heads Up Notifications.
*/
- public void addSwipedOutNotification(String key) {
- mSwipedOutKeys.add(key);
- }
-
public void unpinAll() {
for (String key : mHeadsUpEntries.keySet()) {
HeadsUpEntry entry = mHeadsUpEntries.get(key);
@@ -481,60 +394,13 @@
}
}
- public void onExpandingFinished() {
- if (mReleaseOnExpandFinish) {
- releaseAllImmediately();
- mReleaseOnExpandFinish = false;
- } else {
- for (NotificationData.Entry entry : mEntriesToRemoveAfterExpand) {
- if (isHeadsUp(entry.key)) {
- // Maybe the heads-up was removed already
- removeHeadsUpEntry(entry);
- }
- }
- }
- mEntriesToRemoveAfterExpand.clear();
- }
-
- public void setTrackingHeadsUp(boolean trackingHeadsUp) {
- mTrackingHeadsUp = trackingHeadsUp;
- }
-
- public boolean isTrackingHeadsUp() {
- return mTrackingHeadsUp;
- }
-
- public void setIsExpanded(boolean isExpanded) {
- if (isExpanded != mIsExpanded) {
- mIsExpanded = isExpanded;
- if (isExpanded) {
- // make sure our state is sane
- mWaitingOnCollapseWhenGoingAway = false;
- mHeadsUpGoingAway = false;
- updateTouchableRegionListener();
- }
- }
- }
-
/**
- * @return the height of the top heads up notification when pinned. This is different from the
- * intrinsic height, which also includes whether the notification is system expanded and
- * is mainly used when dragging down from a heads up notification.
+ * Returns the value of the tracking-heads-up flag. See the doc of {@code setTrackingHeadsUp} as
+ * well.
*/
- public int getTopHeadsUpPinnedHeight() {
- HeadsUpEntry topEntry = getTopEntry();
- if (topEntry == null || topEntry.entry == null) {
- return 0;
- }
- ExpandableNotificationRow row = topEntry.entry.row;
- if (row.isChildInGroup()) {
- final ExpandableNotificationRow groupSummary
- = mGroupManager.getGroupSummary(row.getStatusBarNotification());
- if (groupSummary != null) {
- row = groupSummary;
- }
- }
- return row.getPinnedHeadsUpHeight();
+ public boolean isTrackingHeadsUp() {
+ // Might be implemented in subclass.
+ return false;
}
/**
@@ -553,147 +419,67 @@
}
/**
- * Set that we are exiting the headsUp pinned mode, but some notifications might still be
- * animating out. This is used to keep the touchable regions in a sane state.
+ * Sets an entry to be expanded and therefore stick in the heads up area if it's pinned
+ * until it's collapsed again.
*/
- public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
- if (headsUpGoingAway != mHeadsUpGoingAway) {
- mHeadsUpGoingAway = headsUpGoingAway;
- if (!headsUpGoingAway) {
- waitForStatusBarLayout();
- }
- updateTouchableRegionListener();
- }
- }
-
- /**
- * We need to wait on the whole panel to collapse, before we can remove the touchable region
- * listener.
- */
- private void waitForStatusBarLayout() {
- mWaitingOnCollapseWhenGoingAway = true;
- mStatusBarWindowView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft,
- int oldTop, int oldRight, int oldBottom) {
- if (mStatusBarWindowView.getHeight() <= mStatusBarHeight) {
- mStatusBarWindowView.removeOnLayoutChangeListener(this);
- mWaitingOnCollapseWhenGoingAway = false;
- updateTouchableRegionListener();
- }
- }
- });
- }
-
- public static void setIsClickedNotification(View child, boolean clicked) {
- child.setTag(TAG_CLICKED_NOTIFICATION, clicked ? true : null);
- }
-
- public static boolean isClickedHeadsUpNotification(View child) {
- Boolean clicked = (Boolean) child.getTag(TAG_CLICKED_NOTIFICATION);
- return clicked != null && clicked;
- }
-
- public void setRemoteInputActive(NotificationData.Entry entry, boolean remoteInputActive) {
- HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(entry.key);
- if (headsUpEntry != null && headsUpEntry.remoteInputActive != remoteInputActive) {
- headsUpEntry.remoteInputActive = remoteInputActive;
- if (remoteInputActive) {
- headsUpEntry.removeAutoRemovalCallbacks();
- } else {
- headsUpEntry.updateEntry(false /* updatePostTime */);
- }
- }
- }
/**
* Set an entry to be expanded and therefore stick in the heads up area if it's pinned
* until it's collapsed again.
*/
- public void setExpanded(NotificationData.Entry entry, boolean expanded) {
- HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(entry.key);
- if (headsUpEntry != null && headsUpEntry.expanded != expanded && entry.row.isPinned()) {
- headsUpEntry.expanded = expanded;
- if (expanded) {
- headsUpEntry.removeAutoRemovalCallbacks();
- } else {
- headsUpEntry.updateEntry(false /* updatePostTime */);
- }
+ public void setExpanded(@NonNull NotificationData.Entry entry, boolean expanded) {
+ HeadsUpManager.HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(entry.key);
+ if (headsUpEntry != null && entry.row.isPinned()) {
+ headsUpEntry.expanded(expanded);
}
}
- @Override
- public void onReorderingAllowed() {
- mBar.getNotificationScrollLayout().setHeadsUpGoingAwayAnimationsAllowed(false);
- for (NotificationData.Entry entry : mEntriesToRemoveWhenReorderingAllowed) {
- if (isHeadsUp(entry.key)) {
- // Maybe the heads-up was removed already
- removeHeadsUpEntry(entry);
- }
- }
- mEntriesToRemoveWhenReorderingAllowed.clear();
- mBar.getNotificationScrollLayout().setHeadsUpGoingAwayAnimationsAllowed(true);
+ @NonNull
+ protected HeadsUpEntry createHeadsUpEntry() {
+ return new HeadsUpEntry();
}
- public void setVisualStabilityManager(VisualStabilityManager visualStabilityManager) {
- mVisualStabilityManager = visualStabilityManager;
- }
-
- public void setStatusBarState(int statusBarState) {
- mStatusBarState = statusBarState;
+ protected void releaseHeadsUpEntry(@NonNull HeadsUpEntry entry) {
+ // Do nothing for HeadsUpEntry.
}
/**
* This represents a notification and how long it is in a heads up mode. It also manages its
* lifecycle automatically when created.
*/
- public class HeadsUpEntry implements Comparable<HeadsUpEntry> {
- public NotificationData.Entry entry;
+ protected class HeadsUpEntry implements Comparable<HeadsUpEntry> {
+ @Nullable public NotificationData.Entry entry;
public long postTime;
- public long earliestRemovaltime;
- private Runnable mRemoveHeadsUpRunnable;
public boolean remoteInputActive;
+ public long earliestRemovaltime;
public boolean expanded;
- public void setEntry(final NotificationData.Entry entry) {
+ private Runnable mRemoveHeadsUpRunnable;
+
+ public void setEntry(@Nullable final NotificationData.Entry entry) {
+ setEntry(entry, null);
+ }
+
+ public void setEntry(@Nullable final NotificationData.Entry entry,
+ @Nullable Runnable removeHeadsUpRunnable) {
this.entry = entry;
+ this.mRemoveHeadsUpRunnable = removeHeadsUpRunnable;
// The actual post time will be just after the heads-up really slided in
postTime = mClock.currentTimeMillis() + mTouchAcceptanceDelay;
- mRemoveHeadsUpRunnable = new Runnable() {
- @Override
- public void run() {
- if (!mVisualStabilityManager.isReorderingAllowed()) {
- mEntriesToRemoveWhenReorderingAllowed.add(entry);
- mVisualStabilityManager.addReorderingAllowedCallback(HeadsUpManager.this);
- } else if (!mTrackingHeadsUp) {
- removeHeadsUpEntry(entry);
- } else {
- mEntriesToRemoveAfterExpand.add(entry);
- }
- }
- };
- updateEntry();
- }
-
- public void updateEntry() {
- updateEntry(true);
+ updateEntry(true /* updatePostTime */);
}
public void updateEntry(boolean updatePostTime) {
+ if (DEBUG) Log.v(TAG, "updateEntry");
+
long currentTime = mClock.currentTimeMillis();
earliestRemovaltime = currentTime + mMinimumDisplayTime;
if (updatePostTime) {
postTime = Math.max(postTime, currentTime);
}
removeAutoRemovalCallbacks();
- if (mEntriesToRemoveAfterExpand.contains(entry)) {
- mEntriesToRemoveAfterExpand.remove(entry);
- }
- if (mEntriesToRemoveWhenReorderingAllowed.contains(entry)) {
- mEntriesToRemoveWhenReorderingAllowed.remove(entry);
- }
+
if (!isSticky()) {
long finishTime = postTime + mHeadsUpNotificationDecay;
long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime);
@@ -707,7 +493,7 @@
}
@Override
- public int compareTo(HeadsUpEntry o) {
+ public int compareTo(@NonNull HeadsUpEntry o) {
boolean isPinned = entry.row.isPinned();
boolean otherPinned = o.entry.row.isPinned();
if (isPinned && !otherPinned) {
@@ -734,26 +520,29 @@
: -1;
}
- public void removeAutoRemovalCallbacks() {
- mHandler.removeCallbacks(mRemoveHeadsUpRunnable);
- }
-
- public boolean wasShownLongEnough() {
- return earliestRemovaltime < mClock.currentTimeMillis();
- }
-
- public void removeAsSoonAsPossible() {
- removeAutoRemovalCallbacks();
- mHandler.postDelayed(mRemoveHeadsUpRunnable,
- earliestRemovaltime - mClock.currentTimeMillis());
+ public void expanded(boolean expanded) {
+ this.expanded = expanded;
}
public void reset() {
- removeAutoRemovalCallbacks();
entry = null;
- mRemoveHeadsUpRunnable = null;
expanded = false;
remoteInputActive = false;
+ removeAutoRemovalCallbacks();
+ mRemoveHeadsUpRunnable = null;
+ }
+
+ public void removeAutoRemovalCallbacks() {
+ if (mRemoveHeadsUpRunnable != null)
+ mHandler.removeCallbacks(mRemoveHeadsUpRunnable);
+ }
+
+ public void removeAsSoonAsPossible() {
+ if (mRemoveHeadsUpRunnable != null) {
+ removeAutoRemovalCallbacks();
+ mHandler.postDelayed(mRemoveHeadsUpRunnable,
+ earliestRemovaltime - mClock.currentTimeMillis());
+ }
}
}
@@ -762,5 +551,4 @@
return SystemClock.elapsedRealtime();
}
}
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpUtil.java
new file mode 100644
index 0000000..1e3c123c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpUtil.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.view.View;
+
+import com.android.systemui.R;
+
+/**
+ * A class of utility static methods for heads up notifications.
+ */
+public final class HeadsUpUtil {
+ private static final int TAG_CLICKED_NOTIFICATION = R.id.is_clicked_heads_up_tag;
+
+ /**
+ * Set the given view as clicked or not-clicked.
+ * @param view The view to be set the flag to.
+ * @param clicked True to set as clicked. False to not-clicked.
+ */
+ public static void setIsClickedHeadsUpNotification(View view, boolean clicked) {
+ view.setTag(TAG_CLICKED_NOTIFICATION, clicked ? true : null);
+ }
+
+ /**
+ * Check if the given view has the flag of "clicked notification"
+ * @param view The view to be checked.
+ * @return True if the view has clicked. False othrewise.
+ */
+ public static boolean isClickedHeadsUpNotification(View view) {
+ Boolean clicked = (Boolean) view.getTag(TAG_CLICKED_NOTIFICATION);
+ return clicked != null && clicked;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 1e894ff..3febdfd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -119,7 +119,8 @@
// for the current foreground user.
LocationManager locationManager =
(LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
- return locationManager.isLocationEnabledForUser(Process.myUserHandle());
+ return locationManager.isLocationEnabledForUser(
+ UserHandle.of(ActivityManager.getCurrentUser()));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index 424858a..d7a810e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -64,7 +64,7 @@
private boolean mPanelTracking;
private boolean mExpansionChanging;
private boolean mPanelFullWidth;
- private Collection<HeadsUpManager.HeadsUpEntry> mPulsing;
+ private boolean mPulsing;
private boolean mUnlockHintRunning;
private boolean mQsCustomizerShowing;
private int mIntrinsicPadding;
@@ -315,23 +315,18 @@
}
public boolean hasPulsingNotifications() {
- return mPulsing != null;
+ return mPulsing;
}
- public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> hasPulsing) {
+ public void setPulsing(boolean hasPulsing) {
mPulsing = hasPulsing;
}
public boolean isPulsing(NotificationData.Entry entry) {
- if (mPulsing == null) {
+ if (!mPulsing || mHeadsUpManager == null) {
return false;
}
- for (HeadsUpManager.HeadsUpEntry e : mPulsing) {
- if (e.entry == entry) {
- return true;
- }
- }
- return false;
+ return mHeadsUpManager.getAllEntries().anyMatch(e -> (e == entry));
}
public boolean isPanelTracking() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index ad8a0eb..1b55a5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -92,10 +92,11 @@
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.ScrollAdapter;
import android.support.v4.graphics.ColorUtils;
@@ -288,7 +289,7 @@
private HashSet<View> mClearOverlayViewsWhenFinished = new HashSet<>();
private HashSet<Pair<ExpandableNotificationRow, Boolean>> mHeadsUpChangeAnimations
= new HashSet<>();
- private HeadsUpManager mHeadsUpManager;
+ private HeadsUpManagerPhone mHeadsUpManager;
private boolean mTrackingHeadsUp;
private ScrimController mScrimController;
private boolean mForceNoOverlappingRendering;
@@ -358,14 +359,14 @@
}
};
private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
- private Collection<HeadsUpManager.HeadsUpEntry> mPulsing;
+ private boolean mPulsing;
private boolean mDrawBackgroundAsSrc;
private boolean mFadingOut;
private boolean mParentNotFullyVisible;
private boolean mGroupExpandedForMeasure;
private boolean mScrollable;
private View mForcedScroll;
- private float mDarkAmount = 1.0f;
+ private float mDarkAmount = 0f;
private static final Property<NotificationStackScrollLayout, Float> DARK_AMOUNT =
new FloatProperty<NotificationStackScrollLayout>("darkAmount") {
@Override
@@ -402,6 +403,7 @@
private final int mSeparatorThickness;
private final Rect mTmpRect = new Rect();
private int mClockBottom;
+ private int mAntiBurnInOffsetX;
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -523,9 +525,9 @@
setClipBounds(null);
} else {
float animProgress = Interpolators.FAST_OUT_SLOW_IN
- .getInterpolation(mDarkAmount);
+ .getInterpolation(1f - mDarkAmount);
float sidePaddingsProgress = Interpolators.FAST_OUT_SLOW_IN
- .getInterpolation(mDarkAmount * 2);
+ .getInterpolation((1f - mDarkAmount) * 2);
mTmpRect.set((int) MathUtils.lerp(darkLeft, lockScreenLeft, sidePaddingsProgress),
(int) MathUtils.lerp(darkTop, lockScreenTop, animProgress),
(int) MathUtils.lerp(darkRight, lockScreenRight, sidePaddingsProgress),
@@ -548,7 +550,7 @@
} else {
float alpha =
BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
- alpha *= mDarkAmount;
+ alpha *= 1f - mDarkAmount;
// We need to manually blend in the background color
int scrimColor = mScrimController.getBackgroundColor();
color = ColorUtils.blendARGB(scrimColor, mBgColor, alpha);
@@ -689,7 +691,7 @@
}
private void updateAlgorithmHeightAndPadding() {
- if (mPulsing != null) {
+ if (mPulsing) {
mTopPadding = mClockBottom;
} else {
mTopPadding = mAmbientState.isDark() ? mDarkTopPadding : mRegularTopPadding;
@@ -919,6 +921,27 @@
}
/**
+ * @return the height of the top heads up notification when pinned. This is different from the
+ * intrinsic height, which also includes whether the notification is system expanded and
+ * is mainly used when dragging down from a heads up notification.
+ */
+ private int getTopHeadsUpPinnedHeight() {
+ NotificationData.Entry topEntry = mHeadsUpManager.getTopEntry();
+ if (topEntry == null) {
+ return 0;
+ }
+ ExpandableNotificationRow row = topEntry.row;
+ if (row.isChildInGroup()) {
+ final ExpandableNotificationRow groupSummary
+ = mGroupManager.getGroupSummary(row.getStatusBarNotification());
+ if (groupSummary != null) {
+ row = groupSummary;
+ }
+ }
+ return row.getPinnedHeadsUpHeight();
+ }
+
+ /**
* @return the position from where the appear transition ends when expanding.
* Measured in absolute height.
*/
@@ -929,7 +952,7 @@
int minNotificationsForShelf = 1;
if (mTrackingHeadsUp
|| (mHeadsUpManager.hasPinnedHeadsUp() && !mAmbientState.isDark())) {
- appearPosition = mHeadsUpManager.getTopHeadsUpPinnedHeight();
+ appearPosition = getTopHeadsUpPinnedHeight();
minNotificationsForShelf = 2;
} else {
appearPosition = 0;
@@ -1197,9 +1220,9 @@
if (slidingChild instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild;
if (!mIsExpanded && row.isHeadsUp() && row.isPinned()
- && mHeadsUpManager.getTopEntry().entry.row != row
+ && mHeadsUpManager.getTopEntry().row != row
&& mGroupManager.getGroupSummary(
- mHeadsUpManager.getTopEntry().entry.row.getStatusBarNotification())
+ mHeadsUpManager.getTopEntry().row.getStatusBarNotification())
!= row) {
continue;
}
@@ -2119,7 +2142,7 @@
@Override
public boolean hasPulsingNotifications() {
- return mPulsing != null;
+ return mPulsing;
}
private void updateScrollability() {
@@ -2304,8 +2327,9 @@
return;
}
+ final boolean awake = mDarkAmount != 0 || mAmbientState.isDark();
mScrimController.setExcludedBackgroundArea(
- mFadingOut || mParentNotFullyVisible || mDarkAmount != 1 || mIsClipped ? null
+ mFadingOut || mParentNotFullyVisible || awake || mIsClipped ? null
: mCurrentBounds);
invalidate();
}
@@ -2751,7 +2775,7 @@
}
private boolean isClickedHeadsUp(View child) {
- return HeadsUpManager.isClickedHeadsUpNotification(child);
+ return HeadsUpUtil.isClickedHeadsUpNotification(child);
}
/**
@@ -3858,22 +3882,22 @@
mDarkNeedsAnimation = true;
mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation);
mNeedsAnimation = true;
- setDarkAmount(0.0f);
- } else if (!dark) {
- setDarkAmount(1.0f);
- }
- requestChildrenUpdate();
- if (dark) {
- mScrimController.setExcludedBackgroundArea(null);
} else {
+ setDarkAmount(dark ? 1f : 0f);
updateBackground();
}
-
+ requestChildrenUpdate();
+ applyCurrentBackgroundBounds();
updateWillNotDraw();
updateContentHeight();
+ updateAntiBurnInTranslation();
notifyHeightChangeListener(mShelf);
}
+ private void updateAntiBurnInTranslation() {
+ setTranslationX(mAmbientState.isDark() ? mAntiBurnInOffsetX : 0);
+ }
+
/**
* Updates whether or not this Layout will perform its own custom drawing (i.e. whether or
* not {@link #onDraw(Canvas)} is called). This method should be called whenever the
@@ -3894,7 +3918,7 @@
}
private void startBackgroundFadeIn() {
- ObjectAnimator fadeAnimator = ObjectAnimator.ofFloat(this, DARK_AMOUNT, 0f, 1f);
+ ObjectAnimator fadeAnimator = ObjectAnimator.ofFloat(this, DARK_AMOUNT, mDarkAmount, 0f);
fadeAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
fadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
fadeAnimator.start();
@@ -4256,7 +4280,7 @@
mAnimationFinishedRunnables.add(runnable);
}
- public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+ public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
mHeadsUpManager = headsUpManager;
mAmbientState.setHeadsUpManager(headsUpManager);
}
@@ -4324,8 +4348,8 @@
return mIsExpanded;
}
- public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing, int clockBottom) {
- if (mPulsing == null && pulsing == null) {
+ public void setPulsing(boolean pulsing, int clockBottom) {
+ if (!mPulsing && !pulsing) {
return;
}
mPulsing = pulsing;
@@ -4455,15 +4479,16 @@
mHeadsUpGoingAwayAnimationsAllowed = headsUpGoingAwayAnimationsAllowed;
}
- public void setDarkShelfOffsetX(int shelfOffsetX) {
- mShelf.setDarkOffsetX(shelfOffsetX);
+ public void setAntiBurnInOffsetX(int antiBurnInOffsetX) {
+ mAntiBurnInOffsetX = antiBurnInOffsetX;
+ updateAntiBurnInTranslation();
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(String.format("[%s: pulsing=%s qsCustomizerShowing=%s visibility=%s"
+ " alpha:%f scrollY:%d]",
this.getClass().getSimpleName(),
- mPulsing != null ?"T":"f",
+ mPulsing ? "T":"f",
mAmbientState.isQsCustomizerShowing() ? "T":"f",
getVisibility() == View.VISIBLE ? "visible"
: getVisibility() == View.GONE ? "gone"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
index 682b849..04a7bd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
@@ -30,7 +30,7 @@
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.HeadsUpUtil;
/**
* A state of a view. This can be used to apply a set of view properties to a view with
@@ -582,7 +582,7 @@
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- HeadsUpManager.setIsClickedNotification(child, false);
+ HeadsUpUtil.setIsClickedHeadsUpNotification(child, false);
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
child.setTag(TAG_START_TRANSLATION_Y, null);
child.setTag(TAG_END_TRANSLATION_Y, null);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index e1376ca..2c85bb6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -51,6 +51,7 @@
public static final int EVENT_SUPPRESSOR_CHANGED = 14; // (component|string) (name|string)
public static final int EVENT_MUTE_CHANGED = 15; // (stream|int) (muted|bool)
public static final int EVENT_TOUCH_LEVEL_DONE = 16; // (stream|int) (level|bool)
+ public static final int EVENT_ZEN_CONFIG_CHANGED = 17; // (allow/disallow|string)
private static final String[] EVENT_TAGS = {
"show_dialog",
@@ -70,6 +71,7 @@
"suppressor_changed",
"mute_changed",
"touch_level_done",
+ "zen_mode_config_changed",
};
public static final int DISMISS_REASON_UNKNOWN = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 2e23920..9aee00e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -43,6 +43,7 @@
import android.os.Vibrator;
import android.provider.Settings;
import android.service.notification.Condition;
+import android.service.notification.ZenModeConfig;
import android.util.ArrayMap;
import android.util.Log;
import android.view.accessibility.AccessibilityManager;
@@ -58,7 +59,9 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -75,7 +78,7 @@
private static final int DYNAMIC_STREAM_START_INDEX = 100;
private static final int VIBRATE_HINT_DURATION = 50;
- private static final ArrayMap<Integer, Integer> STREAMS = new ArrayMap<>();
+ static final ArrayMap<Integer, Integer> STREAMS = new ArrayMap<>();
static {
STREAMS.put(AudioSystem.STREAM_ALARM, R.string.stream_alarm);
STREAMS.put(AudioSystem.STREAM_BLUETOOTH_SCO, R.string.stream_bluetooth_sco);
@@ -108,7 +111,10 @@
private boolean mShowVolumeDialog;
private boolean mShowSafetyWarning;
private DeviceCallback mDeviceCallback = new DeviceCallback();
- private AudioDeviceInfo mConnectedDevice;
+ private final NotificationManager mNotificationManager;
+ @GuardedBy("mLock")
+ private List<AudioDeviceInfo> mConnectedDevices = new ArrayList<>();
+ private Object mLock = new Object();
private boolean mDestroyed;
private VolumePolicy mVolumePolicy;
@@ -120,6 +126,8 @@
public VolumeDialogControllerImpl(Context context) {
mContext = context.getApplicationContext();
+ mNotificationManager = (NotificationManager) mContext.getSystemService(
+ Context.NOTIFICATION_SERVICE);
Events.writeEvent(mContext, Events.EVENT_COLLECTION_STARTED);
mWorkerThread = new HandlerThread(VolumeDialogControllerImpl.class.getSimpleName());
mWorkerThread.start();
@@ -425,6 +433,7 @@
}
updateRingerModeExternalW(mAudio.getRingerMode());
updateZenModeW();
+ updateZenConfig();
updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
mCallbacks.onStateChanged(mState);
}
@@ -510,6 +519,26 @@
return true;
}
+ private boolean updateZenConfig() {
+ final NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy();
+ boolean disallowAlarms = (policy.priorityCategories & NotificationManager.Policy
+ .PRIORITY_CATEGORY_ALARMS) == 0;
+ boolean disallowMedia = (policy.priorityCategories & NotificationManager.Policy
+ .PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) == 0;
+ boolean disallowRinger = ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(policy);
+ if (mState.disallowAlarms == disallowAlarms && mState.disallowMedia == disallowMedia
+ && mState.disallowRinger == disallowRinger) {
+ return false;
+ }
+ mState.disallowAlarms = disallowAlarms;
+ mState.disallowMedia = disallowMedia;
+ mState.disallowRinger = disallowRinger;
+ Events.writeEvent(mContext, Events.EVENT_ZEN_CONFIG_CHANGED, "disallowAlarms=" +
+ disallowAlarms + " disallowMedia=" + disallowMedia + " disallowRinger=" +
+ disallowRinger);
+ return true;
+ }
+
private boolean updateRingerModeExternalW(int rm) {
if (rm == mState.ringerModeExternal) return false;
mState.ringerModeExternal = rm;
@@ -850,6 +879,10 @@
if (ZEN_MODE_URI.equals(uri)) {
changed = updateZenModeW();
}
+ if (ZEN_MODE_CONFIG_URI.equals(uri)) {
+ changed |= updateZenConfig();
+ }
+
if (changed) {
mCallbacks.onStateChanged(mState);
}
@@ -1026,26 +1059,25 @@
protected final class DeviceCallback extends AudioDeviceCallback {
public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
- for (AudioDeviceInfo info : addedDevices) {
- if (info.isSink()
- && (info.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP
- || info.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO)) {
- mConnectedDevice = info;
- mCallbacks.onConnectedDeviceChanged(info.getProductName().toString());
+ synchronized (mLock) {
+ for (AudioDeviceInfo info : addedDevices) {
+ if (info.isSink()
+ && (info.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP
+ || info.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO)) {
+ mConnectedDevices.add(info);
+ mCallbacks.onConnectedDeviceChanged(info.getProductName().toString());
+ }
}
}
}
public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
- if (mConnectedDevice == null) {
- mCallbacks.onConnectedDeviceChanged(null);
- return;
- }
- for (AudioDeviceInfo info : removedDevices) {
- if (info.isSink() == mConnectedDevice.isSink()
- && Objects.equals(info.getProductName(), mConnectedDevice.getProductName())
- && info.getType() == mConnectedDevice.getType()) {
- mConnectedDevice = null;
+ synchronized (mLock) {
+ for (AudioDeviceInfo info : removedDevices) {
+ mConnectedDevices.remove(info);
+ }
+
+ if (mConnectedDevices.size() == 0) {
mCallbacks.onConnectedDeviceChanged(null);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 56b7201..0c6e0f6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -36,7 +36,6 @@
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
-import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.media.AudioManager;
import android.media.AudioSystem;
@@ -58,12 +57,10 @@
import android.view.View.AccessibilityDelegate;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnClickListener;
-import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageButton;
@@ -79,6 +76,7 @@
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.plugins.VolumeDialogController.State;
import com.android.systemui.plugins.VolumeDialogController.StreamState;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -105,13 +103,14 @@
private CustomDialog mDialog;
private ViewGroup mDialogView;
private ViewGroup mDialogRowsView;
+ private ViewGroup mFooter;
private ImageButton mRingerIcon;
private TextView mRingerStatus;
private final List<VolumeRow> mRows = new ArrayList<>();
private ConfigurableTexts mConfigurableTexts;
private final SparseBooleanArray mDynamic = new SparseBooleanArray();
private final KeyguardManager mKeyguard;
- private final AccessibilityManager mAccessibilityMgr;
+ private final AccessibilityManagerWrapper mAccessibilityMgr;
private final Object mSafetyWarningLock = new Object();
private final Object mOutputChooserLock = new Object();
private final Accessibility mAccessibility = new Accessibility();
@@ -134,8 +133,7 @@
mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
mController = Dependency.get(VolumeDialogController.class);
mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
- mAccessibilityMgr =
- (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ mAccessibilityMgr = Dependency.get(AccessibilityManagerWrapper.class);
mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
}
@@ -203,8 +201,9 @@
hardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE));
mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows);
- mRingerIcon = mDialog.findViewById(R.id.ringer_icon);
- mRingerStatus = mDialog.findViewById(R.id.ringer_status);
+ mFooter = mDialog.findViewById(R.id.footer);
+ mRingerIcon = mFooter.findViewById(R.id.ringer_icon);
+ mRingerStatus = mFooter.findViewById(R.id.ringer_status);
if (mRows.isEmpty()) {
addRow(AudioManager.STREAM_MUSIC,
@@ -231,6 +230,10 @@
initRingerH();
}
+ protected ViewGroup getDialogView() {
+ return mDialogView;
+ }
+
private ColorStateList loadColorStateList(int colorResId) {
return ColorStateList.valueOf(mContext.getColor(colorResId));
}
@@ -258,6 +261,7 @@
private void addRow(int stream, int iconRes, int iconMuteRes, boolean important,
boolean defaultStream, boolean dynamic) {
+ if (D.BUG) Slog.d(TAG, "Adding row for stream " + stream);
VolumeRow row = new VolumeRow();
initRow(row, stream, iconRes, iconMuteRes, important, defaultStream);
int rowSize;
@@ -336,35 +340,8 @@
row.outputChooser = row.view.findViewById(R.id.output_chooser);
row.outputChooser.setOnClickListener(mClickOutputChooser);
- row.outputChooser.findViewById(R.id.output_chooser_button)
- .setOnClickListener(mClickOutputChooser);
row.connectedDevice = row.view.findViewById(R.id.volume_row_connected_device);
- // forward events above the slider into the slider
- row.view.setOnTouchListener(new OnTouchListener() {
- private final Rect mSliderHitRect = new Rect();
- private boolean mDragging;
-
- @SuppressLint("ClickableViewAccessibility")
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- row.slider.getHitRect(mSliderHitRect);
- if (!mDragging && event.getActionMasked() == MotionEvent.ACTION_DOWN
- && event.getY() < mSliderHitRect.top) {
- mDragging = true;
- }
- if (mDragging) {
- event.offsetLocation(-mSliderHitRect.left, -mSliderHitRect.top);
- row.slider.dispatchTouchEvent(event);
- if (event.getActionMasked() == MotionEvent.ACTION_UP
- || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
- mDragging = false;
- }
- return true;
- }
- return false;
- }
- });
row.icon = row.view.findViewById(R.id.volume_row_icon);
row.icon.setImageResource(iconRes);
if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
@@ -407,6 +384,8 @@
if (ss == null) {
return;
}
+ // normal -> vibrate -> silent -> normal (skip vibrate if device doesn't have
+ // a vibrator.
final boolean hasVibrator = mController.hasVibrator();
if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
if (hasVibrator) {
@@ -414,7 +393,12 @@
} else {
final boolean wasZero = ss.level == 0;
mController.setStreamVolume(AudioManager.STREAM_RING, wasZero ? 1 : 0);
+ mController.setRingerMode(AudioManager.RINGER_MODE_SILENT, false);
}
+ } else if (mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
+ final boolean wasZero = ss.level == 0;
+ mController.setStreamVolume(AudioManager.STREAM_RING, wasZero ? 1 : 0);
+ mController.setRingerMode(AudioManager.RINGER_MODE_SILENT, false);
} else {
mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
if (ss.level == 0) {
@@ -620,7 +604,7 @@
}
}
- private void onStateChangedH(State state) {
+ protected void onStateChangedH(State state) {
mState = state;
mDynamic.clear();
// add any new dynamic rows
@@ -668,10 +652,14 @@
&& mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
final boolean isRingSilent = isRingStream
&& mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT;
+ final boolean isZenPriorityOnly = mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS;
final boolean isZenNone = mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream)
: isZenNone ? (isRingStream || isSystemStream || isAlarmStream || isMusicStream)
+ : isZenPriorityOnly ? ((isAlarmStream && mState.disallowAlarms) ||
+ (isMusicStream && mState.disallowMedia) ||
+ (isRingStream && mState.disallowRinger))
: false;
// update slider max
@@ -889,7 +877,7 @@
return ss.remoteLabel;
}
try {
- return mContext.getString(ss.name);
+ return mContext.getResources().getString(ss.name);
} catch (Resources.NotFoundException e) {
Slog.e(TAG, "Can't find translation for stream " + ss);
return "";
@@ -899,7 +887,6 @@
private final OnClickListener mClickOutputChooser = new OnClickListener() {
@Override
public void onClick(View v) {
- // TODO: log
dismissH(DISMISS_REASON_OUTPUT_CHOOSER);
showOutputChooserH();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
index 368194e..f50a287 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
@@ -309,6 +309,12 @@
return super.getOutlineProvider();
}
+ @Override
+ public void setPressed(boolean pressed)
+ {
+ // Ignore presses because it activates the seekbar thumb unnecessarily.
+ }
+
public void setOutsideTouchListener(OnClickListener onClickListener) {
mHasOutsideTouch = true;
requestLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/car/CarVolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/car/CarVolumeDialogController.java
deleted file mode 100644
index 474085c..0000000
--- a/packages/SystemUI/src/com/android/systemui/volume/car/CarVolumeDialogController.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.volume.car;
-
-import android.car.Car;
-import android.car.CarNotConnectedException;
-import android.car.media.CarAudioManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.util.Log;
-
-import com.android.systemui.volume.VolumeDialogControllerImpl;
-
-/**
- * A volume dialog controller for the automotive use case.
- * TODO(hwwang): consider removing this class since it's coupled with stream_type and we are
- * moving to use AudioAttributes usage for volume control in a car.
- *
- * {@link android.car.media.CarAudioManager} is the source of truth to get the stream volumes.
- * And volume changes should be sent to the car's audio module instead of the android's audio mixer.
- */
-public class CarVolumeDialogController extends VolumeDialogControllerImpl {
- private static final String TAG = "CarVolumeDialogController";
-
- private final Car mCar;
- private CarAudioManager mCarAudioManager;
-
- private final ServiceConnection mConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
- try {
- mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE);
- setVolumeController();
- CarVolumeDialogController.this.getState();
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected!", e);
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName componentName) {
- Log.e(TAG, "Car service is disconnected");
- }
- };
-
- public CarVolumeDialogController(Context context) {
- super(context);
- mCar = Car.createCar(context, mConnection);
- mCar.connect();
- }
-
- @Override
- protected void setAudioManagerStreamVolume(int stream, int level, int flag) {
- if (mCarAudioManager == null) {
- Log.d(TAG, "Car audio manager is not initialized yet");
- return;
- }
- try {
- mCarAudioManager.setUsageVolume(stream, level, flag);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected", e);
- }
- }
-
- @Override
- protected int getAudioManagerStreamVolume(int stream) {
- if(mCarAudioManager == null) {
- Log.d(TAG, "Car audio manager is not initialized yet");
- return 0;
- }
-
- try {
- return mCarAudioManager.getUsageVolume(stream);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected", e);
- return 0;
- }
- }
-
- @Override
- protected int getAudioManagerStreamMaxVolume(int stream) {
- if(mCarAudioManager == null) {
- Log.d(TAG, "Car audio manager is not initialized yet");
- return 0;
- }
-
- try {
- return mCarAudioManager.getUsageMaxVolume(stream);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected", e);
- return 0;
- }
- }
-
- @Override
- protected int getAudioManagerStreamMinVolume(int stream) {
- if(mCarAudioManager == null) {
- Log.d(TAG, "Car audio manager is not initialized yet");
- return 0;
- }
-
- try {
- return mCarAudioManager.getUsageMinVolume(stream);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected", e);
- return 0;
- }
- }
-
- @Override
- public void setVolumeController() {
- if (mCarAudioManager == null) {
- Log.d(TAG, "Car audio manager is not initialized yet");
- return;
- }
- try {
- mCarAudioManager.setVolumeController(mVolumeController);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected", e);
- }
- }
-}
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 066cfe5..936ff51 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -50,8 +50,8 @@
android-slices-core \
android-slices-view \
android-slices-builders \
- apptoolkit-arch-core-runtime \
- apptoolkit-lifecycle-extensions \
+ android-arch-core-runtime \
+ android-arch-lifecycle-extensions \
LOCAL_STATIC_JAVA_LIBRARIES := \
metrics-helper-lib \
diff --git a/packages/SystemUI/tests/src/com/android/systemui/RoundedCornersTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
similarity index 66%
rename from packages/SystemUI/tests/src/com/android/systemui/RoundedCornersTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index 2a44771..2f05b06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/RoundedCornersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -14,9 +14,13 @@
package com.android.systemui;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
+
import static com.android.systemui.tuner.TunablePadding.FLAG_END;
import static com.android.systemui.tuner.TunablePadding.FLAG_START;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -29,6 +33,7 @@
import static org.mockito.Mockito.when;
import android.app.Fragment;
+import android.content.res.Configuration;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.view.Display;
@@ -36,7 +41,7 @@
import android.view.WindowManager;
import com.android.systemui.R.dimen;
-import com.android.systemui.RoundedCorners.TunablePaddingTagListener;
+import com.android.systemui.ScreenDecorations.TunablePaddingTagListener;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -51,9 +56,9 @@
@RunWith(AndroidTestingRunner.class)
@SmallTest
-public class RoundedCornersTest extends SysuiTestCase {
+public class ScreenDecorationsTest extends SysuiTestCase {
- private RoundedCorners mRoundedCorners;
+ private ScreenDecorations mScreenDecorations;
private StatusBar mStatusBar;
private WindowManager mWindowManager;
private FragmentService mFragmentService;
@@ -81,20 +86,22 @@
mTunerService = mDependency.injectMockDependency(TunerService.class);
- mRoundedCorners = new RoundedCorners();
- mRoundedCorners.mContext = mContext;
- mRoundedCorners.mComponents = mContext.getComponents();
+ mScreenDecorations = new ScreenDecorations();
+ mScreenDecorations.mContext = mContext;
+ mScreenDecorations.mComponents = mContext.getComponents();
mTunablePaddingService = mDependency.injectMockDependency(TunablePaddingService.class);
}
@Test
- public void testNoRounding() {
+ public void testNoRounding_NoCutout() {
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 0);
mContext.getOrCreateTestableResources()
.addOverride(dimen.rounded_corner_content_padding, 0);
- mRoundedCorners.start();
+ mScreenDecorations.start();
// No views added.
verify(mWindowManager, never()).addView(any(), any());
// No Fragments watched.
@@ -105,11 +112,13 @@
@Test
public void testRounding() {
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 20);
mContext.getOrCreateTestableResources()
.addOverride(dimen.rounded_corner_content_padding, 20);
- mRoundedCorners.start();
+ mScreenDecorations.start();
// Add 2 windows for rounded corners (top and bottom).
verify(mWindowManager, times(2)).addView(any(), any());
@@ -122,6 +131,44 @@
}
@Test
+ public void testCutout() {
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, true);
+ mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 0);
+ mContext.getOrCreateTestableResources()
+ .addOverride(dimen.rounded_corner_content_padding, 0);
+
+ mScreenDecorations.start();
+ // Add 2 windows for rounded corners (top and bottom).
+ verify(mWindowManager, times(2)).addView(any(), any());
+ }
+
+ @Test
+ public void testDelayedCutout() {
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
+ mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 0);
+ mContext.getOrCreateTestableResources()
+ .addOverride(dimen.rounded_corner_content_padding, 0);
+
+ mScreenDecorations.start();
+
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, true);
+ mScreenDecorations.onConfigurationChanged(new Configuration());
+
+ // Add 2 windows for rounded corners (top and bottom).
+ verify(mWindowManager, times(2)).addView(any(), any());
+ }
+
+ @Test
+ public void hasRoundedCornerOverlayFlagSet() {
+ assertThat(mScreenDecorations.getWindowLayoutParams().privateFlags
+ & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY,
+ is(PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY));
+ }
+
+ @Test
public void testPaddingTagListener() {
TunablePaddingTagListener tagListener = new TunablePaddingTagListener(14, 5);
View v = mock(View.class);
@@ -136,7 +183,7 @@
// Trigger callback and verify we get a TunablePadding created.
tagListener.onFragmentViewCreated(null, f);
- verify(mTunablePaddingService).add(eq(child), eq(RoundedCorners.PADDING), eq(14),
+ verify(mTunablePaddingService).add(eq(child), eq(ScreenDecorations.PADDING), eq(14),
eq(FLAG_START | FLAG_END));
// Call again and verify destroy is called.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/chooser/ChooserHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/chooser/ChooserHelperTest.java
deleted file mode 100644
index 8e0426a..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/chooser/ChooserHelperTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.chooser;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.content.Intent;
-import android.os.Binder;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import com.android.systemui.chooser.ChooserHelper;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyFloat;
-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.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class ChooserHelperTest extends SysuiTestCase {
-
- @Test
- public void testOnChoose_CallsStartActivityAsCallerWithToken() {
- final Intent intent = new Intent();
- final Binder token = new Binder();
- intent.putExtra(ActivityManager.EXTRA_PERMISSION_TOKEN, token);
-
- final Activity mockActivity = mock(Activity.class);
- when(mockActivity.getIntent()).thenReturn(intent);
-
- ChooserHelper.onChoose(mockActivity);
- verify(mockActivity, times(1)).startActivityAsCaller(
- any(), any(), eq(token), anyBoolean(), anyInt());
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
index 40f8059..dfc1852 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
@@ -30,6 +30,7 @@
import com.android.systemui.Prefs.Key;
import com.android.systemui.SysuiTestCase;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -40,6 +41,11 @@
private AutoAddTracker mAutoTracker;
+ @Before
+ public void setUp() {
+ Secure.putString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES, "");
+ }
+
@Test
public void testMigration() {
Prefs.putBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true);
@@ -50,7 +56,10 @@
assertTrue(mAutoTracker.isAdded(WORK));
assertFalse(mAutoTracker.isAdded(INVERSION));
+ // These keys have been removed; retrieving their values should always return the default.
+ assertTrue(Prefs.getBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true ));
assertFalse(Prefs.getBoolean(mContext, Key.QS_DATA_SAVER_ADDED, false));
+ assertTrue(Prefs.getBoolean(mContext, Key.QS_WORK_ADDED, true));
assertFalse(Prefs.getBoolean(mContext, Key.QS_WORK_ADDED, false));
mAutoTracker.destroy();
@@ -96,5 +105,4 @@
mAutoTracker.destroy();
}
-
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index 6e7477f..f3c1171 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -32,6 +32,7 @@
import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationInflaterTest;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -51,7 +52,7 @@
public NotificationTestHelper(Context context) {
mContext = context;
mInstrumentation = InstrumentationRegistry.getInstrumentation();
- mHeadsUpManager = new HeadsUpManager(mContext, null, mGroupManager);
+ mHeadsUpManager = new HeadsUpManagerPhone(mContext, null, mGroupManager, null, null);
}
public ExpandableNotificationRow createRow() throws Exception {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index a95e3db..2d2db1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -18,45 +18,48 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.app.AlarmManager.AlarmClockInfo;
+import android.os.Handler;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
-
import com.android.internal.app.ColorDisplayController;
import com.android.systemui.Dependency;
-import com.android.systemui.Prefs;
-import com.android.systemui.Prefs.Key;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
-
-import org.junit.After;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mockito;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
public class AutoTileManagerTest extends SysuiTestCase {
- private QSTileHost mQsTileHost;
+ @Mock private QSTileHost mQsTileHost;
+ @Mock private AutoAddTracker mAutoAddTracker;
+ @Captor private ArgumentCaptor<NextAlarmChangeCallback> mAlarmCallback;
+
private AutoTileManager mAutoTileManager;
@Before
public void setUp() throws Exception {
- mDependency.injectTestDependency(Dependency.BG_LOOPER,
- TestableLooper.get(this).getLooper());
- Prefs.putBoolean(mContext, Key.QS_NIGHTDISPLAY_ADDED, false);
- mQsTileHost = Mockito.mock(QSTileHost.class);
- mAutoTileManager = new AutoTileManager(mContext, mQsTileHost);
- }
-
- @After
- public void tearDown() throws Exception {
- mAutoTileManager = null;
+ MockitoAnnotations.initMocks(this);
+ mDependency.injectMockDependency(NextAlarmController.class);
+ mAutoTileManager = new AutoTileManager(mContext, mAutoAddTracker,
+ mQsTileHost, new Handler(TestableLooper.get(this).getLooper()));
+ verify(Dependency.get(NextAlarmController.class))
+ .addCallback(mAlarmCallback.capture());
}
@Test
@@ -106,4 +109,30 @@
ColorDisplayController.AUTO_MODE_DISABLED);
verify(mQsTileHost, never()).addTile("night");
}
+
+ @Test
+ public void alarmTileAdded_whenAlarmSet() {
+ mAlarmCallback.getValue().onNextAlarmChanged(new AlarmClockInfo(0, null));
+
+ verify(mQsTileHost).addTile("alarm");
+ verify(mAutoAddTracker).setTileAdded("alarm");
+ }
+
+ @Test
+ public void alarmTileNotAdded_whenAlarmNotSet() {
+ mAlarmCallback.getValue().onNextAlarmChanged(null);
+
+ verify(mQsTileHost, never()).addTile("alarm");
+ verify(mAutoAddTracker, never()).setTileAdded("alarm");
+ }
+
+ @Test
+ public void alarmTileNotAdded_whenAlreadyAdded() {
+ when(mAutoAddTracker.isAdded("alarm")).thenReturn(true);
+
+ mAlarmCallback.getValue().onNextAlarmChanged(new AlarmClockInfo(0, null));
+
+ verify(mQsTileHost, never()).addTile("alarm");
+ verify(mAutoAddTracker, never()).setTileAdded("alarm");
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
new file mode 100644
index 0000000..28f9417
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.phone;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.view.View;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.assertFalse;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class HeadsUpManagerPhoneTest extends SysuiTestCase {
+ @Rule public MockitoRule rule = MockitoJUnit.rule();
+
+ private static final String TEST_PACKAGE_NAME = "test";
+ private static final int TEST_UID = 0;
+
+ private HeadsUpManagerPhone mHeadsUpManager;
+
+ private NotificationData.Entry mEntry;
+ private StatusBarNotification mSbn;
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+ @Mock private NotificationGroupManager mGroupManager;
+ @Mock private View mStatusBarWindowView;
+ @Mock private StatusBar mBar;
+ @Mock private ExpandableNotificationRow mRow;
+ @Mock private VisualStabilityManager mVSManager;
+
+ @Before
+ public void setUp() {
+ when(mVSManager.isReorderingAllowed()).thenReturn(true);
+
+ mHeadsUpManager = new HeadsUpManagerPhone(mContext, mStatusBarWindowView, mGroupManager, mBar, mVSManager);
+
+ Notification.Builder n = new Notification.Builder(mContext, "")
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text");
+ mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
+ 0, n.build(), new UserHandle(ActivityManager.getCurrentUser()), null, 0);
+
+ mEntry = new NotificationData.Entry(mSbn);
+ mEntry.row = mRow;
+ mEntry.expandedIcon = mock(StatusBarIconView.class);
+ }
+
+ @Test
+ public void testBasicOperations() {
+ // Check the initial state.
+ assertNull(mHeadsUpManager.getEntry(mEntry.key));
+ assertNull(mHeadsUpManager.getTopEntry());
+ assertEquals(0, mHeadsUpManager.getAllEntries().count());
+ assertFalse(mHeadsUpManager.hasHeadsUpNotifications());
+
+ // Add a notification.
+ mHeadsUpManager.showNotification(mEntry);
+
+ assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
+ assertEquals(mEntry, mHeadsUpManager.getTopEntry());
+ assertEquals(1, mHeadsUpManager.getAllEntries().count());
+ assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+
+ // Update the notification.
+ mHeadsUpManager.updateNotification(mEntry, false);
+
+ assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
+ assertEquals(mEntry, mHeadsUpManager.getTopEntry());
+ assertEquals(1, mHeadsUpManager.getAllEntries().count());
+ assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+
+ // Remove but defer, since the notification is visible on display.
+ mHeadsUpManager.removeNotification(mEntry.key, false);
+
+ assertEquals(mEntry, mHeadsUpManager.getEntry(mEntry.key));
+ assertEquals(mEntry, mHeadsUpManager.getTopEntry());
+ assertEquals(1, mHeadsUpManager.getAllEntries().count());
+ assertTrue(mHeadsUpManager.hasHeadsUpNotifications());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 99202f4..31442af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -84,9 +84,10 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -109,7 +110,7 @@
@Mock private UnlockMethodCache mUnlockMethodCache;
@Mock private KeyguardIndicationController mKeyguardIndicationController;
@Mock private NotificationStackScrollLayout mStackScroller;
- @Mock private HeadsUpManager mHeadsUpManager;
+ @Mock private HeadsUpManagerPhone mHeadsUpManager;
@Mock private SystemServicesProxy mSystemServicesProxy;
@Mock private NotificationPanelView mNotificationPanelView;
@Mock private IStatusBarService mBarService;
@@ -188,7 +189,8 @@
mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
mPowerManager, mNotificationPanelView, mBarService, mNotificationListener,
mNotificationLogger, mVisualStabilityManager, mViewHierarchyManager,
- mEntryManager, mScrimController, mFingerprintUnlockController);
+ mEntryManager, mScrimController, mFingerprintUnlockController,
+ mock(ActivityLaunchAnimator.class));
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mContext.getComponents();
mEntryManager.setUpForTest(mStatusBar, mStackScroller, mStatusBar, mHeadsUpManager,
@@ -586,14 +588,15 @@
static class TestableStatusBar extends StatusBar {
public TestableStatusBar(StatusBarKeyguardViewManager man,
UnlockMethodCache unlock, KeyguardIndicationController key,
- NotificationStackScrollLayout stack, HeadsUpManager hum,
+ NotificationStackScrollLayout stack, HeadsUpManagerPhone hum,
PowerManager pm, NotificationPanelView panelView,
IStatusBarService barService, NotificationListener notificationListener,
NotificationLogger notificationLogger,
VisualStabilityManager visualStabilityManager,
NotificationViewHierarchyManager viewHierarchyManager,
TestableNotificationEntryManager entryManager, ScrimController scrimController,
- FingerprintUnlockController fingerprintUnlockController) {
+ FingerprintUnlockController fingerprintUnlockController,
+ ActivityLaunchAnimator launchAnimator) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
mKeyguardIndicationController = key;
@@ -610,6 +613,7 @@
mEntryManager = entryManager;
mScrimController = scrimController;
mFingerprintUnlockController = fingerprintUnlockController;
+ mActivityLaunchAnimator = launchAnimator;
}
private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
@@ -646,7 +650,7 @@
public void setUpForTest(NotificationPresenter presenter,
NotificationListContainer listContainer,
Callback callback,
- HeadsUpManager headsUpManager,
+ HeadsUpManagerPhone headsUpManager,
NotificationData notificationData) {
super.setUpWithPresenter(presenter, listContainer, callback, headsUpManager);
mNotificationData = notificationData;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
index 1c010b6..d9673d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
@@ -61,4 +61,15 @@
Assert.assertFalse(mStackScroller.isDimmed());
}
+ @Test
+ public void testAntiBurnInOffset() {
+ final int burnInOffset = 30;
+ mStackScroller.setAntiBurnInOffsetX(burnInOffset);
+ mStackScroller.setDark(false /* dark */, false /* animated */, null /* touch */);
+ Assert.assertEquals(0 /* expected */, mStackScroller.getTranslationX(), 0.01 /* delta */);
+ mStackScroller.setDark(true /* dark */, false /* animated */, null /* touch */);
+ Assert.assertEquals(burnInOffset /* expected */, mStackScroller.getTranslationX(),
+ 0.01 /* delta */);
+ }
+
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
new file mode 100644
index 0000000..4888fb2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -0,0 +1,221 @@
+/*
+ * 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.volume;
+
+import static android.media.AudioManager.RINGER_MODE_NORMAL;
+import static android.media.AudioManager.RINGER_MODE_SILENT;
+import static android.media.AudioManager.RINGER_MODE_VIBRATE;
+import static android.media.AudioManager.STREAM_RING;
+
+import static com.android.systemui.volume.Events.DISMISS_REASON_UNKNOWN;
+import static com.android.systemui.volume.Events.SHOW_REASON_UNKNOWN;
+import static com.android.systemui.volume.VolumeDialogControllerImpl.STREAMS;
+
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.KeyguardManager;
+import android.media.AudioManager;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.VolumeDialogController;
+import com.android.systemui.plugins.VolumeDialogController.State;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Predicate;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class VolumeDialogImplTest extends SysuiTestCase {
+
+ VolumeDialogImpl mDialog;
+
+ @Mock
+ VolumeDialogController mController;
+
+ @Mock
+ KeyguardManager mKeyguard;
+
+ @Mock
+ AccessibilityManagerWrapper mAccessibilityMgr;
+
+ @Before
+ public void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mController = mDependency.injectMockDependency(VolumeDialogController.class);
+ mAccessibilityMgr = mDependency.injectMockDependency(AccessibilityManagerWrapper.class);
+ getContext().addMockSystemService(KeyguardManager.class, mKeyguard);
+
+ mDialog = new VolumeDialogImpl(getContext());
+ mDialog.init(0, null);
+ State state = createShellState();
+ mDialog.onStateChangedH(state);
+ }
+
+ private State createShellState() {
+ State state = new VolumeDialogController.State();
+ for (int i = AudioManager.STREAM_VOICE_CALL; i <= AudioManager.STREAM_ACCESSIBILITY; i++) {
+ VolumeDialogController.StreamState ss = new VolumeDialogController.StreamState();
+ ss.name = STREAMS.get(i);
+ ss.level = 1;
+ state.states.append(i, ss);
+ }
+ return state;
+ }
+
+ private void navigateViews(View view, Predicate<View> condition) {
+ if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) view;
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ navigateViews(viewGroup.getChildAt(i), condition);
+ }
+ } else {
+ String resourceName = null;
+ try {
+ resourceName = getContext().getResources().getResourceName(view.getId());
+ } catch (Exception e) {}
+ assertTrue("View " + resourceName != null ? resourceName : view.getId()
+ + " failed test", condition.test(view));
+ }
+ }
+
+ @Test
+ public void testContentDescriptions() {
+ mDialog.show(SHOW_REASON_UNKNOWN);
+ ViewGroup dialog = mDialog.getDialogView();
+
+ navigateViews(dialog, view -> {
+ if (view instanceof ImageView) {
+ return !TextUtils.isEmpty(view.getContentDescription());
+ } else {
+ return true;
+ }
+ });
+
+ mDialog.dismiss(DISMISS_REASON_UNKNOWN);
+ }
+
+ @Test
+ public void testNoDuplicationOfParentState() {
+ mDialog.show(SHOW_REASON_UNKNOWN);
+ ViewGroup dialog = mDialog.getDialogView();
+
+ navigateViews(dialog, view -> !view.isDuplicateParentStateEnabled());
+
+ mDialog.dismiss(DISMISS_REASON_UNKNOWN);
+ }
+
+ @Test
+ public void testNoClickableViewGroups() {
+ mDialog.show(SHOW_REASON_UNKNOWN);
+ ViewGroup dialog = mDialog.getDialogView();
+
+ navigateViews(dialog, view -> {
+ if (view instanceof ViewGroup) {
+ return !view.isClickable();
+ } else {
+ return true;
+ }
+ });
+
+ mDialog.dismiss(DISMISS_REASON_UNKNOWN);
+ }
+
+ @Test
+ public void testTristateToggle_withVibrator() {
+ when(mController.hasVibrator()).thenReturn(true);
+
+ State state = createShellState();
+ state.ringerModeInternal = RINGER_MODE_NORMAL;
+ mDialog.onStateChangedH(state);
+
+ mDialog.show(SHOW_REASON_UNKNOWN);
+ ViewGroup dialog = mDialog.getDialogView();
+
+ // click once, verify updates to vibrate
+ dialog.findViewById(R.id.ringer_icon).performClick();
+ verify(mController, times(1)).setRingerMode(RINGER_MODE_VIBRATE, false);
+
+ // fake the update back to the dialog with the new ringer mode
+ state = createShellState();
+ state.ringerModeInternal = RINGER_MODE_VIBRATE;
+ mDialog.onStateChangedH(state);
+
+ // click once, verify updates to silent
+ dialog.findViewById(R.id.ringer_icon).performClick();
+ verify(mController, times(1)).setRingerMode(RINGER_MODE_SILENT, false);
+ verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
+
+ // fake the update back to the dialog with the new ringer mode
+ state = createShellState();
+ state.states.get(STREAM_RING).level = 0;
+ state.ringerModeInternal = RINGER_MODE_SILENT;
+ mDialog.onStateChangedH(state);
+
+ // click once, verify updates to normal
+ dialog.findViewById(R.id.ringer_icon).performClick();
+ verify(mController, times(1)).setRingerMode(RINGER_MODE_NORMAL, false);
+ verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
+ }
+
+ @Test
+ public void testTristateToggle_withoutVibrator() {
+ when(mController.hasVibrator()).thenReturn(false);
+
+ State state = createShellState();
+ state.ringerModeInternal = RINGER_MODE_NORMAL;
+ mDialog.onStateChangedH(state);
+
+ mDialog.show(SHOW_REASON_UNKNOWN);
+ ViewGroup dialog = mDialog.getDialogView();
+
+ // click once, verify updates to silent
+ dialog.findViewById(R.id.ringer_icon).performClick();
+ verify(mController, times(1)).setRingerMode(RINGER_MODE_SILENT, false);
+ verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
+
+ // fake the update back to the dialog with the new ringer mode
+ state = createShellState();
+ state.states.get(STREAM_RING).level = 0;
+ state.ringerModeInternal = RINGER_MODE_SILENT;
+ mDialog.onStateChangedH(state);
+
+ // click once, verify updates to normal
+ dialog.findViewById(R.id.ringer_icon).performClick();
+ verify(mController, times(1)).setRingerMode(RINGER_MODE_NORMAL, false);
+ verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/ZenModePanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/ZenModePanelTest.java
index 0fdbfd1..4ab2063 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/ZenModePanelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/ZenModePanelTest.java
@@ -30,15 +30,18 @@
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.test.FlakyTest;
import android.view.LayoutInflater;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.ZenModeController;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+@Ignore
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ZenModePanelTest extends SysuiTestCase {
diff --git a/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java b/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java
old mode 100644
new mode 100755
index e970367..dc2707b
--- a/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java
+++ b/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java
@@ -22,11 +22,15 @@
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
+import android.os.Build;
import android.os.IBinder;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.util.Log;
@@ -216,7 +220,27 @@
intent.setClassName(mContext, lastapp.className);
intent.setComponent(new ComponentName(lastapp.packageName,
lastapp.className));
- if (mContext.startService(intent) == null) {
+ PackageManager pm = mContext.getPackageManager();
+ PowerManager powerManager =
+ (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ try {
+ ApplicationInfo appInfo = pm.getApplicationInfo(lastapp.packageName, 0);
+ if (appInfo.targetSdkVersion < Build.VERSION_CODES.O ||
+ powerManager.isIgnoringBatteryOptimizations(lastapp.packageName)) {
+ if (mContext.startService(intent) == null) {
+ Log.w(LOG_TAG, "invalid name " +
+ lastapp.packageName + "/" + lastapp.className);
+ return WapPushManagerParams.INVALID_RECEIVER_NAME;
+ }
+ } else {
+ if (mContext.startForegroundService(intent) == null) {
+ Log.w(LOG_TAG, "invalid name " +
+ lastapp.packageName + "/" + lastapp.className);
+ return WapPushManagerParams.INVALID_RECEIVER_NAME;
+ }
+ }
+
+ } catch (NameNotFoundException e) {
Log.w(LOG_TAG, "invalid name " +
lastapp.packageName + "/" + lastapp.className);
return WapPushManagerParams.INVALID_RECEIVER_NAME;
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
index 43bde88..a584a7f 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
@@ -47,6 +47,10 @@
<!-- Height of the status bar -->
<dimen name="status_bar_height">48dp</dimen>
+ <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
+ <dimen name="quick_qs_offset_height">48dp</dimen>
+ <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+ <dimen name="quick_qs_total_height">176dp</dimen>
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
index 9cf48d9..915e164 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
@@ -47,6 +47,10 @@
<!-- Height of the status bar -->
<dimen name="status_bar_height">48dp</dimen>
+ <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
+ <dimen name="quick_qs_offset_height">48dp</dimen>
+ <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+ <dimen name="quick_qs_total_height">176dp</dimen>
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
index 1ce41f0..b8e29da 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
@@ -47,6 +47,10 @@
<!-- Height of the status bar -->
<dimen name="status_bar_height">48dp</dimen>
+ <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
+ <dimen name="quick_qs_offset_height">48dp</dimen>
+ <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+ <dimen name="quick_qs_total_height">176dp</dimen>
</resources>
diff --git a/proto/src/gnss.proto b/proto/src/gnss.proto
index c54ddad..0168392 100644
--- a/proto/src/gnss.proto
+++ b/proto/src/gnss.proto
@@ -42,4 +42,20 @@
// Standard deviation of top 4 average CN0 (dB-Hz)
optional double standard_deviation_top_four_average_cn0_db_hz = 11;
-}
\ No newline at end of file
+
+ // Power metrics
+ optional PowerMetrics power_metrics = 12;
+}
+
+// Power metrics
+message PowerMetrics {
+
+ // Duration of power log (ms)
+ optional int64 logging_duration_ms = 1;
+
+ // Energy consumed (mAh)
+ optional double energy_consumed_mah = 2;
+
+ // Time spent in signal quality level (ms)
+ repeated int64 time_in_signal_quality_level_ms = 3;
+}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 03dfd46..01714cf 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5168,6 +5168,23 @@
// OS: P
ROTATION_SUGGESTION_SHOWN = 1288;
+ // An autofill service was bound using an unofficial(but still supported) permission.
+ // Package: Package of the autofill service
+ // OS: P
+ AUTOFILL_INVALID_PERMISSION = 1289;
+
+ // OPEN: QS Alarm tile shown
+ // ACTION: QS Alarm tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: P
+ QS_ALARM = 1290;
+
+ // OPEN: Settings->Connected Devices->USB->(click on details link)
+ // CATEGORY: SETTINGS
+ // OS: P
+ USB_DEVICE_DETAILS = 1291;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index db70184..08fdb97 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -200,6 +200,10 @@
// Package: android
NOTE_CARRIER_NETWORK_AVAILABLE = 46;
+ // Inform that USB is configured for Tethering
+ // Package: android
+ NOTE_USB_TETHER = 47;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index f5349df..f6a54af 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -373,6 +373,9 @@
// Wps connection metrics
optional WpsMetrics wps_metrics = 91;
+
+ // Wifi power statistics
+ optional WifiPowerStats wifi_power_stats = 92;
}
// Information that gets logged for every WiFi connection.
@@ -1134,3 +1137,22 @@
// Total number of wps cancellation
optional int32 num_wps_cancellation = 8;
}
+
+// Power stats for Wifi
+message WifiPowerStats {
+
+ // Duration of log (ms)
+ optional int64 logging_duration_ms = 1;
+
+ // Energy consumed by wifi (mAh)
+ optional double energy_consumed_mah = 2;
+
+ // Amount of time wifi is in idle (ms)
+ optional int64 idle_time_ms = 3;
+
+ // Amount of time wifi is in rx (ms)
+ optional int64 rx_time_ms = 4;
+
+ // Amount of time wifi is in tx (ms)
+ optional int64 tx_time_ms = 5;
+}
\ No newline at end of file
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 52d0e08e..b32be73 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -24,9 +24,8 @@
#include <utils/misc.h>
#include <inttypes.h>
-#include <android-base/macros.h>
#include <androidfw/Asset.h>
-#include <androidfw/AssetManager2.h>
+#include <androidfw/AssetManager.h>
#include <androidfw/ResourceTypes.h>
#include <android-base/macros.h>
@@ -1665,22 +1664,18 @@
static jlong
nFileA3DCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path)
{
- Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(_env, _assetMgr);
+ AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
if (mgr == nullptr) {
return 0;
}
AutoJavaStringToUTF8 str(_env, _path);
- std::unique_ptr<Asset> asset;
- {
- ScopedLock<AssetManager2> locked_mgr(*mgr);
- asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
- if (asset == nullptr) {
- return 0;
- }
+ Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+ if (asset == nullptr) {
+ return 0;
}
- jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromAsset((RsContext)con, asset.release());
+ jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromAsset((RsContext)con, asset);
return id;
}
@@ -1757,25 +1752,22 @@
nFontCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path,
jfloat fontSize, jint dpi)
{
- Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(_env, _assetMgr);
+ AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
if (mgr == nullptr) {
return 0;
}
AutoJavaStringToUTF8 str(_env, _path);
- std::unique_ptr<Asset> asset;
- {
- ScopedLock<AssetManager2> locked_mgr(*mgr);
- asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
- if (asset == nullptr) {
- return 0;
- }
+ Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+ if (asset == nullptr) {
+ return 0;
}
jlong id = (jlong)(uintptr_t)rsFontCreateFromMemory((RsContext)con,
str.c_str(), str.length(),
fontSize, dpi,
asset->getBuffer(false), asset->getLength());
+ delete asset;
return id;
}
diff --git a/services/art-profile b/services/art-profile
index 301918f..d2cde02 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -2134,15 +2134,15 @@
HPLcom/android/server/autofill/ui/AutoFillUI$AutoFillUiCallback;->requestShowFillUi(Landroid/view/autofill/AutofillId;IILandroid/view/autofill/IAutofillWindowPresenter;)V
HPLcom/android/server/autofill/ui/AutoFillUI$AutoFillUiCallback;->save()V
HPLcom/android/server/autofill/ui/AutoFillUI$AutoFillUiCallback;->startIntentSender(Landroid/content/IntentSender;)V
-HPLcom/android/server/backup/RefactoredBackupManagerService;->addPackageParticipantsLockedInner(Ljava/lang/String;Ljava/util/List;)V
-HPLcom/android/server/backup/RefactoredBackupManagerService;->allAgentPackages()Ljava/util/List;
-HPLcom/android/server/backup/RefactoredBackupManagerService;->dataChanged(Ljava/lang/String;)V
-HPLcom/android/server/backup/RefactoredBackupManagerService;->dataChangedImpl(Ljava/lang/String;)V
-HPLcom/android/server/backup/RefactoredBackupManagerService;->dataChangedImpl(Ljava/lang/String;Ljava/util/HashSet;)V
-HPLcom/android/server/backup/RefactoredBackupManagerService;->dataChangedTargets(Ljava/lang/String;)Ljava/util/HashSet;
-HPLcom/android/server/backup/RefactoredBackupManagerService;->dequeueFullBackupLocked(Ljava/lang/String;)V
-HPLcom/android/server/backup/RefactoredBackupManagerService;->readFullBackupSchedule()Ljava/util/ArrayList;
-HPLcom/android/server/backup/RefactoredBackupManagerService;->writeToJournalLocked(Ljava/lang/String;)V
+HPLcom/android/server/backup/BackupManagerService;->addPackageParticipantsLockedInner(Ljava/lang/String;Ljava/util/List;)V
+HPLcom/android/server/backup/BackupManagerService;->allAgentPackages()Ljava/util/List;
+HPLcom/android/server/backup/BackupManagerService;->dataChanged(Ljava/lang/String;)V
+HPLcom/android/server/backup/BackupManagerService;->dataChangedImpl(Ljava/lang/String;)V
+HPLcom/android/server/backup/BackupManagerService;->dataChangedImpl(Ljava/lang/String;Ljava/util/HashSet;)V
+HPLcom/android/server/backup/BackupManagerService;->dataChangedTargets(Ljava/lang/String;)Ljava/util/HashSet;
+HPLcom/android/server/backup/BackupManagerService;->dequeueFullBackupLocked(Ljava/lang/String;)V
+HPLcom/android/server/backup/BackupManagerService;->readFullBackupSchedule()Ljava/util/ArrayList;
+HPLcom/android/server/backup/BackupManagerService;->writeToJournalLocked(Ljava/lang/String;)V
HPLcom/android/server/backup/BackupManagerServiceInterface;->acknowledgeAdbBackupOrRestore(IZLjava/lang/String;Ljava/lang/String;Landroid/app/backup/IFullBackupRestoreObserver;)V
HPLcom/android/server/backup/BackupManagerServiceInterface;->adbBackup(Landroid/os/ParcelFileDescriptor;ZZZZZZZZ[Ljava/lang/String;)V
HPLcom/android/server/backup/BackupManagerServiceInterface;->adbRestore(Landroid/os/ParcelFileDescriptor;)V
@@ -9358,37 +9358,37 @@
PLcom/android/server/autofill/ui/AutoFillUI;->lambda$-com_android_server_autofill_ui_AutoFillUI_4826(Lcom/android/server/autofill/ui/AutoFillUI$AutoFillUiCallback;Ljava/lang/String;)V
PLcom/android/server/autofill/ui/AutoFillUI;->setCallback(Lcom/android/server/autofill/ui/AutoFillUI$AutoFillUiCallback;)V
PLcom/android/server/autofill/ui/OverlayControl;-><init>(Landroid/content/Context;)V
-PLcom/android/server/backup/RefactoredBackupManagerService$Lifecycle;-><init>(Landroid/content/Context;)V
-PLcom/android/server/backup/RefactoredBackupManagerService$Lifecycle;->onStart()V
-PLcom/android/server/backup/RefactoredBackupManagerService$Lifecycle;->onUnlockUser(I)V
-PLcom/android/server/backup/RefactoredBackupManagerService;-><init>(Landroid/content/Context;Lcom/android/server/backup/Trampoline;)V
-PLcom/android/server/backup/RefactoredBackupManagerService;->addPackageParticipantsLocked([Ljava/lang/String;)V
-PLcom/android/server/backup/RefactoredBackupManagerService;->backupSettingMigrated(I)Z
-PLcom/android/server/backup/RefactoredBackupManagerService;->enqueueFullBackup(Ljava/lang/String;J)V
-PLcom/android/server/backup/RefactoredBackupManagerService;->getCurrentTransport()Ljava/lang/String;
-PLcom/android/server/backup/RefactoredBackupManagerService;->initPackageTracking()V
-PLcom/android/server/backup/RefactoredBackupManagerService;->isBackupEnabled()Z
-PLcom/android/server/backup/RefactoredBackupManagerService;->parseLeftoverJournals()V
-PLcom/android/server/backup/RefactoredBackupManagerService;->readBackupEnableState(I)Z
-PLcom/android/server/backup/RefactoredBackupManagerService;->removePackageFromSetLocked(Ljava/util/HashSet;Ljava/lang/String;)V
-PLcom/android/server/backup/RefactoredBackupManagerService;->removePackageParticipantsLocked([Ljava/lang/String;I)V
-PLcom/android/server/backup/RefactoredBackupManagerService;->scheduleNextFullBackupJob(J)V
-PLcom/android/server/backup/RefactoredBackupManagerService;->selectBackupTransportAsync(Landroid/content/ComponentName;Landroid/app/backup/ISelectBackupTransportCallback;)V
-PLcom/android/server/backup/RefactoredBackupManagerService;->setBackupEnabled(Z)V
-PLcom/android/server/backup/RefactoredBackupManagerService;->updateStateForTransport(Ljava/lang/String;)V
-PLcom/android/server/backup/RefactoredBackupManagerService;->writeBackupEnableState(ZI)V
-PLcom/android/server/backup/RefactoredBackupManagerService;->writeFullBackupScheduleAsync()V
+PLcom/android/server/backup/BackupManagerService$Lifecycle;-><init>(Landroid/content/Context;)V
+PLcom/android/server/backup/BackupManagerService$Lifecycle;->onStart()V
+PLcom/android/server/backup/BackupManagerService$Lifecycle;->onUnlockUser(I)V
+PLcom/android/server/backup/BackupManagerService;-><init>(Landroid/content/Context;Lcom/android/server/backup/Trampoline;)V
+PLcom/android/server/backup/BackupManagerService;->addPackageParticipantsLocked([Ljava/lang/String;)V
+PLcom/android/server/backup/BackupManagerService;->backupSettingMigrated(I)Z
+PLcom/android/server/backup/BackupManagerService;->enqueueFullBackup(Ljava/lang/String;J)V
+PLcom/android/server/backup/BackupManagerService;->getCurrentTransport()Ljava/lang/String;
+PLcom/android/server/backup/BackupManagerService;->initPackageTracking()V
+PLcom/android/server/backup/BackupManagerService;->isBackupEnabled()Z
+PLcom/android/server/backup/BackupManagerService;->parseLeftoverJournals()V
+PLcom/android/server/backup/BackupManagerService;->readBackupEnableState(I)Z
+PLcom/android/server/backup/BackupManagerService;->removePackageFromSetLocked(Ljava/util/HashSet;Ljava/lang/String;)V
+PLcom/android/server/backup/BackupManagerService;->removePackageParticipantsLocked([Ljava/lang/String;I)V
+PLcom/android/server/backup/BackupManagerService;->scheduleNextFullBackupJob(J)V
+PLcom/android/server/backup/BackupManagerService;->selectBackupTransportAsync(Landroid/content/ComponentName;Landroid/app/backup/ISelectBackupTransportCallback;)V
+PLcom/android/server/backup/BackupManagerService;->setBackupEnabled(Z)V
+PLcom/android/server/backup/BackupManagerService;->updateStateForTransport(Ljava/lang/String;)V
+PLcom/android/server/backup/BackupManagerService;->writeBackupEnableState(ZI)V
+PLcom/android/server/backup/BackupManagerService;->writeFullBackupScheduleAsync()V
PLcom/android/server/backup/FullBackupJob;->schedule(Landroid/content/Context;J)V
PLcom/android/server/backup/KeyValueBackupJob;->cancel(Landroid/content/Context;)V
PLcom/android/server/backup/Trampoline;-><init>(Landroid/content/Context;)V
-PLcom/android/server/backup/Trampoline;->createRefactoredBackupManagerService()Lcom/android/server/backup/BackupManagerServiceInterface;
+PLcom/android/server/backup/Trampoline;->createBackupManagerService()Lcom/android/server/backup/BackupManagerServiceInterface;
PLcom/android/server/backup/Trampoline;->createService()Lcom/android/server/backup/BackupManagerServiceInterface;
PLcom/android/server/backup/Trampoline;->getCurrentTransport()Ljava/lang/String;
PLcom/android/server/backup/Trampoline;->getSuppressFile()Ljava/io/File;
PLcom/android/server/backup/Trampoline;->initialize(I)V
PLcom/android/server/backup/Trampoline;->isBackupDisabled()Z
PLcom/android/server/backup/Trampoline;->isBackupEnabled()Z
-PLcom/android/server/backup/Trampoline;->isRefactoredServiceEnabled()Z
+PLcom/android/server/backup/Trampoline;->isServiceEnabled()Z
PLcom/android/server/backup/Trampoline;->selectBackupTransportAsync(Landroid/content/ComponentName;Landroid/app/backup/ISelectBackupTransportCallback;)V
PLcom/android/server/backup/Trampoline;->setBackupEnabled(Z)V
PLcom/android/server/backup/TransportManager$RebindOnTimeoutHandler;-><init>(Lcom/android/server/backup/TransportManager;Landroid/os/Looper;)V
@@ -9422,13 +9422,13 @@
PLcom/android/server/backup/TransportManager;->registerAllTransports()V
PLcom/android/server/backup/TransportManager;->selectTransport(Ljava/lang/String;)Ljava/lang/String;
PLcom/android/server/backup/TransportManager;->tryBindTransport(Landroid/content/ComponentName;)V
-PLcom/android/server/backup/internal/BackupHandler;-><init>(Lcom/android/server/backup/RefactoredBackupManagerService;Landroid/os/Looper;)V
+PLcom/android/server/backup/internal/BackupHandler;-><init>(Lcom/android/server/backup/BackupManagerService;Landroid/os/Looper;)V
PLcom/android/server/backup/fullbackup/FullBackupEntry;->compareTo(Lcom/android/server/backup/fullbackup/FullBackupEntry;)I
PLcom/android/server/backup/fullbackup/FullBackupEntry;->compareTo(Ljava/lang/Object;)I
PLcom/android/server/backup/internal/BackupHandler;->handleMessage(Landroid/os/Message;)V
-PLcom/android/server/backup/internal/ProvisionedObserver;-><init>(Lcom/android/server/backup/RefactoredBackupManagerService;Landroid/os/Handler;)V
-PLcom/android/server/backup/internal/RunBackupReceiver;-><init>(Lcom/android/server/backup/RefactoredBackupManagerService;)V
-PLcom/android/server/backup/internal/RunInitializeReceiver;-><init>(Lcom/android/server/backup/RefactoredBackupManagerService;)V
+PLcom/android/server/backup/internal/ProvisionedObserver;-><init>(Lcom/android/server/backup/BackupManagerService;Landroid/os/Handler;)V
+PLcom/android/server/backup/internal/RunBackupReceiver;-><init>(Lcom/android/server/backup/BackupManagerService;)V
+PLcom/android/server/backup/internal/RunInitializeReceiver;-><init>(Lcom/android/server/backup/BackupManagerService;)V
PLcom/android/server/backup/utils/AppBackupUtils;->appGetsFullBackup(Landroid/content/pm/PackageInfo;)Z
PLcom/android/server/camera/CameraServiceProxy$1;-><init>(Lcom/android/server/camera/CameraServiceProxy;)V
PLcom/android/server/camera/CameraServiceProxy$2;-><init>(Lcom/android/server/camera/CameraServiceProxy;)V
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 0e2ca14..2b73b33 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -617,6 +617,23 @@
}
@Override
+ public String getUserDataId() throws RemoteException {
+ final int userId = UserHandle.getCallingUserId();
+
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ final UserData userData = service.getUserData(getCallingUid());
+ return userData == null ? null : userData.getId();
+ } else if (sVerbose) {
+ Slog.v(TAG, "getUserDataId(): no service for " + userId);
+ }
+ }
+
+ return null;
+ }
+
+ @Override
public void setUserData(UserData userData) throws RemoteException {
final int userId = UserHandle.getCallingUserId();
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 6b44fa5..6108afa 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -111,7 +111,7 @@
* until the user authenticates or it times out.
*/
final class Session implements RemoteFillService.FillServiceCallbacks, ViewState.Listener,
- AutoFillUI.AutoFillUiCallback {
+ AutoFillUI.AutoFillUiCallback, ValueFinder {
private static final String TAG = "AutofillSession";
private static final String EXTRA_REQUEST_ID = "android.service.autofill.extra.REQUEST_ID";
@@ -310,43 +310,56 @@
return ids;
}
- /**
- * Gets the value of a field, using either the {@code viewStates} or the {@code mContexts}, or
- * {@code null} when not found on either of them.
- */
+ @Override
@Nullable
- private String getValueAsString(@NonNull AutofillId id) {
- AutofillValue value = null;
+ public String findByAutofillId(@NonNull AutofillId id) {
synchronized (mLock) {
- final ViewState state = mViewStates.get(id);
- if (state == null) {
- if (sDebug) Slog.d(TAG, "getValue(): no view state for " + id);
- return null;
- }
- value = state.getCurrentValue();
- if (value == null) {
- if (sDebug) Slog.d(TAG, "getValue(): no current value for " + id);
- value = getValueFromContextsLocked(id);
- }
- }
- if (value != null) {
- if (value.isText()) {
- return value.getTextValue().toString();
- }
- if (value.isList()) {
- final CharSequence[] options = getAutofillOptionsFromContextsLocked(id);
- if (options != null) {
- final int index = value.getListValue();
- final CharSequence option = options[index];
- return option != null ? option.toString() : null;
- } else {
- Slog.w(TAG, "getValueAsString(): no autofill options for id " + id);
+ AutofillValue value = findValueLocked(id);
+ if (value != null) {
+ if (value.isText()) {
+ return value.getTextValue().toString();
+ }
+
+ if (value.isList()) {
+ final CharSequence[] options = getAutofillOptionsFromContextsLocked(id);
+ if (options != null) {
+ final int index = value.getListValue();
+ final CharSequence option = options[index];
+ return option != null ? option.toString() : null;
+ } else {
+ Slog.w(TAG, "findByAutofillId(): no autofill options for id " + id);
+ }
}
}
}
return null;
}
+ @Override
+ public AutofillValue findRawValueByAutofillId(AutofillId id) {
+ synchronized (mLock) {
+ return findValueLocked(id);
+ }
+ }
+
+ /**
+ * <p>Gets the value of a field, using either the {@code viewStates} or the {@code mContexts},
+ * or {@code null} when not found on either of them.
+ */
+ private AutofillValue findValueLocked(@NonNull AutofillId id) {
+ final ViewState state = mViewStates.get(id);
+ if (state == null) {
+ if (sDebug) Slog.d(TAG, "findValueLocked(): no view state for " + id);
+ return null;
+ }
+ AutofillValue value = state.getCurrentValue();
+ if (value == null) {
+ if (sDebug) Slog.d(TAG, "findValueLocked(): no current value for " + id);
+ value = getValueFromContextsLocked(id);
+ }
+ return value;
+ }
+
/**
* Updates values of the nodes in the context's structure so that:
* - proper node is focused
@@ -1355,14 +1368,12 @@
if (sDebug) {
Slog.d(TAG, "at least one field changed, validate fields for save UI");
}
- final ValueFinder valueFinder = (id) -> {return getValueAsString(id);};
-
final InternalValidator validator = saveInfo.getValidator();
if (validator != null) {
final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_SAVE_VALIDATION);
boolean isValid;
try {
- isValid = validator.isValid(valueFinder);
+ isValid = validator.isValid(this);
if (sDebug) Slog.d(TAG, validator + " returned " + isValid);
log.setType(isValid
? MetricsEvent.TYPE_SUCCESS
@@ -1404,10 +1415,13 @@
}
final AutofillValue datasetValue = datasetValues.get(id);
if (!currentValue.equals(datasetValue)) {
- if (sDebug) Slog.d(TAG, "found a change on id " + id);
+ if (sDebug) {
+ Slog.d(TAG, "found a dataset change on id " + id + ": from "
+ + datasetValue + " to " + currentValue);
+ }
continue datasets_loop;
}
- if (sVerbose) Slog.v(TAG, "no changes for id " + id);
+ if (sVerbose) Slog.v(TAG, "no dataset changes for id " + id);
}
if (sDebug) {
Slog.d(TAG, "ignoring Save UI because all fields match contents of "
@@ -1425,7 +1439,7 @@
final IAutoFillManagerClient client = getClient();
mPendingSaveUi = new PendingUi(mActivityToken, id, client);
getUiForShowing().showSaveUi(mService.getServiceLabel(), mService.getServiceIcon(),
- mService.getServicePackageName(), saveInfo, valueFinder,
+ mService.getServicePackageName(), saveInfo, this,
mComponentName.getPackageName(), this,
mPendingSaveUi);
if (client != null) {
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 5ee3cbf..5f112c7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -27,6 +27,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.service.autofill.Dataset;
+import android.service.autofill.Dataset.DatasetFieldFilter;
import android.service.autofill.FillResponse;
import android.text.TextUtils;
import android.util.Slog;
@@ -58,6 +59,7 @@
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
final class FillUi {
private static final String TAG = "FillUi";
@@ -185,7 +187,7 @@
final ArrayList<ViewItem> items = new ArrayList<>(totalItems);
if (header != null) {
if (sVerbose) Slog.v(TAG, "adding header");
- items.add(new ViewItem(null, null, null, header));
+ items.add(new ViewItem(null, null, false, null, header));
}
for (int i = 0; i < datasetCount; i++) {
final Dataset dataset = response.getDatasets().get(i);
@@ -205,21 +207,32 @@
Slog.e(TAG, "Error inflating remote views", e);
continue;
}
- final Pattern filter = dataset.getFilter(index);
+ final DatasetFieldFilter filter = dataset.getFilter(index);
+ Pattern filterPattern = null;
String valueText = null;
+ boolean filterable = true;
if (filter == null) {
final AutofillValue value = dataset.getFieldValues().get(index);
if (value != null && value.isText()) {
valueText = value.getTextValue().toString().toLowerCase();
}
+ } else {
+ filterPattern = filter.pattern;
+ if (filterPattern == null) {
+ if (sVerbose) {
+ Slog.v(TAG, "Explicitly disabling filter at id " + focusedViewId
+ + " for dataset #" + index);
+ }
+ filterable = false;
+ }
}
- items.add(new ViewItem(dataset, filter, valueText, view));
+ items.add(new ViewItem(dataset, filterPattern, filterable, valueText, view));
}
}
if (footer != null) {
if (sVerbose) Slog.v(TAG, "adding footer");
- items.add(new ViewItem(null, null, null, footer));
+ items.add(new ViewItem(null, null, false, null, footer));
}
mAdapter = new ItemsAdapter(items);
@@ -354,7 +367,7 @@
MeasureSpec.AT_MOST);
final int itemCount = mAdapter.getCount();
for (int i = 0; i < itemCount; i++) {
- View view = mAdapter.getItem(i).view;
+ final View view = mAdapter.getItem(i).view;
view.measure(widthMeasureSpec, heightMeasureSpec);
final int clampedMeasuredWidth = Math.min(view.getMeasuredWidth(), maxSize.x);
final int newContentWidth = Math.max(mContentWidth, clampedMeasuredWidth);
@@ -400,13 +413,62 @@
public final @Nullable Dataset dataset;
public final @NonNull View view;
public final @Nullable Pattern filter;
+ public final boolean filterable;
- ViewItem(@Nullable Dataset dataset, @Nullable Pattern filter, @Nullable String value,
- @NonNull View view) {
+ /**
+ * Default constructor.
+ *
+ * @param dataset dataset associated with the item or {@code null} if it's a header or
+ * footer (TODO(b/69796626): make @NonNull if header/footer is refactored out of the list)
+ * @param filter optional filter set by the service to determine how the item should be
+ * filtered
+ * @param filterable optional flag set by the service to indicate this item should not be
+ * filtered (typically used when the dataset has value but it's sensitive, like a password)
+ * @param value dataset value
+ * @param view dataset presentation.
+ */
+ ViewItem(@Nullable Dataset dataset, @Nullable Pattern filter, boolean filterable,
+ @Nullable String value, @NonNull View view) {
this.dataset = dataset;
this.value = value;
this.view = view;
this.filter = filter;
+ this.filterable = filterable;
+ }
+
+ /**
+ * Returns whether this item matches the value input by the user so it can be included
+ * in the filtered datasets.
+ */
+ public boolean matches(CharSequence filterText) {
+ if (TextUtils.isEmpty(filterText)) {
+ // Always show item when the user input is empty
+ return true;
+ }
+ if (!filterable) {
+ // Service explicitly disabled filtering using a null Pattern.
+ return false;
+ }
+ final String constraintLowerCase = filterText.toString().toLowerCase();
+ if (filter != null) {
+ // Uses pattern provided by service
+ return filter.matcher(constraintLowerCase).matches();
+ } else {
+ // Compares it with dataset value with dataset
+ return (value == null)
+ ? (dataset.getAuthentication() == null)
+ : value.toLowerCase().startsWith(constraintLowerCase);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ViewItem: [dataset=" + (dataset == null ? "null" : dataset.getId())
+ + ", value=" + (value == null ? "null" : value.length() + "_chars")
+ + ", filterable=" + filterable
+ + ", filter=" + (filter == null ? "null" : filter.pattern().length() + "_chars")
+ + ", view=" + view.getAutofillId()
+ + "]";
}
}
@@ -509,7 +571,7 @@
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mCallback: "); pw.println(mCallback != null);
pw.print(prefix); pw.print("mListView: "); pw.println(mListView);
- pw.print(prefix); pw.print("mAdapter: "); pw.println(mAdapter != null);
+ pw.print(prefix); pw.print("mAdapter: "); pw.println(mAdapter);
pw.print(prefix); pw.print("mFilterText: ");
Helper.printlnRedactedText(pw, mFilterText);
pw.print(prefix); pw.print("mContentWidth: "); pw.println(mContentWidth);
@@ -556,33 +618,14 @@
public Filter getFilter() {
return new Filter() {
@Override
- protected FilterResults performFiltering(CharSequence constraint) {
+ protected FilterResults performFiltering(CharSequence filterText) {
// No locking needed as mAllItems is final an immutable
+ final List<ViewItem> filtered = mAllItems.stream()
+ .filter((item) -> item.matches(filterText))
+ .collect(Collectors.toList());
final FilterResults results = new FilterResults();
- if (TextUtils.isEmpty(constraint)) {
- results.values = mAllItems;
- results.count = mAllItems.size();
- return results;
- }
- final List<ViewItem> filteredItems = new ArrayList<>();
- final String constraintLowerCase = constraint.toString().toLowerCase();
- final int itemCount = mAllItems.size();
- for (int i = 0; i < itemCount; i++) {
- final ViewItem item = mAllItems.get(i);
- final boolean matches;
- if (item.filter != null) {
- matches = item.filter.matcher(constraintLowerCase).matches();
- } else {
- matches = (item.value == null)
- ? (item.dataset.getAuthentication() == null)
- : item.value.toLowerCase().startsWith(constraintLowerCase);
- }
- if (matches) {
- filteredItems.add(item);
- }
- }
- results.values = filteredItems;
- results.count = filteredItems.size();
+ results.values = filtered;
+ results.count = filtered.size();
return results;
}
@@ -624,6 +667,11 @@
public View getView(int position, View convertView, ViewGroup parent) {
return getItem(position).view;
}
+
+ @Override
+ public String toString() {
+ return "ItemsAdapter: [all=" + mAllItems + ", filtered=" + mFilteredItems + "]";
+ }
}
private final class AnnounceFilterResult implements Runnable {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerConstants.java b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
index 1a54e95..99160c2 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerConstants.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
@@ -18,8 +18,6 @@
import android.app.AlarmManager;
import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
@@ -133,7 +131,7 @@
// group the calls of these methods in a block syncrhonized on
// a reference of this object.
public synchronized long getKeyValueBackupIntervalMilliseconds() {
- if (RefactoredBackupManagerService.DEBUG_SCHEDULING) {
+ if (BackupManagerService.DEBUG_SCHEDULING) {
Slog.v(TAG, "getKeyValueBackupIntervalMilliseconds(...) returns "
+ mKeyValueBackupIntervalMilliseconds);
}
@@ -141,7 +139,7 @@
}
public synchronized long getKeyValueBackupFuzzMilliseconds() {
- if (RefactoredBackupManagerService.DEBUG_SCHEDULING) {
+ if (BackupManagerService.DEBUG_SCHEDULING) {
Slog.v(TAG, "getKeyValueBackupFuzzMilliseconds(...) returns "
+ mKeyValueBackupFuzzMilliseconds);
}
@@ -149,7 +147,7 @@
}
public synchronized boolean getKeyValueBackupRequireCharging() {
- if (RefactoredBackupManagerService.DEBUG_SCHEDULING) {
+ if (BackupManagerService.DEBUG_SCHEDULING) {
Slog.v(TAG, "getKeyValueBackupRequireCharging(...) returns "
+ mKeyValueBackupRequireCharging);
}
@@ -157,7 +155,7 @@
}
public synchronized int getKeyValueBackupRequiredNetworkType() {
- if (RefactoredBackupManagerService.DEBUG_SCHEDULING) {
+ if (BackupManagerService.DEBUG_SCHEDULING) {
Slog.v(TAG, "getKeyValueBackupRequiredNetworkType(...) returns "
+ mKeyValueBackupRequiredNetworkType);
}
@@ -165,7 +163,7 @@
}
public synchronized long getFullBackupIntervalMilliseconds() {
- if (RefactoredBackupManagerService.DEBUG_SCHEDULING) {
+ if (BackupManagerService.DEBUG_SCHEDULING) {
Slog.v(TAG, "getFullBackupIntervalMilliseconds(...) returns "
+ mFullBackupIntervalMilliseconds);
}
@@ -173,14 +171,14 @@
}
public synchronized boolean getFullBackupRequireCharging() {
- if (RefactoredBackupManagerService.DEBUG_SCHEDULING) {
+ if (BackupManagerService.DEBUG_SCHEDULING) {
Slog.v(TAG, "getFullBackupRequireCharging(...) returns " + mFullBackupRequireCharging);
}
return mFullBackupRequireCharging;
}
public synchronized int getFullBackupRequiredNetworkType() {
- if (RefactoredBackupManagerService.DEBUG_SCHEDULING) {
+ if (BackupManagerService.DEBUG_SCHEDULING) {
Slog.v(TAG, "getFullBackupRequiredNetworkType(...) returns "
+ mFullBackupRequiredNetworkType);
}
@@ -191,7 +189,7 @@
* Returns an array of package names that should be notified whenever a backup finishes.
*/
public synchronized String[] getBackupFinishedNotificationReceivers() {
- if (RefactoredBackupManagerService.DEBUG_SCHEDULING) {
+ if (BackupManagerService.DEBUG_SCHEDULING) {
Slog.v(TAG, "getBackupFinishedNotificationReceivers(...) returns "
+ TextUtils.join(", ", mBackupFinishedNotificationReceivers));
}
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
similarity index 99%
rename from services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
rename to services/backup/java/com/android/server/backup/BackupManagerService.java
index dc20d31..3b80f55 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -38,7 +38,6 @@
import android.app.IActivityManager;
import android.app.IBackupAgent;
import android.app.PendingIntent;
-import android.app.admin.DevicePolicyManager;
import android.app.backup.BackupManager;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.FullBackup;
@@ -158,7 +157,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
-public class RefactoredBackupManagerService implements BackupManagerServiceInterface {
+public class BackupManagerService implements BackupManagerServiceInterface {
public static final String TAG = "BackupManagerService";
public static final boolean DEBUG = true;
@@ -628,7 +627,7 @@
* A BackupRestore task gets notified of ack/timeout for the operation via
* BackupRestoreTask#handleCancel, BackupRestoreTask#operationComplete and notifyAll called
* on the mCurrentOpLock.
- * {@link RefactoredBackupManagerService#waitUntilOperationComplete(int)} is
+ * {@link BackupManagerService#waitUntilOperationComplete(int)} is
* used in various places to 'wait' for notifyAll and detect change of pending state of an
* operation. So typically, an operation will be removed from this array by:
* - BackupRestoreTask#handleCancel and
@@ -739,7 +738,7 @@
// ----- Main service implementation -----
- public static RefactoredBackupManagerService create(
+ public static BackupManagerService create(
Context context,
Trampoline parent,
HandlerThread backupThread) {
@@ -772,7 +771,7 @@
// This dir on /cache is managed directly in init.rc
File dataDir = new File(Environment.getDownloadCacheDirectory(), "backup_stage");
- return new RefactoredBackupManagerService(
+ return new BackupManagerService(
context,
parent,
backupThread,
@@ -782,7 +781,7 @@
}
@VisibleForTesting
- RefactoredBackupManagerService(
+ BackupManagerService(
Context context,
Trampoline parent,
HandlerThread backupThread,
@@ -2639,7 +2638,7 @@
confIntent.setClassName("com.android.backupconfirm",
"com.android.backupconfirm.BackupRestoreConfirmation");
confIntent.putExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, token);
- confIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ confIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
mContext.startActivityAsUser(confIntent, UserHandle.SYSTEM);
} catch (ActivityNotFoundException e) {
return false;
diff --git a/services/backup/java/com/android/server/backup/FileMetadata.java b/services/backup/java/com/android/server/backup/FileMetadata.java
index 3d260cb..fe75041 100644
--- a/services/backup/java/com/android/server/backup/FileMetadata.java
+++ b/services/backup/java/com/android/server/backup/FileMetadata.java
@@ -16,7 +16,7 @@
package com.android.server.backup;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.BackupAgent;
import android.util.Slog;
diff --git a/services/backup/java/com/android/server/backup/FullBackupJob.java b/services/backup/java/com/android/server/backup/FullBackupJob.java
index b81a54d..82638b4 100644
--- a/services/backup/java/com/android/server/backup/FullBackupJob.java
+++ b/services/backup/java/com/android/server/backup/FullBackupJob.java
@@ -61,7 +61,7 @@
@Override
public boolean onStartJob(JobParameters params) {
mParams = params;
- Trampoline service = RefactoredBackupManagerService.getInstance();
+ Trampoline service = BackupManagerService.getInstance();
return service.beginFullBackup(this);
}
@@ -69,7 +69,7 @@
public boolean onStopJob(JobParameters params) {
if (mParams != null) {
mParams = null;
- Trampoline service = RefactoredBackupManagerService.getInstance();
+ Trampoline service = BackupManagerService.getInstance();
service.endFullBackup();
}
return false;
diff --git a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
index 42785be..4755877 100644
--- a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
@@ -4,8 +4,8 @@
import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_BACKUP_INTERVAL;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_BACKUP_INTERVAL;
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
@@ -80,7 +80,7 @@
mNewStateName = new File(mStateDir,
pkg + BACKUP_KEY_VALUE_NEW_STATE_FILENAME_SUFFIX);
- mManifestFile = new File(mDataDir, RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME);
+ mManifestFile = new File(mDataDir, BackupManagerService.BACKUP_MANIFEST_FILENAME);
}
public void backupOnePackage() throws IOException {
diff --git a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
index 5dfb0bc..d8411e2 100644
--- a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
+++ b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
@@ -71,7 +71,7 @@
if (delay <= 0) {
delay = interval + new Random().nextInt((int) fuzz);
}
- if (RefactoredBackupManagerService.DEBUG_SCHEDULING) {
+ if (BackupManagerService.DEBUG_SCHEDULING) {
Slog.v(TAG, "Scheduling k/v pass in " + (delay / 1000 / 60) + " minutes");
}
JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, sKeyValueJobService)
@@ -110,7 +110,7 @@
}
// Time to run a key/value backup!
- Trampoline service = RefactoredBackupManagerService.getInstance();
+ Trampoline service = BackupManagerService.getInstance();
try {
service.backupNow();
} catch (RemoteException e) {}
diff --git a/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java b/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java
index e29b7d5..b5db5e2 100644
--- a/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java
+++ b/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java
@@ -19,7 +19,6 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
-import com.android.server.backup.RefactoredBackupManagerService;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
@@ -47,7 +46,7 @@
final class ProcessedPackagesJournal {
private static final String TAG = "ProcessedPackagesJournal";
private static final String JOURNAL_FILE_NAME = "processed";
- private static final boolean DEBUG = RefactoredBackupManagerService.DEBUG || false;
+ private static final boolean DEBUG = BackupManagerService.DEBUG || false;
// using HashSet instead of ArraySet since we expect 100-500 elements range
@GuardedBy("mProcessedPackages")
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 540f5a1..2abeaa6 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -100,8 +100,8 @@
BACKUP_SUPPRESS_FILENAME);
}
- protected BackupManagerServiceInterface createRefactoredBackupManagerService() {
- return RefactoredBackupManagerService.create(mContext, this, mHandlerThread);
+ protected BackupManagerServiceInterface createBackupManagerService() {
+ return BackupManagerService.create(mContext, this, mHandlerThread);
}
// internal control API
@@ -117,7 +117,7 @@
synchronized (this) {
if (!mSuppressFile.exists()) {
- mService = createRefactoredBackupManagerService();
+ mService = createBackupManagerService();
} else {
Slog.i(TAG, "Backup inactive in user " + whichUser);
}
@@ -162,7 +162,7 @@
Slog.i(TAG, "Making backup "
+ (makeActive ? "" : "in") + "active in user " + userHandle);
if (makeActive) {
- mService = createRefactoredBackupManagerService();
+ mService = createBackupManagerService();
mSuppressFile.delete();
} else {
mService = null;
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
index d460f4d..0582aba 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -16,17 +16,17 @@
package com.android.server.backup.fullbackup;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_METADATA_FILENAME;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_METADATA_VERSION;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT;
-import static com.android.server.backup.RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
-import static com.android.server.backup.RefactoredBackupManagerService
+import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_FILENAME;
+import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_FILENAME;
+import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_VERSION;
+import static com.android.server.backup.BackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
+import static com.android.server.backup.BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
+import static com.android.server.backup.BackupManagerService
.TIMEOUT_SHARED_BACKUP_INTERVAL;
import android.app.ApplicationThreadConstants;
@@ -46,7 +46,7 @@
import com.android.server.AppWidgetBackupBridge;
import com.android.server.backup.BackupRestoreTask;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.utils.FullBackupUtils;
import java.io.BufferedOutputStream;
@@ -62,7 +62,7 @@
*/
public class FullBackupEngine {
- private RefactoredBackupManagerService backupManagerService;
+ private BackupManagerService backupManagerService;
OutputStream mOutput;
FullBackupPreflight mPreflightHook;
BackupRestoreTask mTimeoutMonitor;
@@ -163,7 +163,7 @@
}
}
- public FullBackupEngine(RefactoredBackupManagerService backupManagerService,
+ public FullBackupEngine(BackupManagerService backupManagerService,
OutputStream output,
FullBackupPreflight preflightHook, PackageInfo pkg,
boolean alsoApks, BackupRestoreTask timeoutMonitor, long quota, int opToken,
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
index da8a66a..40b6967 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
@@ -16,10 +16,10 @@
package com.android.server.backup.fullbackup;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
+import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
import android.app.backup.IBackupManager;
import android.content.ComponentName;
@@ -33,7 +33,7 @@
import android.util.Slog;
import com.android.internal.backup.IObbBackupService;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.utils.FullBackupUtils;
import java.io.IOException;
@@ -44,10 +44,10 @@
*/
public class FullBackupObbConnection implements ServiceConnection {
- private RefactoredBackupManagerService backupManagerService;
+ private BackupManagerService backupManagerService;
volatile IObbBackupService mService;
- public FullBackupObbConnection(RefactoredBackupManagerService backupManagerService) {
+ public FullBackupObbConnection(BackupManagerService backupManagerService) {
this.backupManagerService = backupManagerService;
mService = null;
}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java
index 37961f9..8f6923b 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java
@@ -16,7 +16,7 @@
package com.android.server.backup.fullbackup;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.IFullBackupRestoreObserver;
import android.os.RemoteException;
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index 19e601b..2e2d3eb 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -17,12 +17,12 @@
package com.android.server.backup.fullbackup;
import static com.android.server.backup.BackupPasswordManager.PBKDF_CURRENT;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_FILE_HEADER_MAGIC;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_FILE_VERSION;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.BACKUP_FILE_HEADER_MAGIC;
+import static com.android.server.backup.BackupManagerService.BACKUP_FILE_VERSION;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.IFullBackupRestoreObserver;
import android.content.pm.ApplicationInfo;
@@ -37,7 +37,7 @@
import com.android.server.AppWidgetBackupBridge;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.KeyValueAdbBackupEngine;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.utils.AppBackupUtils;
import com.android.server.backup.utils.PasswordUtils;
@@ -66,7 +66,7 @@
*/
public class PerformAdbBackupTask extends FullBackupTask implements BackupRestoreTask {
- private RefactoredBackupManagerService backupManagerService;
+ private BackupManagerService backupManagerService;
FullBackupEngine mBackupEngine;
final AtomicBoolean mLatch;
@@ -86,7 +86,7 @@
String mEncryptPassword;
private final int mCurrentOpToken;
- public PerformAdbBackupTask(RefactoredBackupManagerService backupManagerService,
+ public PerformAdbBackupTask(BackupManagerService backupManagerService,
ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets,
String curPassword, String encryptPassword, boolean doAllApps, boolean doSystem,
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index d04be12..f9c36699 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -16,13 +16,13 @@
package com.android.server.backup.fullbackup;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG_SCHEDULING;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_PENDING;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_BACKUP;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.DEBUG_SCHEDULING;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.OP_PENDING;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
import android.annotation.Nullable;
import android.app.IBackupAgent;
@@ -46,7 +46,7 @@
import com.android.server.EventLogTags;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.FullBackupJob;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.TransportManager;
import com.android.server.backup.internal.OnTaskFinishedListener;
import com.android.server.backup.internal.Operation;
@@ -95,7 +95,7 @@
*/
public class PerformFullTransportBackupTask extends FullBackupTask implements BackupRestoreTask {
public static PerformFullTransportBackupTask newWithCurrentTransport(
- RefactoredBackupManagerService backupManagerService,
+ BackupManagerService backupManagerService,
IFullBackupRestoreObserver observer,
String[] whichPackages,
boolean updateSchedule,
@@ -126,7 +126,7 @@
private static final String TAG = "PFTBT";
- private RefactoredBackupManagerService backupManagerService;
+ private BackupManagerService backupManagerService;
private final Object mCancelLock = new Object();
ArrayList<PackageInfo> mPackages;
@@ -147,7 +147,7 @@
private volatile boolean mCancelAll;
private final int mCurrentOpToken;
- public PerformFullTransportBackupTask(RefactoredBackupManagerService backupManagerService,
+ public PerformFullTransportBackupTask(BackupManagerService backupManagerService,
TransportClient transportClient,
IFullBackupRestoreObserver observer,
String[] whichPackages, boolean updateSchedule,
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index f29a9c2..3df6e47 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -16,12 +16,11 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_RESTORE_INTERVAL;
-import android.app.AlarmManager;
import android.app.backup.RestoreSet;
import android.content.Intent;
import android.os.Handler;
@@ -35,9 +34,9 @@
import com.android.internal.backup.IBackupTransport;
import com.android.server.EventLogTags;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.DataChangedJournal;
-import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.TransportManager;
import com.android.server.backup.fullbackup.PerformAdbBackupTask;
@@ -81,10 +80,9 @@
public static final int MSG_BACKUP_RESTORE_STEP = 20;
public static final int MSG_OP_COMPLETE = 21;
- private final RefactoredBackupManagerService backupManagerService;
+ private final BackupManagerService backupManagerService;
- public BackupHandler(
- RefactoredBackupManagerService backupManagerService, Looper looper) {
+ public BackupHandler(BackupManagerService backupManagerService, Looper looper) {
super(looper);
this.backupManagerService = backupManagerService;
}
diff --git a/services/backup/java/com/android/server/backup/internal/ClearDataObserver.java b/services/backup/java/com/android/server/backup/internal/ClearDataObserver.java
index d82c865..b0b8037 100644
--- a/services/backup/java/com/android/server/backup/internal/ClearDataObserver.java
+++ b/services/backup/java/com/android/server/backup/internal/ClearDataObserver.java
@@ -18,13 +18,13 @@
import android.content.pm.IPackageDataObserver;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
public class ClearDataObserver extends IPackageDataObserver.Stub {
- private RefactoredBackupManagerService backupManagerService;
+ private BackupManagerService backupManagerService;
- public ClearDataObserver(RefactoredBackupManagerService backupManagerService) {
+ public ClearDataObserver(BackupManagerService backupManagerService) {
this.backupManagerService = backupManagerService;
}
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index bacb357..0ba83cf 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -16,15 +16,15 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG_BACKUP_TRACE;
-import static com.android.server.backup.RefactoredBackupManagerService.KEY_WIDGET_STATE;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_PENDING;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_BACKUP;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT;
-import static com.android.server.backup.RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_BACKUP_INTERVAL;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.DEBUG_BACKUP_TRACE;
+import static com.android.server.backup.BackupManagerService.KEY_WIDGET_STATE;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.OP_PENDING;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
+import static com.android.server.backup.BackupManagerService.PACKAGE_MANAGER_SENTINEL;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_BACKUP_INTERVAL;
import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_OPERATION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTORE_STEP;
@@ -61,7 +61,7 @@
import com.android.server.backup.DataChangedJournal;
import com.android.server.backup.KeyValueBackupJob;
import com.android.server.backup.PackageManagerBackupAgent;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.transport.TransportUtils;
@@ -111,7 +111,7 @@
public class PerformBackupTask implements BackupRestoreTask {
private static final String TAG = "PerformBackupTask";
- private RefactoredBackupManagerService backupManagerService;
+ private BackupManagerService backupManagerService;
private final Object mCancelLock = new Object();
private ArrayList<BackupRequest> mQueue;
@@ -145,7 +145,7 @@
private volatile boolean mCancelAll;
- public PerformBackupTask(RefactoredBackupManagerService backupManagerService,
+ public PerformBackupTask(BackupManagerService backupManagerService,
TransportClient transportClient, String dirName,
ArrayList<BackupRequest> queue, @Nullable DataChangedJournal journal,
IBackupObserver observer, IBackupManagerMonitor monitor,
diff --git a/services/backup/java/com/android/server/backup/internal/PerformClearTask.java b/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
index 140d7286..d028104 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
@@ -16,26 +16,26 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.content.pm.PackageInfo;
import android.util.Slog;
import com.android.internal.backup.IBackupTransport;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.TransportManager;
import com.android.server.backup.transport.TransportClient;
import java.io.File;
public class PerformClearTask implements Runnable {
- private final RefactoredBackupManagerService mBackupManagerService;
+ private final BackupManagerService mBackupManagerService;
private final TransportManager mTransportManager;
private final TransportClient mTransportClient;
private final PackageInfo mPackage;
private final OnTaskFinishedListener mListener;
- PerformClearTask(RefactoredBackupManagerService backupManagerService,
+ PerformClearTask(BackupManagerService backupManagerService,
TransportClient transportClient, PackageInfo packageInfo,
OnTaskFinishedListener listener) {
mBackupManagerService = backupManagerService;
diff --git a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
index 2f2af98..88e0b7fc 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
@@ -16,7 +16,7 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.annotation.Nullable;
import android.app.AlarmManager;
@@ -30,7 +30,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
import com.android.server.EventLogTags;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.TransportManager;
import com.android.server.backup.transport.TransportClient;
@@ -49,7 +49,7 @@
* operation was successful then it's {@link BackupTransport#TRANSPORT_OK}.
*/
public class PerformInitializeTask implements Runnable {
- private final RefactoredBackupManagerService mBackupManagerService;
+ private final BackupManagerService mBackupManagerService;
private final TransportManager mTransportManager;
private final String[] mQueue;
private final File mBaseStateDir;
@@ -57,7 +57,7 @@
@Nullable private IBackupObserver mObserver;
public PerformInitializeTask(
- RefactoredBackupManagerService backupManagerService,
+ BackupManagerService backupManagerService,
String[] transportNames,
@Nullable IBackupObserver observer,
OnTaskFinishedListener listener) {
@@ -72,7 +72,7 @@
@VisibleForTesting
PerformInitializeTask(
- RefactoredBackupManagerService backupManagerService,
+ BackupManagerService backupManagerService,
TransportManager transportManager,
String[] transportNames,
@Nullable IBackupObserver observer,
diff --git a/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java b/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java
index 1001d3a..69720d4 100644
--- a/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java
+++ b/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java
@@ -16,22 +16,22 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.database.ContentObserver;
import android.os.Handler;
import android.util.Slog;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.KeyValueBackupJob;
-import com.android.server.backup.RefactoredBackupManagerService;
public class ProvisionedObserver extends ContentObserver {
- private RefactoredBackupManagerService backupManagerService;
+ private BackupManagerService backupManagerService;
public ProvisionedObserver(
- RefactoredBackupManagerService backupManagerService, Handler handler) {
+ BackupManagerService backupManagerService, Handler handler) {
super(handler);
this.backupManagerService = backupManagerService;
}
diff --git a/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java b/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
index f1fa7eb..6f574ca 100644
--- a/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
@@ -16,10 +16,10 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.RUN_BACKUP_ACTION;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.RUN_BACKUP_ACTION;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_BACKUP;
import android.app.PendingIntent;
@@ -29,13 +29,13 @@
import android.os.Message;
import android.util.Slog;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
public class RunBackupReceiver extends BroadcastReceiver {
- private RefactoredBackupManagerService backupManagerService;
+ private BackupManagerService backupManagerService;
- public RunBackupReceiver(RefactoredBackupManagerService backupManagerService) {
+ public RunBackupReceiver(BackupManagerService backupManagerService) {
this.backupManagerService = backupManagerService;
}
diff --git a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
index 6c160a3..548c580 100644
--- a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
@@ -16,9 +16,9 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.RUN_INITIALIZE_ACTION;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.RUN_INITIALIZE_ACTION;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -27,12 +27,12 @@
import android.util.ArraySet;
import android.util.Slog;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
public class RunInitializeReceiver extends BroadcastReceiver {
- private final RefactoredBackupManagerService mBackupManagerService;
+ private final BackupManagerService mBackupManagerService;
- public RunInitializeReceiver(RefactoredBackupManagerService backupManagerService) {
+ public RunInitializeReceiver(BackupManagerService backupManagerService) {
mBackupManagerService = backupManagerService;
}
diff --git a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
index 82106ec..238f7a0 100644
--- a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
+++ b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
@@ -16,8 +16,8 @@
package com.android.server.backup.restore;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_GET_RESTORE_SETS;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE;
@@ -35,9 +35,8 @@
import android.os.PowerManager;
import android.util.Slog;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.TransportManager;
-import com.android.server.backup.internal.BackupHandler;
import com.android.server.backup.internal.OnTaskFinishedListener;
import com.android.server.backup.params.RestoreGetSetsParams;
import com.android.server.backup.params.RestoreParams;
@@ -53,13 +52,13 @@
private final TransportManager mTransportManager;
private final String mTransportName;
- private final RefactoredBackupManagerService mBackupManagerService;
+ private final BackupManagerService mBackupManagerService;
private final String mPackageName;
public RestoreSet[] mRestoreSets = null;
boolean mEnded = false;
boolean mTimedOut = false;
- public ActiveRestoreSession(RefactoredBackupManagerService backupManagerService,
+ public ActiveRestoreSession(BackupManagerService backupManagerService,
String packageName, String transportName) {
mBackupManagerService = backupManagerService;
mPackageName = packageName;
@@ -399,11 +398,10 @@
// Posted to the handler to tear down a restore session in a cleanly synchronized way
public class EndRestoreRunnable implements Runnable {
- RefactoredBackupManagerService mBackupManager;
+ BackupManagerService mBackupManager;
ActiveRestoreSession mSession;
- public EndRestoreRunnable(RefactoredBackupManagerService manager,
- ActiveRestoreSession session) {
+ public EndRestoreRunnable(BackupManagerService manager, ActiveRestoreSession session) {
mBackupManager = manager;
mSession = session;
}
diff --git a/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java b/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
index 6353d1f..e4f3a9d 100644
--- a/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
+++ b/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
@@ -16,14 +16,14 @@
package com.android.server.backup.restore;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
import android.util.Slog;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.BackupRestoreTask;
-import com.android.server.backup.RefactoredBackupManagerService;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -34,11 +34,11 @@
public class AdbRestoreFinishedLatch implements BackupRestoreTask {
private static final String TAG = "AdbRestoreFinishedLatch";
- private RefactoredBackupManagerService backupManagerService;
+ private BackupManagerService backupManagerService;
final CountDownLatch mLatch;
private final int mCurrentOpToken;
- public AdbRestoreFinishedLatch(RefactoredBackupManagerService backupManagerService,
+ public AdbRestoreFinishedLatch(BackupManagerService backupManagerService,
int currentOpToken) {
this.backupManagerService = backupManagerService;
mLatch = new CountDownLatch(1);
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index 2c8b5b4..0ca4f25 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -16,15 +16,15 @@
package com.android.server.backup.restore;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_METADATA_FILENAME;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT;
-import static com.android.server.backup.RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL;
-import static com.android.server.backup.RefactoredBackupManagerService
+import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_FILENAME;
+import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_FILENAME;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_RESTORE_WAIT;
+import static com.android.server.backup.BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_RESTORE_INTERVAL;
+import static com.android.server.backup.BackupManagerService
.TIMEOUT_SHARED_BACKUP_INTERVAL;
import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
@@ -44,7 +44,7 @@
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.FileMetadata;
import com.android.server.backup.KeyValueAdbRestoreEngine;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.fullbackup.FullBackupObbConnection;
import com.android.server.backup.utils.BytesReadListener;
import com.android.server.backup.utils.FullBackupRestoreObserverUtils;
@@ -62,7 +62,7 @@
*/
public class FullRestoreEngine extends RestoreEngine {
- private final RefactoredBackupManagerService mBackupManagerService;
+ private final BackupManagerService mBackupManagerService;
// Task in charge of monitoring timeouts
private final BackupRestoreTask mMonitorTask;
@@ -119,7 +119,7 @@
final int mEphemeralOpToken;
- public FullRestoreEngine(RefactoredBackupManagerService backupManagerService,
+ public FullRestoreEngine(BackupManagerService backupManagerService,
BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer,
IBackupManagerMonitor monitor, PackageInfo onlyPackage, boolean allowApks,
boolean allowObbs, int ephemeralOpToken) {
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 54c2746..e576b3c 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -18,18 +18,18 @@
import static com.android.server.backup.BackupPasswordManager.PBKDF_CURRENT;
import static com.android.server.backup.BackupPasswordManager.PBKDF_FALLBACK;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_FILE_HEADER_MAGIC;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_FILE_VERSION;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_METADATA_FILENAME;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT;
-import static com.android.server.backup.RefactoredBackupManagerService.SETTINGS_PACKAGE;
-import static com.android.server.backup.RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL;
+import static com.android.server.backup.BackupManagerService.BACKUP_FILE_HEADER_MAGIC;
+import static com.android.server.backup.BackupManagerService.BACKUP_FILE_VERSION;
+import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_FILENAME;
+import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_FILENAME;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_RESTORE_WAIT;
+import static com.android.server.backup.BackupManagerService.SETTINGS_PACKAGE;
+import static com.android.server.backup.BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_RESTORE_INTERVAL;
import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
import android.app.ApplicationThreadConstants;
@@ -47,10 +47,10 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.FileMetadata;
import com.android.server.backup.KeyValueAdbRestoreEngine;
import com.android.server.backup.PackageManagerBackupAgent;
-import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.fullbackup.FullBackupObbConnection;
import com.android.server.backup.utils.BytesReadListener;
import com.android.server.backup.utils.FullBackupRestoreObserverUtils;
@@ -82,7 +82,7 @@
public class PerformAdbRestoreTask implements Runnable {
- private final RefactoredBackupManagerService mBackupManagerService;
+ private final BackupManagerService mBackupManagerService;
private final ParcelFileDescriptor mInputFile;
private final String mCurrentPassword;
private final String mDecryptPassword;
@@ -106,10 +106,10 @@
private final IBackupAgent mAgent;
private final int mToken;
- private final RefactoredBackupManagerService mBackupManagerService;
+ private final BackupManagerService mBackupManagerService;
RestoreFinishedRunnable(IBackupAgent agent, int token,
- RefactoredBackupManagerService backupManagerService) {
+ BackupManagerService backupManagerService) {
mAgent = agent;
mToken = token;
mBackupManagerService = backupManagerService;
@@ -139,7 +139,7 @@
// Packages we've already wiped data on when restoring their first file
private final HashSet<String> mClearedPackages = new HashSet<>();
- public PerformAdbRestoreTask(RefactoredBackupManagerService backupManagerService,
+ public PerformAdbRestoreTask(BackupManagerService backupManagerService,
ParcelFileDescriptor fd, String curPassword, String decryptPassword,
IFullBackupRestoreObserver observer, AtomicBoolean latch) {
this.mBackupManagerService = backupManagerService;
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 88f9ead..6eb9619 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -16,16 +16,16 @@
package com.android.server.backup.restore;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.KEY_WIDGET_STATE;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT;
-import static com.android.server.backup.RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL;
-import static com.android.server.backup.RefactoredBackupManagerService.SETTINGS_PACKAGE;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
-import static com.android.server.backup.RefactoredBackupManagerService
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.KEY_WIDGET_STATE;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.OP_TYPE_RESTORE_WAIT;
+import static com.android.server.backup.BackupManagerService.PACKAGE_MANAGER_SENTINEL;
+import static com.android.server.backup.BackupManagerService.SETTINGS_PACKAGE;
+import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService
.TIMEOUT_RESTORE_FINISHED_INTERVAL;
-import static com.android.server.backup.RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_RESTORE_INTERVAL;
import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTORE_STEP;
import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
@@ -60,7 +60,7 @@
import com.android.server.backup.BackupUtils;
import com.android.server.backup.PackageManagerBackupAgent;
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.TransportManager;
import com.android.server.backup.internal.OnTaskFinishedListener;
import com.android.server.backup.transport.TransportClient;
@@ -78,7 +78,7 @@
public class PerformUnifiedRestoreTask implements BackupRestoreTask {
- private RefactoredBackupManagerService backupManagerService;
+ private BackupManagerService backupManagerService;
private final TransportManager mTransportManager;
// Transport client we're working with to do the restore
private final TransportClient mTransportClient;
@@ -160,7 +160,7 @@
// Invariant: mWakelock is already held, and this task is responsible for
// releasing it at the end of the restore operation.
- public PerformUnifiedRestoreTask(RefactoredBackupManagerService backupManagerService,
+ public PerformUnifiedRestoreTask(BackupManagerService backupManagerService,
TransportClient transportClient, IRestoreObserver observer,
IBackupManagerMonitor monitor, long restoreSetToken, PackageInfo targetPackage,
int pmToken, boolean isFullSystemRestore, String[] filterSet,
diff --git a/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java b/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java
index 6c9a222..635b6d6 100644
--- a/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java
+++ b/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java
@@ -21,7 +21,7 @@
import android.os.RemoteException;
import com.android.server.backup.FileMetadata;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import java.io.IOException;
@@ -35,9 +35,9 @@
private final FileMetadata mInfo;
private final ParcelFileDescriptor mSocket;
private final int mToken;
- private final RefactoredBackupManagerService mBackupManagerService;
+ private final BackupManagerService mBackupManagerService;
- RestoreFileRunnable(RefactoredBackupManagerService backupManagerService, IBackupAgent agent,
+ RestoreFileRunnable(BackupManagerService backupManagerService, IBackupAgent agent,
FileMetadata info, ParcelFileDescriptor socket, int token) throws IOException {
mAgent = agent;
mInfo = info;
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index dbf1a826..6780563 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -16,9 +16,9 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.annotation.Nullable;
import android.app.backup.BackupTransport;
diff --git a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
index 010684e..b23781d 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
@@ -18,8 +18,8 @@
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.IBackupManagerMonitor;
diff --git a/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java b/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
index 3be1e33..c0cf2ef 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
@@ -16,8 +16,8 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.BackupProgress;
import android.app.backup.IBackupObserver;
diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
index 089109e..fa856ce 100644
--- a/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
@@ -16,7 +16,7 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.IFullBackupRestoreObserver;
import android.os.RemoteException;
diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
index a731fc9..d2ab099 100644
--- a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
@@ -16,8 +16,8 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_MANIFEST_VERSION;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_VERSION;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
diff --git a/services/backup/java/com/android/server/backup/utils/PasswordUtils.java b/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
index 9c5e283..a7eb644 100644
--- a/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
@@ -16,7 +16,7 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.util.Slog;
diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
index 632f5b5..10f0695 100644
--- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
@@ -16,8 +16,8 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.content.Context;
import android.content.IIntentReceiver;
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index ff9cb56..cc26ff8 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -34,14 +34,14 @@
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_MANIFEST_VERSION;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_METADATA_FILENAME;
-import static com.android.server.backup.RefactoredBackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
-import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
-import static com.android.server.backup.RefactoredBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_FILENAME;
+import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_VERSION;
+import static com.android.server.backup.BackupManagerService.BACKUP_METADATA_FILENAME;
+import static com.android.server.backup.BackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.BackupAgent;
import android.app.backup.BackupManagerMonitor;
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 342b48e..30dfee8 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlarmManager;
@@ -26,6 +27,8 @@
import android.app.IAlarmManager;
import android.app.IUidObserver;
import android.app.PendingIntent;
+import android.app.usage.UsageStatsManager;
+import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -57,6 +60,7 @@
import android.util.ArrayMap;
import android.util.KeyValueListParser;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -75,6 +79,7 @@
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Random;
@@ -120,6 +125,7 @@
static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
static final boolean DEBUG_WAKELOCK = localLOGV || false;
static final boolean DEBUG_BG_LIMIT = localLOGV || false;
+ static final boolean DEBUG_STANDBY = localLOGV || false;
static final boolean RECORD_ALARMS_IN_HISTORY = true;
static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
static final int ALARM_EVENT = 1;
@@ -140,6 +146,7 @@
AppOpsManager mAppOps;
DeviceIdleController.LocalService mLocalDeviceIdleController;
+ private UsageStatsManagerInternal mUsageStatsManagerInternal;
final Object mLock = new Object();
@@ -215,6 +222,14 @@
}
final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
+ interface Stats {
+ int REBATCH_ALL_ALARMS = 0;
+ }
+
+ private final StatLogger mStatLogger = new StatLogger(new String[] {
+ "REBATCH_ALL_ALARMS",
+ });
+
/**
* Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
*/
@@ -233,6 +248,8 @@
new SparseArray<>();
private final ForceAppStandbyTracker mForceAppStandbyTracker;
+ private boolean mAppStandbyParole;
+ private ArrayMap<Pair<String, Integer>, Long> mLastAlarmDeliveredForPackage = new ArrayMap<>();
/**
* All times are in milliseconds. These constants are kept synchronized with the system
@@ -249,13 +266,28 @@
= "allow_while_idle_whitelist_duration";
private static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
+ // Keys for specifying throttling delay based on app standby bucketing
+ private final String[] KEYS_APP_STANDBY_DELAY = {
+ "standby_active_delay",
+ "standby_working_delay",
+ "standby_frequent_delay",
+ "standby_rare_delay",
+ "standby_never_delay",
+ };
+
private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
-
private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
+ private final long[] DEFAULT_APP_STANDBY_DELAYS = {
+ 0, // Active
+ 6 * 60_000, // Working
+ 30 * 60_000, // Frequent
+ 2 * 60 * 60_000, // Rare
+ 10 * 24 * 60 * 60_000 // Never
+ };
// Minimum futurity of a new alarm
public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
@@ -276,6 +308,8 @@
// Direct alarm listener callback timeout
public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
+ public long[] APP_STANDBY_MIN_DELAYS = new long[DEFAULT_APP_STANDBY_DELAYS.length];
+
private ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
private long mLastAllowWhileIdleWhitelistDuration = -1;
@@ -328,7 +362,12 @@
DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
DEFAULT_LISTENER_TIMEOUT);
-
+ APP_STANDBY_MIN_DELAYS[0] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[0],
+ DEFAULT_APP_STANDBY_DELAYS[0]);
+ for (int i = 1; i < KEYS_APP_STANDBY_DELAY.length; i++) {
+ APP_STANDBY_MIN_DELAYS[i] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[i],
+ Math.max(APP_STANDBY_MIN_DELAYS[i-1], DEFAULT_APP_STANDBY_DELAYS[i]));
+ }
updateAllowWhileIdleWhitelistDurationLocked();
}
}
@@ -359,6 +398,12 @@
pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("=");
TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
pw.println();
+
+ for (int i = 0; i < KEYS_APP_STANDBY_DELAY.length; i++) {
+ pw.print(" "); pw.print(KEYS_APP_STANDBY_DELAY[i]); pw.print("=");
+ TimeUtils.formatDuration(APP_STANDBY_MIN_DELAYS[i], pw);
+ pw.println();
+ }
}
void dumpProto(ProtoOutputStream proto, long fieldId) {
@@ -618,9 +663,7 @@
}
PriorityClass packagePrio = a.priorityClass;
- String alarmPackage = (a.operation != null)
- ? a.operation.getCreatorPackage()
- : a.packageName;
+ String alarmPackage = a.sourcePackage;
if (packagePrio == null) packagePrio = mPriorities.get(alarmPackage);
if (packagePrio == null) {
packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
@@ -751,6 +794,7 @@
}
void rebatchAllAlarmsLocked(boolean doValidate) {
+ long start = mStatLogger.getTime();
final int oldCount =
getAlarmCount(mAlarmBatches) + ArrayUtils.size(mPendingWhileIdleAlarms);
final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches)
@@ -790,6 +834,7 @@
rescheduleKernelAlarmsLocked();
updateNextAlarmClockLocked();
+ mStatLogger.logDurationStat(Stats.REBATCH_ALL_ALARMS, start);
}
void reAddAlarmLocked(Alarm a, long nowElapsed, boolean doValidate) {
@@ -905,7 +950,7 @@
// Recurring alarms may have passed several alarm intervals while the
// alarm was kept pending. Send the appropriate trigger count.
if (alarm.repeatInterval > 0) {
- alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval;
+ alarm.count += (nowELAPSED - alarm.requestedWhenElapsed) / alarm.repeatInterval;
// Also schedule its next recurrence
final long delta = alarm.count * alarm.repeatInterval;
final long nextElapsed = alarm.whenElapsed + delta;
@@ -1228,6 +1273,8 @@
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mLocalDeviceIdleController
= LocalServices.getService(DeviceIdleController.LocalService.class);
+ mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
+ mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());
}
}
@@ -1377,6 +1424,51 @@
setImplLocked(a, false, doValidate);
}
+ private long getMinDelayForBucketLocked(int bucket) {
+ // Return the minimum time that should elapse before an app in the specified bucket
+ // can receive alarms again
+ if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) {
+ return mConstants.APP_STANDBY_MIN_DELAYS[4];
+ }
+ else if (bucket >= UsageStatsManager.STANDBY_BUCKET_RARE) {
+ return mConstants.APP_STANDBY_MIN_DELAYS[3];
+ }
+ else if (bucket >= UsageStatsManager.STANDBY_BUCKET_FREQUENT) {
+ return mConstants.APP_STANDBY_MIN_DELAYS[2];
+ }
+ else if (bucket >= UsageStatsManager.STANDBY_BUCKET_WORKING_SET) {
+ return mConstants.APP_STANDBY_MIN_DELAYS[1];
+ }
+ else return mConstants.APP_STANDBY_MIN_DELAYS[0];
+ }
+
+ private void adjustDeliveryTimeBasedOnStandbyBucketLocked(Alarm alarm) {
+ if (alarm.alarmClock != null || UserHandle.isCore(alarm.creatorUid)) {
+ return;
+ }
+ if (mAppStandbyParole) {
+ if (alarm.whenElapsed > alarm.requestedWhenElapsed) {
+ // We did throttle this alarm earlier, restore original requirements
+ alarm.whenElapsed = alarm.requestedWhenElapsed;
+ alarm.maxWhenElapsed = alarm.requestedMaxWhenElapsed;
+ }
+ return;
+ }
+ final String sourcePackage = alarm.sourcePackage;
+ final int sourceUserId = UserHandle.getUserId(alarm.creatorUid);
+ final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket(
+ sourcePackage, sourceUserId, SystemClock.elapsedRealtime());
+
+ final Pair<String, Integer> packageUser = Pair.create(sourcePackage, sourceUserId);
+ final long lastElapsed = mLastAlarmDeliveredForPackage.getOrDefault(packageUser, 0L);
+ if (lastElapsed > 0) {
+ final long minElapsed = lastElapsed + getMinDelayForBucketLocked(standbyBucket);
+ if (alarm.requestedWhenElapsed < minElapsed) {
+ alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
+ }
+ }
+ }
+
private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
// This is a special alarm that will put the system into idle until it goes off.
@@ -1428,6 +1520,7 @@
mAllowWhileIdleDispatches.add(ent);
}
}
+ adjustDeliveryTimeBasedOnStandbyBucketLocked(a);
int whichBatch = ((a.flags&AlarmManager.FLAG_STANDALONE) != 0)
? -1 : attemptCoalesceLocked(a.whenElapsed, a.maxWhenElapsed);
@@ -1655,6 +1748,9 @@
mForceAppStandbyTracker.dump(pw, " ");
pw.println();
+ pw.println(" App Standby Parole: " + mAppStandbyParole);
+ pw.println();
+
final long nowRTC = System.currentTimeMillis();
final long nowELAPSED = SystemClock.elapsedRealtime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
@@ -1753,6 +1849,15 @@
}
pw.println("]");
+ pw.println(" mLastAlarmDeliveredForPackage:");
+ for (int i = 0; i < mLastAlarmDeliveredForPackage.size(); i++) {
+ Pair<String, Integer> packageUser = mLastAlarmDeliveredForPackage.keyAt(i);
+ pw.print(" Package " + packageUser.first + ", User " + packageUser.second + ":");
+ TimeUtils.formatDuration(mLastAlarmDeliveredForPackage.valueAt(i), nowELAPSED, pw);
+ pw.println();
+ }
+ pw.println();
+
if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
pw.println();
pw.println(" Idle mode state:");
@@ -1913,6 +2018,8 @@
}
}
}
+ pw.println();
+ mStatLogger.dump(pw, " ");
if (RECORD_DEVICE_IDLE_ALARMS) {
pw.println();
@@ -2746,8 +2853,7 @@
// Don't block starting foreground components
return false;
}
- final String sourcePackage =
- (alarm.operation != null) ? alarm.operation.getCreatorPackage() : alarm.packageName;
+ final String sourcePackage = alarm.sourcePackage;
final int sourceUid = alarm.creatorUid;
return mForceAppStandbyTracker.areAlarmsRestricted(sourceUid, sourcePackage,
allowWhileIdle);
@@ -2856,7 +2962,7 @@
if (alarm.repeatInterval > 0) {
// this adjustment will be zero if we're late by
// less than one full repeat interval
- alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval;
+ alarm.count += (nowELAPSED - alarm.requestedWhenElapsed) / alarm.repeatInterval;
// Also schedule its next recurrence
final long delta = alarm.count * alarm.repeatInterval;
@@ -2925,11 +3031,14 @@
public final int uid;
public final int creatorUid;
public final String packageName;
+ public final String sourcePackage;
public int count;
public long when;
public long windowLength;
public long whenElapsed; // 'when' in the elapsed time base
public long maxWhenElapsed; // also in the elapsed time base
+ public final long requestedWhenElapsed; // original expiry time requested by the app
+ public final long requestedMaxWhenElapsed;
public long repeatInterval;
public PriorityClass priorityClass;
@@ -2943,8 +3052,10 @@
|| _type == AlarmManager.RTC_WAKEUP;
when = _when;
whenElapsed = _whenElapsed;
+ requestedWhenElapsed = _whenElapsed;
windowLength = _windowLength;
maxWhenElapsed = _maxWhen;
+ requestedMaxWhenElapsed = _maxWhen;
repeatInterval = _interval;
operation = _op;
listener = _rec;
@@ -2955,7 +3066,7 @@
alarmClock = _info;
uid = _uid;
packageName = _pkgName;
-
+ sourcePackage = (operation != null) ? operation.getCreatorPackage() : packageName;
creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
}
@@ -2980,9 +3091,7 @@
}
public boolean matches(String packageName) {
- return (operation != null)
- ? packageName.equals(operation.getTargetPackage())
- : packageName.equals(this.packageName);
+ return packageName.equals(sourcePackage);
}
@Override
@@ -2995,11 +3104,7 @@
sb.append(" when ");
sb.append(when);
sb.append(" ");
- if (operation != null) {
- sb.append(operation.getTargetPackage());
- } else {
- sb.append(packageName);
- }
+ sb.append(sourcePackage);
sb.append('}');
return sb.toString();
}
@@ -3009,6 +3114,8 @@
final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
pw.print(prefix); pw.print("tag="); pw.println(statsTag);
pw.print(prefix); pw.print("type="); pw.print(type);
+ pw.print(" requestedWhenELapsed="); TimeUtils.formatDuration(
+ requestedWhenElapsed, nowELAPSED, pw);
pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
nowELAPSED, pw);
pw.print(" when=");
@@ -3249,8 +3356,6 @@
// alarms, we need to merge them in to the list. note we don't
// just deliver them first because we generally want non-wakeup
// alarms delivered after wakeup alarms.
- rescheduleKernelAlarmsLocked();
- updateNextAlarmClockLocked();
if (mPendingNonWakeupAlarms.size() > 0) {
calculateDeliveryPriorities(mPendingNonWakeupAlarms);
triggerList.addAll(mPendingNonWakeupAlarms);
@@ -3262,6 +3367,27 @@
}
mPendingNonWakeupAlarms.clear();
}
+ boolean needRebatch = false;
+ final HashSet<String> triggerPackages = new HashSet<>();
+ for (int i = triggerList.size() - 1; i >= 0; i--) {
+ triggerPackages.add(triggerList.get(i).sourcePackage);
+ }
+ outer:
+ for (int i = 0; i < mAlarmBatches.size(); i++) {
+ final Batch batch = mAlarmBatches.get(i);
+ for (int j = 0; j < batch.size(); j++) {
+ if (triggerPackages.contains(batch.get(j))) {
+ needRebatch = true;
+ break outer;
+ }
+ }
+ }
+ if (needRebatch) {
+ rebatchAllAlarmsLocked(false);
+ } else {
+ rescheduleKernelAlarmsLocked();
+ updateNextAlarmClockLocked();
+ }
deliverAlarmsLocked(triggerList, nowELAPSED);
}
}
@@ -3318,6 +3444,8 @@
public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
public static final int LISTENER_TIMEOUT = 3;
public static final int REPORT_ALARMS_ACTIVE = 4;
+ public static final int APP_STANDBY_BUCKET_CHANGED = 5;
+ public static final int APP_STANDBY_PAROLE_CHANGED = 6;
public AlarmHandler() {
}
@@ -3363,6 +3491,19 @@
}
break;
+ case APP_STANDBY_PAROLE_CHANGED:
+ synchronized (mLock) {
+ mAppStandbyParole = (Boolean) msg.obj;
+ rebatchAllAlarmsLocked(false);
+ }
+ break;
+
+ case APP_STANDBY_BUCKET_CHANGED:
+ synchronized (mLock) {
+ rebatchAllAlarmsLocked(false);
+ }
+ break;
+
default:
// nope, just ignore it
break;
@@ -3489,6 +3630,13 @@
int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (userHandle >= 0) {
removeUserLocked(userHandle);
+ for (int i = mLastAlarmDeliveredForPackage.size() - 1; i >= 0; i--) {
+ final Pair<String, Integer> packageUser =
+ mLastAlarmDeliveredForPackage.keyAt(i);
+ if (packageUser.second == userHandle) {
+ mLastAlarmDeliveredForPackage.removeAt(i);
+ }
+ }
}
} else if (Intent.ACTION_UID_REMOVED.equals(action)) {
if (uid >= 0) {
@@ -3509,6 +3657,13 @@
}
}
if (pkgList != null && (pkgList.length > 0)) {
+ for (int i = mLastAlarmDeliveredForPackage.size() - 1; i >= 0; i--) {
+ Pair<String, Integer> packageUser = mLastAlarmDeliveredForPackage.keyAt(i);
+ if (ArrayUtils.contains(pkgList, packageUser.first)
+ && packageUser.second == UserHandle.getUserId(uid)) {
+ mLastAlarmDeliveredForPackage.removeAt(i);
+ }
+ }
for (String pkg : pkgList) {
if (uid >= 0) {
// package-removed case
@@ -3563,6 +3718,33 @@
}
};
+ /**
+ * Tracking of app assignments to standby buckets
+ */
+ final class AppStandbyTracker extends UsageStatsManagerInternal.AppIdleStateChangeListener {
+ @Override
+ public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
+ boolean idle, int bucket) {
+ if (DEBUG_STANDBY) {
+ Slog.d(TAG, "Package " + packageName + " for user " + userId + " now in bucket " +
+ bucket);
+ }
+ mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
+ mHandler.sendEmptyMessage(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
+ }
+
+ @Override
+ public void onParoleStateChanged(boolean isParoleOn) {
+ if (DEBUG_STANDBY) {
+ Slog.d(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
+ }
+ mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
+ mHandler.removeMessages(AlarmHandler.APP_STANDBY_PAROLE_CHANGED);
+ mHandler.obtainMessage(AlarmHandler.APP_STANDBY_PAROLE_CHANGED,
+ Boolean.valueOf(isParoleOn)).sendToTarget();
+ }
+ };
+
private final Listener mForceAppStandbyListener = new Listener() {
@Override
public void unblockAllUnrestrictedAlarms() {
@@ -3841,7 +4023,6 @@
alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
mInFlight.add(inflight);
mBroadcastRefCount++;
-
if (allowWhileIdle) {
// Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
@@ -3860,6 +4041,11 @@
mAllowWhileIdleDispatches.add(ent);
}
}
+ if (!UserHandle.isCore(alarm.creatorUid)) {
+ final Pair<String, Integer> packageUser = Pair.create(alarm.sourcePackage,
+ UserHandle.getUserId(alarm.creatorUid));
+ mLastAlarmDeliveredForPackage.put(packageUser, nowELAPSED);
+ }
final BroadcastStats bs = inflight.mBroadcastStats;
bs.count++;
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index f4675fd..894106a 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -39,6 +39,7 @@
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.ShellCommand;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManagerInternal;
@@ -248,7 +249,7 @@
public AppOpsService(File storagePath, Handler handler) {
LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
- mFile = new AtomicFile(storagePath);
+ mFile = new AtomicFile(storagePath, "appops");
mHandler = handler;
readState();
}
@@ -1666,8 +1667,6 @@
void writeState() {
synchronized (mFile) {
- List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
-
FileOutputStream stream;
try {
stream = mFile.startWrite();
@@ -1676,6 +1675,8 @@
return;
}
+ List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
+
try {
XmlSerializer out = new FastXmlSerializer();
out.setOutput(stream, StandardCharsets.UTF_8.name());
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index dc5f5a2..8265262 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -43,17 +43,17 @@
import android.hardware.health.V2_0.IHealth;
import android.hardware.health.V2_0.Result;
import android.os.BatteryManager;
-import android.os.BatteryManagerProto;
import android.os.BatteryManagerInternal;
import android.os.BatteryProperty;
import android.os.Binder;
+import android.os.DropBoxManager;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBatteryPropertiesListener;
import android.os.IBatteryPropertiesRegistrar;
import android.os.IBinder;
-import android.os.DropBoxManager;
+import android.os.OsProtoEnums;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -127,7 +127,7 @@
private static final String DUMPSYS_DATA_PATH = "/data/system/";
// This should probably be exposed in the API, though it's not critical
- private static final int BATTERY_PLUGGED_NONE = 0;
+ private static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0
private final Context mContext;
private final IBatteryStats mBatteryStats;
@@ -835,6 +835,9 @@
case "level":
mHealthInfo.batteryLevel = Integer.parseInt(value);
break;
+ case "counter":
+ mHealthInfo.batteryChargeCounter = Integer.parseInt(value);
+ break;
case "temp":
mHealthInfo.batteryTemperature = Integer.parseInt(value);
break;
@@ -921,13 +924,13 @@
synchronized (mLock) {
proto.write(BatteryServiceDumpProto.ARE_UPDATES_STOPPED, mUpdatesStopped);
- int batteryPluggedValue = BatteryManagerProto.PLUG_TYPE_NONE;
+ int batteryPluggedValue = OsProtoEnums.BATTERY_PLUGGED_NONE;
if (mHealthInfo.chargerAcOnline) {
- batteryPluggedValue = BatteryManagerProto.PLUG_TYPE_AC;
+ batteryPluggedValue = OsProtoEnums.BATTERY_PLUGGED_AC;
} else if (mHealthInfo.chargerUsbOnline) {
- batteryPluggedValue = BatteryManagerProto.PLUG_TYPE_USB;
+ batteryPluggedValue = OsProtoEnums.BATTERY_PLUGGED_USB;
} else if (mHealthInfo.chargerWirelessOnline) {
- batteryPluggedValue = BatteryManagerProto.PLUG_TYPE_WIRELESS;
+ batteryPluggedValue = OsProtoEnums.BATTERY_PLUGGED_WIRELESS;
}
proto.write(BatteryServiceDumpProto.PLUGGED, batteryPluggedValue);
proto.write(BatteryServiceDumpProto.MAX_CHARGING_CURRENT, mHealthInfo.maxChargingCurrent);
@@ -1164,6 +1167,20 @@
}
@Override
+ public int getBatteryChargeCounter() {
+ synchronized (mLock) {
+ return mHealthInfo.batteryChargeCounter;
+ }
+ }
+
+ @Override
+ public int getBatteryFullCharge() {
+ synchronized (mLock) {
+ return mHealthInfo.batteryFullCharge;
+ }
+ }
+
+ @Override
public boolean getBatteryLevelLow() {
synchronized (mLock) {
return mBatteryLevelLow;
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index a12c85a..44974ff 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -141,6 +141,8 @@
private boolean mHasNetworkLocation;
private Location mLastGenericLocation;
private Location mLastGpsLocation;
+ // Current locked state of the screen
+ private boolean mScreenLocked;
/** Device is currently active. */
private static final int STATE_ACTIVE = 0;
@@ -156,6 +158,7 @@
private static final int STATE_IDLE = 5;
/** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
private static final int STATE_IDLE_MAINTENANCE = 6;
+
private static String stateToString(int state) {
switch (state) {
case STATE_ACTIVE: return "ACTIVE";
@@ -547,6 +550,11 @@
"sms_temp_app_whitelist_duration";
private static final String KEY_NOTIFICATION_WHITELIST_DURATION =
"notification_whitelist_duration";
+ /**
+ * Whether to wait for the user to unlock the device before causing screen-on to
+ * exit doze. Default = true
+ */
+ private static final String KEY_WAIT_FOR_UNLOCK = "wait_for_unlock";
/**
* This is the time, after becoming inactive, that we go in to the first
@@ -765,6 +773,8 @@
*/
public long NOTIFICATION_WHITELIST_DURATION;
+ public boolean WAIT_FOR_UNLOCK;
+
private final ContentResolver mResolver;
private final boolean mSmallBatteryDevice;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -855,6 +865,7 @@
KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
NOTIFICATION_WHITELIST_DURATION = mParser.getDurationMillis(
KEY_NOTIFICATION_WHITELIST_DURATION, 30 * 1000L);
+ WAIT_FOR_UNLOCK = mParser.getBoolean(KEY_WAIT_FOR_UNLOCK, false);
}
}
@@ -962,6 +973,9 @@
pw.print(" "); pw.print(KEY_NOTIFICATION_WHITELIST_DURATION); pw.print("=");
TimeUtils.formatDuration(NOTIFICATION_WHITELIST_DURATION, pw);
pw.println();
+
+ pw.print(" "); pw.print(KEY_WAIT_FOR_UNLOCK); pw.print("=");
+ pw.println(WAIT_FOR_UNLOCK);
}
}
@@ -1340,6 +1354,19 @@
}
}
+ private ActivityManagerInternal.ScreenObserver mScreenObserver =
+ new ActivityManagerInternal.ScreenObserver() {
+ @Override
+ public void onAwakeStateChanged(boolean isAwake) { }
+
+ @Override
+ public void onKeyguardStateChanged(boolean isShowing) {
+ synchronized (DeviceIdleController.this) {
+ DeviceIdleController.this.keyguardShowingLocked(isShowing);
+ }
+ }
+ };
+
public DeviceIdleController(Context context) {
super(context);
mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
@@ -1406,6 +1433,7 @@
mNetworkConnected = true;
mScreenOn = true;
+ mScreenLocked = false;
// Start out assuming we are charging. If we aren't, we will at least get
// a battery update the next time the level drops.
mCharging = true;
@@ -1501,6 +1529,8 @@
mLocalActivityManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
+ mLocalActivityManager.registerScreenObserver(mScreenObserver);
+
passWhiteListToForceAppStandbyTrackerLocked();
updateInteractivityLocked();
}
@@ -1976,7 +2006,7 @@
}
} else if (screenOn) {
mScreenOn = true;
- if (!mForceIdle) {
+ if (!mForceIdle && (!mScreenLocked || !mConstants.WAIT_FOR_UNLOCK)) {
becomeActiveLocked("screen", Process.myUid());
}
}
@@ -1997,6 +2027,16 @@
}
}
+ void keyguardShowingLocked(boolean showing) {
+ if (DEBUG) Slog.i(TAG, "keyguardShowing=" + showing);
+ if (mScreenLocked != showing) {
+ mScreenLocked = showing;
+ if (mScreenOn && !mForceIdle && !mScreenLocked) {
+ becomeActiveLocked("unlocked", Process.myUid());
+ }
+ }
+ }
+
void scheduleReportActiveLocked(String activeReason, int activeUid) {
Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
mHandler.sendMessage(msg);
@@ -3308,6 +3348,7 @@
pw.print(" mForceIdle="); pw.println(mForceIdle);
pw.print(" mMotionSensor="); pw.println(mMotionSensor);
pw.print(" mScreenOn="); pw.println(mScreenOn);
+ pw.print(" mScreenLocked="); pw.println(mScreenLocked);
pw.print(" mNetworkConnected="); pw.println(mNetworkConnected);
pw.print(" mCharging="); pw.println(mCharging);
pw.print(" mMotionActive="); pw.println(mMotionListener.active);
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 732ac66..219facd 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -34,6 +34,7 @@
2731 power_soft_sleep_requested (savedwaketimems|2)
# Power save state has changed. See BatterySaverController.java for the details.
2739 battery_saver_mode (prevOffOrOn|1|5),(nowOffOrOn|1|5),(interactive|1|5),(features|3|5)
+27390 battery_saving_stats (batterySaver|1|5),(interactive|1|5),(doze|1|5),(delta_duration|2|3),(delta_battery_drain|1|6),(total_duration|2|3),(total_battery_drain|1|6)
#
# Leave IDs through 2740 for more power logs (2730 used by battery_discharge above)
diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/ForceAppStandbyTracker.java
index 257845e..7604044 100644
--- a/services/core/java/com/android/server/ForceAppStandbyTracker.java
+++ b/services/core/java/com/android/server/ForceAppStandbyTracker.java
@@ -22,6 +22,9 @@
import android.app.AppOpsManager.PackageOps;
import android.app.IActivityManager;
import android.app.IUidObserver;
+import android.app.usage.UsageStatsManager;
+import android.app.usage.UsageStatsManagerInternal;
+import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -42,6 +45,7 @@
import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;
+import android.util.SparseSetArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
@@ -50,6 +54,7 @@
import com.android.internal.app.IAppOpsService;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
+import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage;
import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;
import java.io.PrintWriter;
@@ -74,7 +79,7 @@
*/
public class ForceAppStandbyTracker {
private static final String TAG = "ForceAppStandbyTracker";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
@GuardedBy("ForceAppStandbyTracker.class")
private static ForceAppStandbyTracker sInstance;
@@ -89,6 +94,8 @@
AppOpsManager mAppOpsManager;
IAppOpsService mAppOpsService;
PowerManagerInternal mPowerManagerInternal;
+ StandbyTracker mStandbyTracker;
+ UsageStatsManagerInternal mUsageStatsManagerInternal;
private final MyHandler mHandler;
@@ -113,6 +120,12 @@
@GuardedBy("mLock")
private int[] mTempWhitelistedAppIds = mPowerWhitelistedAllAppIds;
+ /**
+ * Per-user packages that are in the EXEMPT bucket.
+ */
+ @GuardedBy("mLock")
+ private final SparseSetArray<String> mExemptedPackages = new SparseSetArray<>();
+
@GuardedBy("mLock")
final ArraySet<Listener> mListeners = new ArraySet<>();
@@ -146,6 +159,28 @@
@GuardedBy("mLock")
boolean mForcedAppStandbyEnabled;
+ interface Stats {
+ int UID_STATE_CHANGED = 0;
+ int RUN_ANY_CHANGED = 1;
+ int ALL_UNWHITELISTED = 2;
+ int ALL_WHITELIST_CHANGED = 3;
+ int TEMP_WHITELIST_CHANGED = 4;
+ int EXEMPT_CHANGED = 5;
+ int FORCE_ALL_CHANGED = 6;
+ int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 7;
+ }
+
+ private final StatLogger mStatLogger = new StatLogger(new String[] {
+ "UID_STATE_CHANGED",
+ "RUN_ANY_CHANGED",
+ "ALL_UNWHITELISTED",
+ "ALL_WHITELIST_CHANGED",
+ "TEMP_WHITELIST_CHANGED",
+ "EXEMPT_CHANGED",
+ "FORCE_ALL_CHANGED",
+ "FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED",
+ });
+
@VisibleForTesting
class FeatureFlagsObserver extends ContentObserver {
FeatureFlagsObserver() {
@@ -162,12 +197,11 @@
}
boolean isForcedAppStandbyEnabled() {
- return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
+ return injectGetGlobalSettingInt(Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
}
boolean isForcedAppStandbyForSmallBatteryEnabled() {
- return Settings.Global.getInt(mContext.getContentResolver(),
+ return injectGetGlobalSettingInt(
Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 0) == 1;
}
@@ -258,6 +292,17 @@
// only for affected app-ids.
updateAllJobs();
+
+ // Note when an app is just put in the temp whitelist, we do *not* drain pending alarms.
+ }
+
+ /**
+ * This is called when the EXEMPT bucket is updated.
+ */
+ private void onExemptChanged(ForceAppStandbyTracker sender) {
+ // This doesn't happen very often, so just re-evaluate all jobs / alarms.
+ updateAllJobs();
+ unblockAllUnrestrictedAlarms();
}
/**
@@ -346,11 +391,16 @@
mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
+ mUsageStatsManagerInternal = Preconditions.checkNotNull(
+ injectUsageStatsManagerInternal());
+
mFlagsObserver = new FeatureFlagsObserver();
mFlagsObserver.register();
mForcedAppStandbyEnabled = mFlagsObserver.isForcedAppStandbyEnabled();
mForceAllAppStandbyForSmallBattery =
mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
+ mStandbyTracker = new StandbyTracker();
+ mUsageStatsManagerInternal.addAppIdleStateChangeListener(mStandbyTracker);
try {
mIActivityManager.registerUidObserver(new UidObserver(),
@@ -408,10 +458,20 @@
}
@VisibleForTesting
+ UsageStatsManagerInternal injectUsageStatsManagerInternal() {
+ return LocalServices.getService(UsageStatsManagerInternal.class);
+ }
+
+ @VisibleForTesting
boolean isSmallBatteryDevice() {
return ActivityManager.isSmallBatteryDevice();
}
+ @VisibleForTesting
+ int injectGetGlobalSettingInt(String key, int def) {
+ return Settings.Global.getInt(mContext.getContentResolver(), key, def);
+ }
+
/**
* Update {@link #mRunAnyRestrictedPackages} with the current app ops state.
*/
@@ -604,6 +664,30 @@
}
}
+ final class StandbyTracker extends AppIdleStateChangeListener {
+ @Override
+ public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
+ int bucket) {
+ if (DEBUG) {
+ Slog.d(TAG,"onAppIdleStateChanged: " + packageName + " u" + userId
+ + (idle ? " idle" : " active") + " " + bucket);
+ }
+ final boolean changed;
+ if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) {
+ changed = mExemptedPackages.add(userId, packageName);
+ } else {
+ changed = mExemptedPackages.remove(userId, packageName);
+ }
+ if (changed) {
+ mHandler.notifyExemptChanged();
+ }
+ }
+
+ @Override
+ public void onParoleStateChanged(boolean isParoleOn) {
+ }
+ }
+
private Listener[] cloneListeners() {
synchronized (mLock) {
return mListeners.toArray(new Listener[mListeners.size()]);
@@ -619,6 +703,7 @@
private static final int MSG_FORCE_ALL_CHANGED = 6;
private static final int MSG_USER_REMOVED = 7;
private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
+ private static final int MSG_EXEMPT_CHANGED = 9;
public MyHandler(Looper looper) {
super(looper);
@@ -652,6 +737,10 @@
obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
}
+ public void notifyExemptChanged() {
+ obtainMessage(MSG_EXEMPT_CHANGED).sendToTarget();
+ }
+
public void doUserRemoved(int userId) {
obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
}
@@ -672,37 +761,57 @@
}
final ForceAppStandbyTracker sender = ForceAppStandbyTracker.this;
+ long start = mStatLogger.getTime();
switch (msg.what) {
case MSG_UID_STATE_CHANGED:
for (Listener l : cloneListeners()) {
l.onUidForegroundStateChanged(sender, msg.arg1);
}
+ mStatLogger.logDurationStat(Stats.UID_STATE_CHANGED, start);
return;
+
case MSG_RUN_ANY_CHANGED:
for (Listener l : cloneListeners()) {
l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj);
}
+ mStatLogger.logDurationStat(Stats.RUN_ANY_CHANGED, start);
return;
+
case MSG_ALL_UNWHITELISTED:
for (Listener l : cloneListeners()) {
l.onPowerSaveUnwhitelisted(sender);
}
+ mStatLogger.logDurationStat(Stats.ALL_UNWHITELISTED, start);
return;
+
case MSG_ALL_WHITELIST_CHANGED:
for (Listener l : cloneListeners()) {
l.onPowerSaveWhitelistedChanged(sender);
}
+ mStatLogger.logDurationStat(Stats.ALL_WHITELIST_CHANGED, start);
return;
+
case MSG_TEMP_WHITELIST_CHANGED:
for (Listener l : cloneListeners()) {
l.onTempPowerSaveWhitelistChanged(sender);
}
+ mStatLogger.logDurationStat(Stats.TEMP_WHITELIST_CHANGED, start);
return;
+
+ case MSG_EXEMPT_CHANGED:
+ for (Listener l : cloneListeners()) {
+ l.onExemptChanged(sender);
+ }
+ mStatLogger.logDurationStat(Stats.EXEMPT_CHANGED, start);
+ return;
+
case MSG_FORCE_ALL_CHANGED:
for (Listener l : cloneListeners()) {
l.onForceAllAppsStandbyChanged(sender);
}
+ mStatLogger.logDurationStat(Stats.FORCE_ALL_CHANGED, start);
return;
+
case MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED:
// Feature flag for forced app standby changed.
final boolean unblockAlarms;
@@ -715,7 +824,10 @@
l.unblockAllUnrestrictedAlarms();
}
}
+ mStatLogger.logDurationStat(
+ Stats.FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED, start);
return;
+
case MSG_USER_REMOVED:
handleUserRemoved(msg.arg1);
return;
@@ -742,6 +854,7 @@
mForegroundUids.removeAt(i);
}
}
+ mExemptedPackages.remove(removedUserId);
}
}
@@ -860,6 +973,10 @@
if (exemptOnBatterySaver) {
return false;
}
+ final int userId = UserHandle.getUserId(uid);
+ if (mExemptedPackages.contains(userId, packageName)) {
+ return false;
+ }
return mForceAllAppsStandby;
}
}
@@ -966,6 +1083,23 @@
pw.println(Arrays.toString(mTempWhitelistedAppIds));
pw.print(indent);
+ pw.println("Exempted packages:");
+ for (int i = 0; i < mExemptedPackages.size(); i++) {
+ pw.print(indent);
+ pw.print(" User ");
+ pw.print(mExemptedPackages.keyAt(i));
+ pw.println();
+
+ for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
+ pw.print(indent);
+ pw.print(" ");
+ pw.print(mExemptedPackages.valueAt(i, j));
+ pw.println();
+ }
+ }
+ pw.println();
+
+ pw.print(indent);
pw.println("Restricted packages:");
for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
pw.print(indent);
@@ -975,6 +1109,8 @@
pw.print(uidAndPackage.second);
pw.println();
}
+
+ mStatLogger.dump(pw, indent);
}
}
@@ -987,7 +1123,7 @@
isSmallBatteryDevice());
proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY,
mForceAllAppStandbyForSmallBattery);
- proto.write(ForceAppStandbyTrackerProto.IS_CHARGING, mIsPluggedIn);
+ proto.write(ForceAppStandbyTrackerProto.IS_PLUGGED_IN, mIsPluggedIn);
for (int i = 0; i < mForegroundUids.size(); i++) {
if (mForegroundUids.valueAt(i)) {
@@ -1004,6 +1140,18 @@
proto.write(ForceAppStandbyTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
}
+ for (int i = 0; i < mExemptedPackages.size(); i++) {
+ for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
+ final long token2 = proto.start(
+ ForceAppStandbyTrackerProto.EXEMPTED_PACKAGES);
+
+ proto.write(ExemptedPackage.USER_ID, mExemptedPackages.keyAt(i));
+ proto.write(ExemptedPackage.PACKAGE_NAME, mExemptedPackages.valueAt(i, j));
+
+ proto.end(token2);
+ }
+ }
+
for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
final long token2 = proto.start(
ForceAppStandbyTrackerProto.RUN_ANY_IN_BACKGROUND_RESTRICTED_PACKAGES);
@@ -1012,6 +1160,9 @@
uidAndPackage.second);
proto.end(token2);
}
+
+ mStatLogger.dumpProto(proto, ForceAppStandbyTrackerProto.STATS);
+
proto.end(token);
}
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 21137ad..fc91d0d 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -4306,7 +4306,7 @@
Slog.w(TAG, "Couldn't create dir.: " + inputMethodDir.getAbsolutePath());
}
final File subtypeFile = new File(inputMethodDir, ADDITIONAL_SUBTYPES_FILE_NAME);
- mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile);
+ mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile, "input-subtypes");
if (!subtypeFile.exists()) {
// If "subtypes.xml" doesn't exist, create a blank file.
writeAdditionalInputMethodSubtypes(
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index fe4ac6d7..a07a982 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -87,6 +87,7 @@
private static final String NETD_SERVICE_NAME = "netd";
private static final int[] DIRECTIONS =
new int[] {IpSecManager.DIRECTION_OUT, IpSecManager.DIRECTION_IN};
+ private static final String[] WILDCARD_ADDRESSES = new String[]{"0.0.0.0", "::"};
private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms
private static final int MAX_PORT_BIND_ATTEMPTS = 10;
@@ -413,12 +414,16 @@
.append(mTransformQuotaTracker)
.append(", mSocketQuotaTracker=")
.append(mSocketQuotaTracker)
+ .append(", mTunnelQuotaTracker=")
+ .append(mTunnelQuotaTracker)
.append(", mSpiRecords=")
.append(mSpiRecords)
.append(", mTransformRecords=")
.append(mTransformRecords)
.append(", mEncapSocketRecords=")
.append(mEncapSocketRecords)
+ .append(", mTunnelInterfaceRecords=")
+ .append(mTunnelInterfaceRecords)
.append("}")
.toString();
}
@@ -815,12 +820,14 @@
try {
mSrvConfig.getNetdInstance().removeVirtualTunnelInterface(mInterfaceName);
- for (int direction : DIRECTIONS) {
- int mark = (direction == IpSecManager.DIRECTION_IN) ? mIkey : mOkey;
- mSrvConfig
- .getNetdInstance()
- .ipSecDeleteSecurityPolicy(
- 0, direction, mLocalAddress, mRemoteAddress, mark, 0xffffffff);
+ for(String wildcardAddr : WILDCARD_ADDRESSES) {
+ for (int direction : DIRECTIONS) {
+ int mark = (direction == IpSecManager.DIRECTION_IN) ? mIkey : mOkey;
+ mSrvConfig
+ .getNetdInstance()
+ .ipSecDeleteSecurityPolicy(
+ 0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff);
+ }
}
} catch (ServiceSpecificException e) {
// FIXME: get the error code and throw is at an IOException from Errno Exception
@@ -1261,19 +1268,21 @@
.getNetdInstance()
.addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey);
- for (int direction : DIRECTIONS) {
- int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey;
+ for(String wildcardAddr : WILDCARD_ADDRESSES) {
+ for (int direction : DIRECTIONS) {
+ int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey;
- mSrvConfig
- .getNetdInstance()
- .ipSecAddSecurityPolicy(
+ mSrvConfig
+ .getNetdInstance()
+ .ipSecAddSecurityPolicy(
0, // Use 0 for reqId
direction,
- "",
- "",
+ wildcardAddr,
+ wildcardAddr,
0,
mark,
0xffffffff);
+ }
}
userRecord.mTunnelInterfaceRecords.put(
@@ -1646,16 +1655,18 @@
c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork());
// If outbound, also add SPI to the policy.
- mSrvConfig
- .getNetdInstance()
- .ipSecUpdateSecurityPolicy(
- 0, // Use 0 for reqId
- direction,
- "",
- "",
- transformInfo.getSpiRecord().getSpi(),
- mark,
- 0xffffffff);
+ for(String wildcardAddr : WILDCARD_ADDRESSES) {
+ mSrvConfig
+ .getNetdInstance()
+ .ipSecUpdateSecurityPolicy(
+ 0, // Use 0 for reqId
+ direction,
+ wildcardAddr,
+ wildcardAddr,
+ transformInfo.getSpiRecord().getSpi(),
+ mark,
+ 0xffffffff);
+ }
}
// Update SA with tunnel mark (ikey or okey based on direction)
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index bd93b179..1dd92f3 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1577,13 +1577,22 @@
}
/**
- * Returns all providers by name, including passive, but excluding
- * fused, also including ones that are not permitted to
- * be accessed by the calling activity or are currently disabled.
+ * Returns all providers by name, including passive and the ones that are not permitted to
+ * be accessed by the calling activity or are currently disabled, but excluding fused.
*/
@Override
public List<String> getAllProviders() {
- List<String> out = getProviders(null /*criteria*/, false /*enabledOnly*/);
+ ArrayList<String> out;
+ synchronized (mLock) {
+ out = new ArrayList<>(mProviders.size());
+ for (LocationProviderInterface provider : mProviders) {
+ String name = provider.getName();
+ if (LocationManager.FUSED_PROVIDER.equals(name)) {
+ continue;
+ }
+ out.add(name);
+ }
+ }
if (D) Log.d(TAG, "getAllProviders()=" + out);
return out;
}
@@ -2586,9 +2595,10 @@
// Check INTERACT_ACROSS_USERS permission if userId is not current user id.
checkInteractAcrossUsersPermission(userId);
- // Enable or disable all location providers
+ // Enable or disable all location providers. Fused provider and passive provider are
+ // excluded.
synchronized (mLock) {
- for(String provider : getAllProviders()) {
+ for(String provider : getAllProvidersForLocationSettings()) {
setProviderEnabledForUser(provider, enabled, userId);
}
}
@@ -2605,9 +2615,10 @@
// Check INTERACT_ACROSS_USERS permission if userId is not current user id.
checkInteractAcrossUsersPermission(userId);
- // If at least one location provider is enabled, return true
+ // If at least one location provider is enabled, return true. Fused provider and passive
+ // provider are excluded.
synchronized (mLock) {
- for (String provider : getAllProviders()) {
+ for (String provider : getAllProvidersForLocationSettings()) {
if (isProviderEnabledForUser(provider, userId)) {
return true;
}
@@ -2691,6 +2702,26 @@
}
/**
+ * Return all location providers except fused provider and passive provider. These two
+ * providers are not generating location by themselves, but only echo locations from other
+ * providers.
+ *
+ * @return All location providers except fused provider and passive provider, including
+ * providers that are not permitted to be accessed by the calling activity or are
+ * currently disabled.
+ */
+ private List<String> getAllProvidersForLocationSettings() {
+ List<String> providersForSettings = new ArrayList<>(mProviders.size());
+ for (String provider : getAllProviders()) {
+ if (provider.equals(LocationManager.PASSIVE_PROVIDER)) {
+ continue;
+ }
+ providersForSettings.add(provider);
+ }
+ return providersForSettings;
+ }
+
+ /**
* Read location provider status from Settings.Secure
*
* @param provider the location provider to query
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 3d7408e..2869114 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -372,15 +372,19 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+ long totalSize = 0;
pw.println("Pinned Files:");
synchronized(this) {
for (int i = 0; i < mPinnedFiles.size(); i++) {
pw.println(mPinnedFiles.get(i).mFilename);
+ totalSize += mPinnedFiles.get(i).mLength;
}
for (int i = 0; i < mPinnedCameraFiles.size(); i++) {
pw.println(mPinnedCameraFiles.get(i).mFilename);
+ totalSize += mPinnedCameraFiles.get(i).mLength;
}
}
+ pw.println("Total size: " + totalSize);
}
}
diff --git a/services/core/java/com/android/server/StatLogger.java b/services/core/java/com/android/server/StatLogger.java
new file mode 100644
index 0000000..f211731
--- /dev/null
+++ b/services/core/java/com/android/server/StatLogger.java
@@ -0,0 +1,108 @@
+/*
+ * 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.server;
+
+import android.os.SystemClock;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.StatLoggerProto.Event;
+
+import java.io.PrintWriter;
+
+/**
+ * Simple class to keep track of the number of times certain events happened and their durations for
+ * benchmarking.
+ *
+ * TODO Update shortcut service to switch to it.
+ *
+ * @hide
+ */
+public class StatLogger {
+ private final Object mLock = new Object();
+
+ private final int SIZE;
+
+ @GuardedBy("mLock")
+ private final int[] mCountStats;
+
+ @GuardedBy("mLock")
+ private final long[] mDurationStats;
+
+ private final String[] mLabels;
+
+ public StatLogger(String[] eventLabels) {
+ SIZE = eventLabels.length;
+ mCountStats = new int[SIZE];
+ mDurationStats = new long[SIZE];
+ mLabels = eventLabels;
+ }
+
+ /**
+ * Return the current time in the internal time unit.
+ * Call it before an event happens, and
+ * give it back to the {@link #logDurationStat(int, long)}} after the event.
+ */
+ public long getTime() {
+ return SystemClock.elapsedRealtimeNanos() / 1000;
+ }
+
+ /**
+ * @see {@link #getTime()}
+ */
+ public void logDurationStat(int eventId, long start) {
+ synchronized (mLock) {
+ mCountStats[eventId]++;
+ mDurationStats[eventId] += (getTime() - start);
+ }
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ synchronized (mLock) {
+ pw.print(prefix);
+ pw.println("Stats:");
+ for (int i = 0; i < SIZE; i++) {
+ pw.print(prefix);
+ pw.print(" ");
+ final int count = mCountStats[i];
+ final double durationMs = mDurationStats[i] / 1000.0;
+ pw.println(String.format("%s: count=%d, total=%.1fms, avg=%.3fms",
+ mLabels[i], count, durationMs,
+ (count == 0 ? 0 : ((double) durationMs) / count)));
+ }
+ }
+ }
+
+ public void dumpProto(ProtoOutputStream proto, long fieldId) {
+ synchronized (mLock) {
+ final long outer = proto.start(fieldId);
+
+ for (int i = 0; i < mLabels.length; i++) {
+ final long inner = proto.start(StatLoggerProto.EVENTS);
+
+ proto.write(Event.EVENT_ID, i);
+ proto.write(Event.LABEL, mLabels[i]);
+ proto.write(Event.COUNT, mCountStats[i]);
+ proto.write(Event.TOTAL_DURATION_MICROS, mDurationStats[i]);
+
+ proto.end(inner);
+ }
+
+ proto.end(outer);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 7361e70..84b93e3 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -36,6 +36,7 @@
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.KeyguardManager;
+import android.app.admin.SecurityLog;
import android.app.usage.StorageStatsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -50,7 +51,6 @@
import android.content.res.Configuration;
import android.content.res.ObbInfo;
import android.database.ContentObserver;
-import android.net.TrafficStats;
import android.net.Uri;
import android.os.Binder;
import android.os.DropBoxManager;
@@ -150,7 +150,6 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
-import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -1275,6 +1274,29 @@
mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
OBB_FLUSH_MOUNT_STATE, vol.path));
}
+ maybeLogMediaMount(vol, newState);
+ }
+
+ private void maybeLogMediaMount(VolumeInfo vol, int newState) {
+ if (!SecurityLog.isLoggingEnabled()) {
+ return;
+ }
+
+ final DiskInfo disk = vol.getDisk();
+ if (disk == null || (disk.flags & (DiskInfo.FLAG_SD | DiskInfo.FLAG_USB)) == 0) {
+ return;
+ }
+
+ // Sometimes there is a newline character.
+ final String label = disk.label != null ? disk.label.trim() : "";
+
+ if (newState == VolumeInfo.STATE_MOUNTED
+ || newState == VolumeInfo.STATE_MOUNTED_READ_ONLY) {
+ SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_MOUNT, vol.path, label);
+ } else if (newState == VolumeInfo.STATE_UNMOUNTED
+ || newState == VolumeInfo.STATE_BAD_REMOVAL) {
+ SecurityLog.writeEvent(SecurityLog.TAG_MEDIA_UNMOUNT, vol.path, label);
+ }
}
private void onMoveStatusLocked(int status) {
@@ -1386,7 +1408,7 @@
}
mSettingsFile = new AtomicFile(
- new File(Environment.getDataSystemDirectory(), "storage.xml"));
+ new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
synchronized (mLock) {
readSettingsLocked();
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 30432df..5215b6f 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -87,6 +87,7 @@
"media.metrics", // system/bin/mediametrics
"media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service
"com.android.bluetooth", // Bluetooth service
+ "statsd", // Stats daemon
};
public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList(
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 266abf8..2f7d4c1 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1042,14 +1042,20 @@
throw new SecurityException("Instant app " + r.appInfo.packageName
+ " does not have permission to create foreground services");
default:
- mAm.enforcePermission(
- android.Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE,
- r.app.pid, r.appInfo.uid, "startForeground");
+ try {
+ if (AppGlobals.getPackageManager().checkPermission(
+ android.Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE,
+ r.appInfo.packageName, UserHandle.getUserId(r.appInfo.uid))
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Instant app " + r.appInfo.packageName
+ + " does not have permission to create foreground"
+ + "services");
+ }
+ } catch (RemoteException e) {
+ throw new SecurityException("Failed to check instant app permission." ,
+ e);
+ }
}
- } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.P) {
- mAm.enforcePermission(
- android.Manifest.permission.FOREGROUND_SERVICE,
- r.app.pid, r.appInfo.uid, "startForeground");
}
if (r.fgRequired) {
if (DEBUG_SERVICE || DEBUG_BACKGROUND_CHECK) {
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 427ccba..220014f 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -50,7 +51,9 @@
import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.ConfigurationContainer;
+import com.android.server.wm.DisplayWindowController;
+import com.android.server.wm.WindowContainerListener;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -58,7 +61,8 @@
* Exactly one of these classes per Display in the system. Capable of holding zero or more
* attached {@link ActivityStack}s.
*/
-class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
+class ActivityDisplay extends ConfigurationContainer<ActivityStack>
+ implements WindowContainerListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_AM;
private static final String TAG_STACK = TAG + POSTFIX_STACK;
@@ -100,6 +104,8 @@
// Used in updating the display size
private Point mTmpDisplaySize = new Point();
+ private DisplayWindowController mWindowContainerController;
+
ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
mSupervisor = supervisor;
mDisplayId = displayId;
@@ -108,10 +114,15 @@
throw new IllegalStateException("Display does not exist displayId=" + displayId);
}
mDisplay = display;
+ mWindowContainerController = createWindowContainerController();
updateBounds();
}
+ protected DisplayWindowController createWindowContainerController() {
+ return new DisplayWindowController(mDisplayId, this);
+ }
+
void updateBounds() {
mDisplay.getSize(mTmpDisplaySize);
setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
@@ -148,7 +159,10 @@
private void positionChildAt(ActivityStack stack, int position) {
mStacks.remove(stack);
- mStacks.add(getTopInsertPosition(stack, position), stack);
+ final int insertPosition = getTopInsertPosition(stack, position);
+ mStacks.add(insertPosition, stack);
+ mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
+ insertPosition);
}
private int getTopInsertPosition(ActivityStack stack, int candidatePosition) {
@@ -661,6 +675,64 @@
&& (mSupervisor.mService.mRunningVoice == null);
}
+ /**
+ * @return the stack currently above the home stack. Can be null if there is no home stack, or
+ * the home stack is already on top.
+ */
+ ActivityStack getStackAboveHome() {
+ if (mHomeStack == null) {
+ // Skip if there is no home stack
+ return null;
+ }
+
+ final int stackIndex = mStacks.indexOf(mHomeStack) + 1;
+ return (stackIndex < mStacks.size()) ? mStacks.get(stackIndex) : null;
+ }
+
+ /**
+ * Adjusts the home stack behind the last visible stack in the display if necessary. Generally
+ * used in conjunction with {@link #moveHomeStackBehindStack}.
+ */
+ void moveHomeStackBehindBottomMostVisibleStack() {
+ if (mHomeStack == null) {
+ // Skip if there is no home stack
+ return;
+ }
+
+ // Move the home stack to the bottom to not affect the following visibility checks
+ positionChildAtBottom(mHomeStack);
+
+ // Find the next position where the homes stack should be placed
+ final int numStacks = mStacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
+ final ActivityStack stack = mStacks.get(stackNdx);
+ if (stack == mHomeStack) {
+ continue;
+ }
+ final int winMode = stack.getWindowingMode();
+ final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN ||
+ winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+ if (stack.shouldBeVisible(null) && isValidWindowingMode) {
+ // Move the home stack to behind this stack
+ positionChildAt(mHomeStack, Math.max(0, stackNdx - 1));
+ break;
+ }
+ }
+ }
+
+ /**
+ * Moves the home stack behind the given {@param stack} if possible. If {@param stack} is not
+ * currently in the display, then then the home stack is moved to the back. Generally used in
+ * conjunction with {@link #moveHomeStackBehindBottomMostVisibleStack}.
+ */
+ void moveHomeStackBehindStack(ActivityStack behindStack) {
+ if (behindStack == null) {
+ return;
+ }
+
+ positionChildAt(mHomeStack, Math.max(0, mStacks.indexOf(behindStack) - 1));
+ }
+
boolean isSleeping() {
return mSleeping;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 168baf0..5b8b691 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -26,7 +26,6 @@
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REMOVE_TASKS;
-import static android.Manifest.permission.START_ACTIVITY_AS_CALLER;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
@@ -39,6 +38,7 @@
import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
import static android.app.AppOpsManager.OP_ASSIST_STRUCTURE;
import static android.app.AppOpsManager.OP_NONE;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -86,6 +86,7 @@
import static android.os.Process.SCHED_FIFO;
import static android.os.Process.SCHED_OTHER;
import static android.os.Process.SCHED_RESET_ON_FORK;
+import static android.os.Process.SE_UID;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SIGNAL_QUIT;
import static android.os.Process.SIGNAL_USR1;
@@ -378,6 +379,7 @@
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;
import android.view.Gravity;
+import android.view.IRecentsAnimationRunner;
import android.view.LayoutInflater;
import android.view.RemoteAnimationDefinition;
import android.view.View;
@@ -451,6 +453,7 @@
import com.android.server.utils.PriorityDump;
import com.android.server.vr.VrManagerInternal;
import com.android.server.wm.PinnedStackWindowController;
+import com.android.server.wm.RecentsAnimationController;
import com.android.server.wm.WindowManagerService;
import dalvik.system.VMRuntime;
@@ -567,23 +570,6 @@
// could take much longer than usual.
static final int PROC_START_TIMEOUT_WITH_WRAPPER = 1200*1000;
- // Permission tokens are used to temporarily granted a trusted app the ability to call
- // #startActivityAsCaller. A client is expected to dump its token after this time has elapsed,
- // showing any appropriate error messages to the user.
- private static final long START_AS_CALLER_TOKEN_TIMEOUT =
- 10 * DateUtils.MINUTE_IN_MILLIS;
-
- // How long before the service actually expires a token. This is slightly longer than
- // START_AS_CALLER_TOKEN_TIMEOUT, to provide a buffer so clients will rarely encounter the
- // expiration exception.
- private static final long START_AS_CALLER_TOKEN_TIMEOUT_IMPL =
- START_AS_CALLER_TOKEN_TIMEOUT + 2*1000;
-
- // How long the service will remember expired tokens, for the purpose of providing error
- // messaging when a client uses an expired token.
- private static final long START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT =
- START_AS_CALLER_TOKEN_TIMEOUT_IMPL + 20 * DateUtils.MINUTE_IN_MILLIS;
-
// How long we allow a receiver to run before giving up on it.
static final int BROADCAST_FG_TIMEOUT = 10*1000;
static final int BROADCAST_BG_TIMEOUT = 60*1000;
@@ -692,13 +678,6 @@
final ArrayList<ActiveInstrumentation> mActiveInstrumentation = new ArrayList<>();
- // Activity tokens of system activities that are delegating their call to
- // #startActivityByCaller, keyed by the permissionToken granted to the delegate.
- final HashMap<IBinder, IBinder> mStartActivitySources = new HashMap<>();
-
- // Permission tokens that have expired, but we remember for error reporting.
- final ArrayList<IBinder> mExpiredStartAsCallerTokens = new ArrayList<>();
-
public final IntentFirewall mIntentFirewall;
// Whether we should show our dialogs (ANR, crash, etc) or just perform their
@@ -1652,7 +1631,7 @@
String mTrackAllocationApp = null;
String mNativeDebuggingApp = null;
- final long[] mTmpLong = new long[2];
+ final long[] mTmpLong = new long[3];
private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet();
@@ -1877,8 +1856,6 @@
static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
- static final int EXPIRE_START_AS_CALLER_TOKEN_MSG = 75;
- static final int FORGET_START_AS_CALLER_TOKEN_MSG = 76;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -2543,19 +2520,6 @@
}
}
} break;
- case EXPIRE_START_AS_CALLER_TOKEN_MSG: {
- synchronized (ActivityManagerService.this) {
- final IBinder permissionToken = (IBinder)msg.obj;
- mStartActivitySources.remove(permissionToken);
- mExpiredStartAsCallerTokens.add(permissionToken);
- }
- } break;
- case FORGET_START_AS_CALLER_TOKEN_MSG: {
- synchronized (ActivityManagerService.this) {
- final IBinder permissionToken = (IBinder)msg.obj;
- mExpiredStartAsCallerTokens.remove(permissionToken);
- }
- } break;
}
}
};
@@ -2610,22 +2574,24 @@
}
int num = 0;
- long[] tmp = new long[2];
+ long[] tmp = new long[3];
do {
ProcessRecord proc;
int procState;
+ int statType;
int pid;
long lastPssTime;
synchronized (ActivityManagerService.this) {
if (mPendingPssProcesses.size() <= 0) {
if (mTestPssMode || DEBUG_PSS) Slog.d(TAG_PSS,
- "Collected PSS of " + num + " processes in "
+ "Collected pss of " + num + " processes in "
+ (SystemClock.uptimeMillis() - start) + "ms");
mPendingPssProcesses.clear();
return;
}
proc = mPendingPssProcesses.remove(0);
procState = proc.pssProcState;
+ statType = proc.pssStatType;
lastPssTime = proc.lastPssTime;
if (proc.thread != null && procState == proc.setProcState
&& (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
@@ -2644,8 +2610,17 @@
if (pss != 0 && proc.thread != null && proc.setProcState == procState
&& proc.pid == pid && proc.lastPssTime == lastPssTime) {
num++;
- recordPssSampleLocked(proc, procState, pss, tmp[0], tmp[1],
- endTime-startTime, SystemClock.uptimeMillis());
+ ProcessList.commitNextPssTime(proc.procStateMemTracker);
+ recordPssSampleLocked(proc, procState, pss, tmp[0], tmp[1], tmp[2],
+ statType, endTime-startTime, SystemClock.uptimeMillis());
+ } else {
+ ProcessList.abortNextPssTime(proc.procStateMemTracker);
+ if (DEBUG_PSS) Slog.d(TAG_PSS, "Skipped pss collection of " + pid +
+ ": " + (proc.thread == null ? "NO_THREAD " : "") +
+ (proc.pid != pid ? "PID_CHANGED " : "") +
+ " initState=" + procState + " curState=" +
+ proc.setProcState + " " +
+ (proc.lastPssTime != lastPssTime ? "TIME_CHANGED" : ""));
}
}
}
@@ -2942,7 +2917,7 @@
}
});
- mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
+ mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "uri-grants");
mUserController = new UserController(this);
@@ -4830,54 +4805,16 @@
}
- /**
- * Only callable from the system. This token grants a temporary permission to call
- * #startActivityAsCallerWithToken. The token will time out after
- * START_AS_CALLER_TOKEN_TIMEOUT if it is not used.
- *
- * @param delegatorToken The Binder token referencing the system Activity that wants to delegate
- * the #startActivityAsCaller to another app. The "caller" will be the caller of this
- * activity's token, not the delegate's caller (which is probably the delegator itself).
- *
- * @return Returns a token that can be given to a "delegate" app that may call
- * #startActivityAsCaller
- */
@Override
- public IBinder requestStartActivityPermissionToken(IBinder delegatorToken) {
- int callingUid = Binder.getCallingUid();
- if (UserHandle.getAppId(callingUid) != SYSTEM_UID) {
- throw new SecurityException("Only the system process can request a permission token, " +
- "received request from uid: " + callingUid);
- }
- IBinder permissionToken = new Binder();
- synchronized (this) {
- mStartActivitySources.put(permissionToken, delegatorToken);
- }
+ public final int startActivityAsCaller(IApplicationThread caller, String callingPackage,
+ Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
+ int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, boolean ignoreTargetSecurity,
+ int userId) {
- Message expireMsg = mHandler.obtainMessage(EXPIRE_START_AS_CALLER_TOKEN_MSG,
- permissionToken);
- mHandler.sendMessageDelayed(expireMsg, START_AS_CALLER_TOKEN_TIMEOUT_IMPL);
-
- Message forgetMsg = mHandler.obtainMessage(FORGET_START_AS_CALLER_TOKEN_MSG,
- permissionToken);
- mHandler.sendMessageDelayed(forgetMsg, START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT);
-
- return permissionToken;
- }
-
- @Override
- public final int startActivityAsCaller(IApplicationThread caller,
- String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
- String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
- Bundle bOptions, IBinder permissionToken, boolean ignoreTargetSecurity, int userId) {
// This is very dangerous -- it allows you to perform a start activity (including
- // permission grants) as any app that may launch one of your own activities. So we only
- // allow this in two cases:
- // 1) The caller is an activity that is part of the core framework, and then only when it
- // is running as the system.
- // 2) The caller provides a valid permissionToken. Permission tokens are one-time use and
- // can only be requested by a system activity, which may then delegate this call to
- // another app.
+ // permission grants) as any app that may launch one of your own activities. So
+ // we will only allow this to be done from activities that are part of the core framework,
+ // and then only when they are running as the system.
final ActivityRecord sourceRecord;
final int targetUid;
final String targetPackage;
@@ -4885,47 +4822,17 @@
if (resultTo == null) {
throw new SecurityException("Must be called from an activity");
}
-
- final IBinder sourceToken;
- if (permissionToken != null) {
- // To even attempt to use a permissionToken, an app must also have this signature
- // permission.
- enforceCallingPermission(android.Manifest.permission.START_ACTIVITY_AS_CALLER,
- "startActivityAsCaller");
- // If called with a permissionToken, we want the sourceRecord from the delegator
- // activity that requested this token.
- sourceToken =
- mStartActivitySources.remove(permissionToken);
- if (sourceToken == null) {
- // Invalid permissionToken, check if it recently expired.
- if (mExpiredStartAsCallerTokens.contains(permissionToken)) {
- throw new SecurityException("Called with expired permission token: "
- + permissionToken);
- } else {
- throw new SecurityException("Called with invalid permission token: "
- + permissionToken);
- }
- }
- } else {
- // This method was called directly by the source.
- sourceToken = resultTo;
- }
-
- sourceRecord = mStackSupervisor.isInAnyStackLocked(sourceToken);
+ sourceRecord = mStackSupervisor.isInAnyStackLocked(resultTo);
if (sourceRecord == null) {
- throw new SecurityException("Called with bad activity token: " + sourceToken);
+ throw new SecurityException("Called with bad activity token: " + resultTo);
+ }
+ if (!sourceRecord.info.packageName.equals("android")) {
+ throw new SecurityException(
+ "Must be called from an activity that is declared in the android package");
}
if (sourceRecord.app == null) {
throw new SecurityException("Called without a process attached to activity");
}
-
- // Whether called directly or from a delegate, the source activity must be from the
- // android package.
- if (!sourceRecord.info.packageName.equals("android")) {
- throw new SecurityException("Must be called from an activity that is " +
- "declared in the android package");
- }
-
if (UserHandle.getAppId(sourceRecord.app.uid) != SYSTEM_UID) {
// This is still okay, as long as this activity is running under the
// uid of the original calling activity.
@@ -4936,7 +4843,6 @@
+ sourceRecord.launchedFromUid);
}
}
-
if (ignoreTargetSecurity) {
if (intent.getComponent() == null) {
throw new SecurityException(
@@ -5105,23 +5011,16 @@
}
@Override
- public int startRecentsActivity(IAssistDataReceiver assistDataReceiver, Bundle options,
- Bundle activityOptions, int userId) {
- if (!mRecentTasks.isCallerRecents(Binder.getCallingUid())) {
- String msg = "Permission Denial: startRecentsActivity() from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " not recent tasks package";
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
-
- final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options);
- final int recentsUid = mRecentTasks.getRecentsComponentUid();
- final ComponentName recentsComponent = mRecentTasks.getRecentsComponent();
- final String recentsPackage = recentsComponent.getPackageName();
+ public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver,
+ IRecentsAnimationRunner recentsAnimationRunner) {
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
+ final int recentsUid = mRecentTasks.getRecentsComponentUid();
+ final ComponentName recentsComponent = mRecentTasks.getRecentsComponent();
+ final String recentsPackage = recentsComponent.getPackageName();
+
// If provided, kick off the request for the assist data in the background before
// starting the activity
if (assistDataReceiver != null) {
@@ -5138,17 +5037,24 @@
recentsUid, recentsPackage);
}
- final Intent intent = new Intent();
- intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
- intent.setComponent(recentsComponent);
- intent.putExtras(options);
+ // Start a new recents animation
+ final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor,
+ mActivityStartController, mWindowManager, mUserController);
+ anim.startRecentsActivity(intent, recentsAnimationRunner, recentsComponent,
+ recentsUid);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
- return mActivityStartController.obtainStarter(intent, "startRecentsActivity")
- .setCallingUid(recentsUid)
- .setCallingPackage(recentsPackage)
- .setActivityOptions(safeOptions)
- .setMayWait(userId)
- .execute();
+ @Override
+ public void cancelRecentsAnimation() {
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "cancelRecentsAnimation()");
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ mWindowManager.cancelRecentsAnimation();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -6431,7 +6337,8 @@
if (!keepState) {
synchronized (this) {
// Remove all permissions granted from/to this package
- removeUriPermissionsForPackageLocked(packageName, resolvedUserId, true);
+ removeUriPermissionsForPackageLocked(packageName, resolvedUserId, true,
+ false);
}
// Reset notification state
@@ -6759,7 +6666,7 @@
if (proc.thread != null && proc.setAdj == oomAdj) {
// Record this for posterity if the process has been stable.
proc.baseProcessTracker.addPss(infos[i].getTotalPss(),
- infos[i].getTotalUss(), false,
+ infos[i].getTotalUss(), infos[i].getTotalRss(), false,
ProcessStats.ADD_PSS_EXTERNAL_SLOW, endTime-startTime,
proc.pkgList);
}
@@ -6782,7 +6689,7 @@
oomAdj = proc != null ? proc.setAdj : 0;
}
}
- long[] tmpUss = new long[1];
+ long[] tmpUss = new long[3];
long startTime = SystemClock.currentThreadTimeMillis();
pss[i] = Debug.getPss(pids[i], tmpUss, null);
long endTime = SystemClock.currentThreadTimeMillis();
@@ -6790,7 +6697,7 @@
synchronized (this) {
if (proc.thread != null && proc.setAdj == oomAdj) {
// Record this for posterity if the process has been stable.
- proc.baseProcessTracker.addPss(pss[i], tmpUss[0], false,
+ proc.baseProcessTracker.addPss(pss[i], tmpUss[0], tmpUss[2], false,
ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime, proc.pkgList);
}
}
@@ -7086,7 +6993,7 @@
}
// Remove transient permissions granted from/to this package/user
- removeUriPermissionsForPackageLocked(packageName, userId, false);
+ removeUriPermissionsForPackageLocked(packageName, userId, false, false);
if (doit) {
for (i = mBroadcastQueues.length - 1; i >= 0; i--) {
@@ -8914,20 +8821,6 @@
/**
* This can be called with or without the global lock held.
*/
- void enforcePermission(String permission, int pid, int uid, String func) {
- if (checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED) {
- return;
- }
-
- String msg = "Permission Denial: " + func + " from pid=" + pid + ", uid=" + uid
- + " requires " + permission;
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
-
- /**
- * This can be called with or without the global lock held.
- */
void enforceCallerIsRecentsOrHasPermission(String permission, String func) {
if (!mRecentTasks.isCallerRecents(Binder.getCallingUid())) {
enforceCallingPermission(permission, func);
@@ -9823,9 +9716,11 @@
* @param userHandle User to match, or {@link UserHandle#USER_ALL} to apply
* to all users.
* @param persistable If persistable grants should be removed.
+ * @param targetOnly When {@code true}, only remove permissions where the app is the target,
+ * not source.
*/
private void removeUriPermissionsForPackageLocked(
- String packageName, int userHandle, boolean persistable) {
+ String packageName, int userHandle, boolean persistable, boolean targetOnly) {
if (userHandle == UserHandle.USER_ALL && packageName == null) {
throw new IllegalArgumentException("Must narrow by either package or user");
}
@@ -9844,7 +9739,7 @@
final UriPermission perm = it.next();
// Only inspect grants matching package
- if (packageName == null || perm.sourcePkg.equals(packageName)
+ if (packageName == null || (!targetOnly && perm.sourcePkg.equals(packageName))
|| perm.targetPkg.equals(packageName)) {
// Hacky solution as part of fixing a security bug; ignore
// grants associated with DownloadManager so we don't have
@@ -9963,6 +9858,8 @@
private void writeGrantedUriPermissions() {
if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "writeGrantedUriPermissions()");
+ final long startTime = SystemClock.uptimeMillis();
+
// Snapshot permissions so we can persist without lock
ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList();
synchronized (this) {
@@ -9979,7 +9876,7 @@
FileOutputStream fos = null;
try {
- fos = mGrantFile.startWrite();
+ fos = mGrantFile.startWrite(startTime);
XmlSerializer out = new FastXmlSerializer();
out.setOutput(fos, StandardCharsets.UTF_8.name());
@@ -10096,8 +9993,7 @@
boolean persistChanged = false;
GrantUri grantUri = new GrantUri(userId, uri, false);
- UriPermission exactPerm = findUriPermissionLocked(callingUid,
- new GrantUri(userId, uri, false));
+ UriPermission exactPerm = findUriPermissionLocked(callingUid, grantUri);
UriPermission prefixPerm = findUriPermissionLocked(callingUid,
new GrantUri(userId, uri, true));
@@ -10280,7 +10176,9 @@
public void clearGrantedUriPermissions(String packageName, int userId) {
enforceCallingPermission(android.Manifest.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS,
"clearGrantedUriPermissions");
- removeUriPermissionsForPackageLocked(packageName, userId, true);
+ synchronized(this) {
+ removeUriPermissionsForPackageLocked(packageName, userId, true, true);
+ }
}
@Override
@@ -14532,7 +14430,7 @@
&& proc.setProcState >= ActivityManager.PROCESS_STATE_PERSISTENT) {
proc.notCachedSinceIdle = true;
proc.initialIdlePss = 0;
- proc.nextPssTime = ProcessList.computeNextPssTime(proc.setProcState, true,
+ proc.nextPssTime = ProcessList.computeNextPssTime(proc.setProcState, null,
mTestPssMode, isSleepingLocked(), now);
}
}
@@ -14845,6 +14743,8 @@
mUserController.sendUserSwitchBroadcasts(-1, currentUserId);
BinderInternal.nSetBinderProxyCountEnabled(true);
+ //STOPSHIP: Temporary BinderProxy Threshold for b/71353150
+ BinderInternal.nSetBinderProxyCountWatermarks(1500, 1200);
BinderInternal.setBinderProxyCountCallback(
new BinderInternal.BinderProxyLimitListener() {
@Override
@@ -18462,12 +18362,13 @@
final long myTotalPss = mi.getTotalPss();
final long myTotalUss = mi.getTotalUss();
+ final long myTotalRss = mi.getTotalRss();
final long myTotalSwapPss = mi.getTotalSwappedOutPss();
synchronized (this) {
if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
// Record this for posterity if the process has been stable.
- r.baseProcessTracker.addPss(myTotalPss, myTotalUss, true,
+ r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
reportType, endTime-startTime, r.pkgList);
}
}
@@ -18958,12 +18859,13 @@
final long myTotalPss = mi.getTotalPss();
final long myTotalUss = mi.getTotalUss();
+ final long myTotalRss = mi.getTotalRss();
final long myTotalSwapPss = mi.getTotalSwappedOutPss();
synchronized (this) {
if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
// Record this for posterity if the process has been stable.
- r.baseProcessTracker.addPss(myTotalPss, myTotalUss, true,
+ r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
reportType, endTime-startTime, r.pkgList);
}
}
@@ -20736,6 +20638,7 @@
case PHONE_UID:
case BLUETOOTH_UID:
case NFC_UID:
+ case SE_UID:
isCallerSystem = true;
break;
default:
@@ -20869,7 +20772,8 @@
intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
// Remove all permissions granted from/to this package
- removeUriPermissionsForPackageLocked(ssp, userId, true);
+ removeUriPermissionsForPackageLocked(ssp, userId, true,
+ false);
mRecentTasks.removeTasksByPackageName(ssp, userId);
@@ -23238,14 +23142,13 @@
* Record new PSS sample for a process.
*/
void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss, long swapPss,
- long pssDuration, long now) {
+ long rss, int statType, long pssDuration, long now) {
EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024,
- swapPss * 1024);
+ swapPss * 1024, rss * 1024, statType, procState, pssDuration);
proc.lastPssTime = now;
- proc.baseProcessTracker.addPss(pss, uss, true, ProcessStats.ADD_PSS_INTERNAL,
- pssDuration, proc.pkgList);
+ proc.baseProcessTracker.addPss(pss, uss, rss, true, statType, pssDuration, proc.pkgList);
if (DEBUG_PSS) Slog.d(TAG_PSS,
- "PSS of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
+ "pss of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
+ " state=" + ProcessList.makeProcStateString(procState));
if (proc.initialIdlePss == 0) {
proc.initialIdlePss = pss;
@@ -23344,8 +23247,9 @@
if (mPendingPssProcesses.size() == 0) {
mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
}
- if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting PSS of: " + proc);
+ if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of: " + proc);
proc.pssProcState = procState;
+ proc.pssStatType = ProcessStats.ADD_PSS_INTERNAL_SINGLE;
mPendingPssProcesses.add(proc);
}
@@ -23360,7 +23264,7 @@
return;
}
}
- if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting PSS of all procs! memLowered=" + memLowered);
+ if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of all procs! memLowered=" + memLowered);
mLastFullPssTime = now;
mFullPssPending = true;
mPendingPssProcesses.ensureCapacity(mLruProcesses.size());
@@ -23373,8 +23277,10 @@
}
if (memLowered || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) {
app.pssProcState = app.setProcState;
- app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
- mTestPssMode, isSleepingLocked(), now);
+ app.pssStatType = always ? ProcessStats.ADD_PSS_INTERNAL_ALL_POLL
+ : ProcessStats.ADD_PSS_INTERNAL_ALL_MEM;
+ app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
+ app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
mPendingPssProcesses.add(app);
}
}
@@ -23741,16 +23647,16 @@
long startTime = SystemClock.currentThreadTimeMillis();
long pss = Debug.getPss(app.pid, mTmpLong, null);
long endTime = SystemClock.currentThreadTimeMillis();
- recordPssSampleLocked(app, app.curProcState, pss, endTime-startTime,
- mTmpLong[0], mTmpLong[1], now);
+ recordPssSampleLocked(app, app.curProcState, pss, mTmpLong[0], mTmpLong[1],
+ mTmpLong[2], ProcessStats.ADD_PSS_INTERNAL_SINGLE, endTime-startTime, now);
mPendingPssProcesses.remove(app);
Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState
+ " to " + app.curProcState + ": "
+ (SystemClock.uptimeMillis()-start) + "ms");
}
app.lastStateTime = now;
- app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
- mTestPssMode, isSleepingLocked(), now);
+ app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
+ app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from "
+ ProcessList.makeProcStateString(app.setProcState) + " to "
+ ProcessList.makeProcStateString(app.curProcState) + " next pss in "
@@ -23760,10 +23666,10 @@
&& now > (app.lastStateTime+ProcessList.minTimeFromStateChange(
mTestPssMode)))) {
requestPssLocked(app, app.setProcState);
- app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
- mTestPssMode, isSleepingLocked(), now);
+ app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
+ app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
} else if (false && DEBUG_PSS) Slog.d(TAG_PSS,
- "Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
+ "Not requesting pss of " + app + ": next=" + (app.nextPssTime-now));
}
if (app.setProcState != app.curProcState) {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mCurOomAdjUid == app.uid) {
@@ -25518,6 +25424,7 @@
public void notifyAppTransitionFinished() {
synchronized (ActivityManagerService.this) {
mStackSupervisor.notifyAppTransitionDone();
+ mKeyguardController.notifyAppTransitionDone();
}
}
@@ -25623,11 +25530,14 @@
// "= 0" is needed because otherwise catch(RemoteException) would make it look like
// packageUid may not be initialized.
int packageUid = 0;
+ final long ident = Binder.clearCallingIdentity();
try {
packageUid = AppGlobals.getPackageManager().getPackageUid(
packageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
} catch (RemoteException e) {
// Shouldn't happen.
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
synchronized (ActivityManagerService.this) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 3bef877..cae0d2b 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1695,7 +1695,7 @@
resumeKeyDispatchingLocked();
final ActivityStack stack = getStack();
- stack.mNoAnimActivities.clear();
+ mStackSupervisor.mNoAnimActivities.clear();
// Mark the point when the activity is resuming
// TODO: To be more accurate, the mark should be before the onCreate,
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 9d06b0d..ab2dc36 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -277,12 +277,6 @@
final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();
/**
- * Animations that for the current transition have requested not to
- * be considered for the transition animation.
- */
- final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<>();
-
- /**
* When we are in the process of pausing an activity, before starting the
* next one, this variable holds the activity that is currently being paused.
*/
@@ -453,6 +447,9 @@
mStackId = stackId;
mCurrentUser = mService.mUserController.getCurrentUserId();
mTmpRect2.setEmpty();
+ // Set display id before setting activity and window type to make sure it won't affect
+ // stacks on a wrong display.
+ mDisplayId = display.mDisplayId;
setActivityType(activityType);
setWindowingMode(windowingMode);
mWindowContainerController = createStackWindowController(display.mDisplayId, onTop,
@@ -481,7 +478,7 @@
@Override
public void setWindowingMode(int windowingMode) {
- setWindowingMode(windowingMode, false /* animate */, true /* showRecents */,
+ setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
false /* enteringSplitScreenMode */);
}
@@ -547,7 +544,7 @@
wm.deferSurfaceLayout();
try {
if (!animate && topActivity != null) {
- mNoAnimActivities.add(topActivity);
+ mStackSupervisor.mNoAnimActivities.add(topActivity);
}
super.setWindowingMode(windowingMode);
@@ -642,7 +639,10 @@
// TODO: We should probably resolve the windowing mode for the stack on the new display here
// so that it end up in a compatible mode in the new display. e.g. split-screen secondary.
removeFromDisplay();
+ // Reparent the window container before we try to update the position when adding it to
+ // the new display below
mTmpRect2.setEmpty();
+ mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */);
mStackSupervisor.resumeFocusedStackTopActivityLocked();
@@ -650,7 +650,6 @@
// windows that are no longer visible.
mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
!PRESERVE_WINDOWS);
- mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
}
/**
@@ -994,12 +993,6 @@
insertTaskAtTop(task, null);
return;
}
-
- task = topTask();
- if (task != null) {
- mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
- true /* includingParents */);
- }
}
/**
@@ -1024,12 +1017,6 @@
if (task != null) {
insertTaskAtBottom(task);
return;
- } else {
- task = bottomTask();
- if (task != null) {
- mWindowContainerController.positionChildAtBottom(
- task.getWindowContainerController(), true /* includingParents */);
- }
}
}
@@ -2467,7 +2454,7 @@
if (prev.finishing) {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare close transition: prev=" + prev);
- if (mNoAnimActivities.contains(prev)) {
+ if (mStackSupervisor.mNoAnimActivities.contains(prev)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
@@ -2479,7 +2466,7 @@
} else {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare open transition: prev=" + prev);
- if (mNoAnimActivities.contains(next)) {
+ if (mStackSupervisor.mNoAnimActivities.contains(next)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
@@ -2492,7 +2479,7 @@
}
} else {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
- if (mNoAnimActivities.contains(next)) {
+ if (mStackSupervisor.mNoAnimActivities.contains(next)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
@@ -2500,17 +2487,14 @@
}
}
- Bundle resumeAnimOptions = null;
if (anim) {
- ActivityOptions opts = next.getOptionsForTargetActivityLocked();
- if (opts != null) {
- resumeAnimOptions = opts.toBundle();
- }
next.applyOptionsLocked();
} else {
next.clearOptionsLocked();
}
+ mStackSupervisor.mNoAnimActivities.clear();
+
ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
@@ -2866,7 +2850,7 @@
"Prepare open transition: starting " + r);
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
- mNoAnimActivities.add(r);
+ mStackSupervisor.mNoAnimActivities.add(r);
} else {
int transit = TRANSIT_ACTIVITY_OPEN;
if (newTask) {
@@ -2885,7 +2869,7 @@
}
}
mWindowManager.prepareAppTransition(transit, keepCurTransition);
- mNoAnimActivities.remove(r);
+ mStackSupervisor.mNoAnimActivities.remove(r);
}
boolean doShow = true;
if (newTask) {
@@ -4504,7 +4488,7 @@
if (noAnimation) {
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
if (r != null) {
- mNoAnimActivities.add(r);
+ mStackSupervisor.mNoAnimActivities.add(r);
}
ActivityOptions.abort(options);
} else {
@@ -5197,7 +5181,6 @@
void executeAppTransition(ActivityOptions options) {
mWindowManager.executeAppTransition();
- mNoAnimActivities.clear();
ActivityOptions.abort(options);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index bfb563f..bf38825 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -297,6 +297,7 @@
private RunningTasks mRunningTasks;
final ActivityStackSupervisorHandler mHandler;
+ final Looper mLooper;
/** Short cut */
WindowManagerService mWindowManager;
@@ -356,6 +357,12 @@
* application */
final ArrayList<ActivityRecord> mPipModeChangedActivities = new ArrayList<>();
+ /**
+ * Animations that for the current transition have requested not to
+ * be considered for the transition animation.
+ */
+ final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<>();
+
/** The target stack bounds for the picture-in-picture mode changed that we need to report to
* the application */
Rect mPipModeChangedTargetStackBounds;
@@ -581,6 +588,7 @@
public ActivityStackSupervisor(ActivityManagerService service, Looper looper) {
mService = service;
+ mLooper = looper;
mHandler = new ActivityStackSupervisorHandler(looper);
}
@@ -1243,10 +1251,14 @@
synchronized (mService) {
try {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent");
+ int modifiedFlags = flags
+ | PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS;
+ if (intent.isBrowsableWebIntent()
+ || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
+ modifiedFlags |= PackageManager.MATCH_INSTANT;
+ }
return mService.getPackageManagerInternalLocked().resolveIntent(
- intent, resolvedType, PackageManager.MATCH_INSTANT
- | PackageManager.MATCH_DEFAULT_ONLY | flags
- | ActivityManagerService.STOCK_PM_FLAGS, userId, true);
+ intent, resolvedType, modifiedFlags, userId, true);
} finally {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 0480646..b86a8a6 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
+import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_ONE_SHOT;
@@ -41,6 +42,7 @@
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.Binder;
+import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -119,11 +121,12 @@
}
private IntentSender createIntentSenderForOriginalIntent(int callingUid, int flags) {
+ Bundle activityOptions = deferCrossProfileAppsAnimationIfNecessary();
final IIntentSender target = mService.getIntentSenderLocked(
INTENT_SENDER_ACTIVITY, mCallingPackage, callingUid, mUserId, null /*token*/,
null /*resultCode*/, 0 /*requestCode*/,
new Intent[] { mIntent }, new String[] { mResolvedType },
- flags, null /*bOptions*/);
+ flags, activityOptions);
return new IntentSender(target);
}
@@ -164,11 +167,27 @@
return interceptWorkProfileChallengeIfNeeded();
}
+ /**
+ * If the activity option is the {@link ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} one,
+ * defer the animation until the original intent is started.
+ *
+ * @return the activity option used to start the original intent.
+ */
+ private Bundle deferCrossProfileAppsAnimationIfNecessary() {
+ if (mActivityOptions != null
+ && mActivityOptions.getAnimationType() == ANIM_OPEN_CROSS_PROFILE_APPS) {
+ mActivityOptions = null;
+ return ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle();
+ }
+ return null;
+ }
+
private boolean interceptQuietProfileIfNeeded() {
// Do not intercept if the user has not turned off the profile
if (!mUserManager.isQuietModeEnabled(UserHandle.of(mUserId))) {
return false;
}
+
IntentSender target = createIntentSenderForOriginalIntent(mCallingUid,
FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT);
@@ -210,8 +229,7 @@
}
private boolean interceptWorkProfileChallengeIfNeeded() {
- final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(mIntent,
- mResolvedType, mAInfo, mCallingPackage, mUserId);
+ final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(mAInfo, mUserId);
if (interceptingIntent == null) {
return false;
}
@@ -248,8 +266,7 @@
*
* @return The intercepting intent if needed.
*/
- private Intent interceptWithConfirmCredentialsIfNeeded(Intent intent, String resolvedType,
- ActivityInfo aInfo, String callingPackage, int userId) {
+ private Intent interceptWithConfirmCredentialsIfNeeded(ActivityInfo aInfo, int userId) {
if (!mUserController.shouldConfirmCredentials(userId)) {
return null;
}
@@ -296,5 +313,4 @@
mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
return true;
}
-
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 4dc30dd..eab88aa 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -31,6 +31,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
@@ -302,6 +303,7 @@
SafeActivityOptions activityOptions;
boolean ignoreTargetSecurity;
boolean componentSpecified;
+ boolean avoidMoveToFront;
ActivityRecord[] outActivity;
TaskRecord inTask;
String reason;
@@ -356,6 +358,7 @@
userId = 0;
waitResult = null;
mayWait = false;
+ avoidMoveToFront = false;
}
/**
@@ -390,6 +393,7 @@
userId = request.userId;
waitResult = request.waitResult;
mayWait = request.mayWait;
+ avoidMoveToFront = request.avoidMoveToFront;
}
}
@@ -786,7 +790,7 @@
// Instead, launch the ephemeral installer. Once the installer is finished, it
// starts either the intent we resolved here [on install error] or the ephemeral
// app [on install success].
- if (rInfo != null && rInfo.auxiliaryInfo != null) {
+ if (rInfo != null && rInfo.isInstantAppAvailable) {
intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
callingPackage, verificationBundle, resolvedType, userId);
resolvedType = null;
@@ -846,22 +850,27 @@
/**
* Creates a launch intent for the given auxiliary resolution data.
*/
- private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
+ private @NonNull Intent createLaunchIntent(@Nullable AuxiliaryResolveInfo auxiliaryResponse,
Intent originalIntent, String callingPackage, Bundle verificationBundle,
String resolvedType, int userId) {
- if (auxiliaryResponse.needsPhaseTwo) {
+ if (auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo) {
// request phase two resolution
mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
auxiliaryResponse, originalIntent, resolvedType, callingPackage,
verificationBundle, userId);
}
return InstantAppResolver.buildEphemeralInstallerIntent(
- Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
- auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
- resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
- auxiliaryResponse.installFailureActivity, auxiliaryResponse.versionCode,
- auxiliaryResponse.token, auxiliaryResponse.resolveInfo.getExtras(),
- auxiliaryResponse.needsPhaseTwo);
+ originalIntent,
+ InstantAppResolver.sanitizeIntent(originalIntent),
+ auxiliaryResponse == null ? null : auxiliaryResponse.failureIntent,
+ callingPackage,
+ verificationBundle,
+ resolvedType,
+ userId,
+ auxiliaryResponse == null ? null : auxiliaryResponse.installFailureActivity,
+ auxiliaryResponse == null ? null : auxiliaryResponse.token,
+ auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo,
+ auxiliaryResponse == null ? null : auxiliaryResponse.filters);
}
void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) {
@@ -921,12 +930,12 @@
// Don't modify the client's object!
intent = new Intent(intent);
if (componentSpecified
- && intent.getData() != null
- && Intent.ACTION_VIEW.equals(intent.getAction())
+ && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
+ && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
&& mService.getPackageManagerInternalLocked()
.isInstantAppInstallerComponent(intent.getComponent())) {
// intercept intents targeted directly to the ephemeral installer the
- // ephemeral installer should never be started with a raw URL; instead
+ // ephemeral installer should never be started with a raw Intent; instead
// adjust the intent so it looks like a "normal" instant app launch
intent.setComponent(null /*component*/);
componentSpecified = false;
@@ -1485,19 +1494,23 @@
mDoResume = false;
}
- if (mOptions != null && mOptions.getLaunchTaskId() != -1
- && mOptions.getTaskOverlay()) {
- r.mTaskOverlay = true;
- if (!mOptions.canTaskOverlayResume()) {
- final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
- final ActivityRecord top = task != null ? task.getTopActivity() : null;
- if (top != null && top.state != RESUMED) {
+ if (mOptions != null) {
+ if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
+ r.mTaskOverlay = true;
+ if (!mOptions.canTaskOverlayResume()) {
+ final TaskRecord task = mSupervisor.anyTaskForIdLocked(
+ mOptions.getLaunchTaskId());
+ final ActivityRecord top = task != null ? task.getTopActivity() : null;
+ if (top != null && top.state != RESUMED) {
- // The caller specifies that we'd like to be avoided to be moved to the front,
- // so be it!
- mDoResume = false;
- mAvoidMoveToFront = true;
+ // The caller specifies that we'd like to be avoided to be moved to the
+ // front, so be it!
+ mDoResume = false;
+ mAvoidMoveToFront = true;
+ }
}
+ } else if (mOptions.getAvoidMoveToFront()) {
+ mAvoidMoveToFront = true;
}
}
@@ -1838,7 +1851,7 @@
// Need to update mTargetStack because if task was moved out of it, the original stack may
// be destroyed.
mTargetStack = intentActivity.getStack();
- if (!mMovedToFront && mDoResume) {
+ if (!mAvoidMoveToFront && !mMovedToFront && mDoResume) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
+ " from " + intentActivity);
mTargetStack.moveToFront("intentActivityFound");
diff --git a/services/core/java/com/android/server/am/AppWarnings.java b/services/core/java/com/android/server/am/AppWarnings.java
index 806e95d..4b43bd9 100644
--- a/services/core/java/com/android/server/am/AppWarnings.java
+++ b/services/core/java/com/android/server/am/AppWarnings.java
@@ -81,7 +81,7 @@
mUiContext = uiContext;
mAmsHandler = new ConfigHandler(amsHandler.getLooper());
mUiHandler = new UiHandler(uiHandler.getLooper());
- mConfigFile = new AtomicFile(new File(systemDir, CONFIG_FILE_NAME));
+ mConfigFile = new AtomicFile(new File(systemDir, CONFIG_FILE_NAME), "warnings-config");
readConfigFromFileAmsThread();
}
diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
index 65c4a42..d84f487 100644
--- a/services/core/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -82,7 +82,7 @@
public CompatModePackages(ActivityManagerService service, File systemDir, Handler handler) {
mService = service;
- mFile = new AtomicFile(new File(systemDir, "packages-compat.xml"));
+ mFile = new AtomicFile(new File(systemDir, "packages-compat.xml"), "compat-mode");
mHandler = new CompatHandler(handler.getLooper());
FileInputStream fis = null;
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index a131db5..cb2957d 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -102,7 +102,7 @@
# Report collection of global memory state
30046 am_meminfo (Cached|2|2),(Free|2|2),(Zram|2|2),(Kernel|2|2),(Native|2|2)
# Report collection of memory used by a process
-30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2)
+30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2),(Rss|2|2),(StatType|1|5),(ProcState|1|5),(TimeToCollect|2|2)
# Attempting to stop an activity
30048 am_stop_activity (User|1|5),(Token|1|5),(Component Name|3)
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 79f3fe3..05305f3 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -384,4 +384,8 @@
proto.write(KEYGUARD_OCCLUDED, mOccluded);
proto.end(token);
}
+
+ public void notifyAppTransitionDone() {
+ setKeyguardGoingAway(false);
+ }
}
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index 21f9135..e5762d2 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -38,6 +38,7 @@
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
@@ -142,14 +143,6 @@
TelecomManager mTelecomManager;
/**
- * Helper that is responsible for showing the right toast when a disallowed activity operation
- * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
- * fully locked mode we only show that unlocking is blocked.
- */
- @VisibleForTesting
- LockTaskNotify mLockTaskNotify;
-
- /**
* The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode.
*
* The first task in the list, which started the current LockTask session, is called the root
@@ -475,7 +468,7 @@
getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
}
if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
- getLockTaskNotify().showPinningExitToast();
+ getStatusBarService().showPinningEnterExitToast(false /* entering */);
}
} catch (RemoteException ex) {
throw new RuntimeException(ex);
@@ -490,7 +483,11 @@
*/
void showLockTaskToast() {
if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
- mHandler.post(() -> getLockTaskNotify().showEscapeToast());
+ try {
+ getStatusBarService().showPinningEscapeToast();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to send pinning escape toast", e);
+ }
}
}
@@ -582,7 +579,7 @@
// When lock task starts, we disable the status bars.
try {
if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
- getLockTaskNotify().showPinningStartToast();
+ getStatusBarService().showPinningEnterExitToast(true /* entering */);
}
mLockTaskModeState = lockTaskModeState;
setStatusBarState(lockTaskModeState, userId);
@@ -835,15 +832,6 @@
return mTelecomManager;
}
- // Should only be called on the handler thread
- @NonNull
- private LockTaskNotify getLockTaskNotify() {
- if (mLockTaskNotify == null) {
- mLockTaskNotify = new LockTaskNotify(mContext);
- }
- return mLockTaskNotify;
- }
-
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "LockTaskController");
prefix = prefix + " ";
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index a50d069..08ee237 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -21,6 +21,7 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.io.PrintWriter;
import java.nio.ByteBuffer;
import android.app.ActivityManager;
@@ -482,7 +483,7 @@
public static final int PSS_MIN_TIME_FROM_STATE_CHANGE = 15*1000;
// The maximum amount of time we want to go between PSS collections.
- public static final int PSS_MAX_INTERVAL = 40*60*1000;
+ public static final int PSS_MAX_INTERVAL = 60*60*1000;
// The minimum amount of time between successive PSS requests for *all* processes.
public static final int PSS_ALL_INTERVAL = 20*60*1000;
@@ -497,7 +498,10 @@
private static final int PSS_FIRST_BACKGROUND_INTERVAL = 20*1000;
// The amount of time until PSS when a process first becomes cached.
- private static final int PSS_FIRST_CACHED_INTERVAL = 30*1000;
+ private static final int PSS_FIRST_CACHED_INTERVAL = 20*1000;
+
+ // The amount of time until PSS when an important process stays in the same state.
+ private static final int PSS_SAME_PERSISTENT_INTERVAL = 20*60*1000;
// The amount of time until PSS when the top process stays in the same state.
private static final int PSS_SAME_TOP_INTERVAL = 5*60*1000;
@@ -509,7 +513,7 @@
private static final int PSS_SAME_SERVICE_INTERVAL = 20*60*1000;
// The amount of time until PSS when a cached process stays in the same state.
- private static final int PSS_SAME_CACHED_INTERVAL = 30*60*1000;
+ private static final int PSS_SAME_CACHED_INTERVAL = 20*60*1000;
// The amount of time until PSS when a persistent process first appears.
private static final int PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL = 1*60*1000;
@@ -543,7 +547,9 @@
public static final int PROC_MEM_IMPORTANT = 2;
public static final int PROC_MEM_SERVICE = 3;
public static final int PROC_MEM_CACHED = 4;
+ public static final int PROC_MEM_NUM = 5;
+ // Map large set of system process states to
private static final int[] sProcStateToProcMem = new int[] {
PROC_MEM_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
PROC_MEM_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
@@ -567,138 +573,96 @@
};
private static final long[] sFirstAwakePssTimes = new long[] {
- PSS_FIRST_PERSISTENT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
- PSS_FIRST_PERSISTENT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
- PSS_FIRST_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
- PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
- PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
- PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
- PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
- PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BACKUP
- PSS_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_SERVICE
- PSS_FIRST_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_RECEIVER
- PSS_FIRST_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
- PSS_FIRST_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
- PSS_FIRST_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HOME
- PSS_FIRST_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
- PSS_FIRST_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
- PSS_FIRST_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
- PSS_FIRST_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_RECENT
- PSS_FIRST_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ PSS_FIRST_PERSISTENT_INTERVAL, // PROC_MEM_PERSISTENT
+ PSS_FIRST_TOP_INTERVAL, // PROC_MEM_TOP
+ PSS_FIRST_BACKGROUND_INTERVAL, // PROC_MEM_IMPORTANT
+ PSS_FIRST_BACKGROUND_INTERVAL, // PROC_MEM_SERVICE
+ PSS_FIRST_CACHED_INTERVAL, // PROC_MEM_CACHED
};
private static final long[] sSameAwakePssTimes = new long[] {
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
- PSS_SAME_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BACKUP
- PSS_SAME_SERVICE_INTERVAL, // ActivityManager.PROCESS_STATE_SERVICE
- PSS_SAME_SERVICE_INTERVAL, // ActivityManager.PROCESS_STATE_RECEIVER
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HOME
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_RECENT
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ PSS_SAME_PERSISTENT_INTERVAL, // PROC_MEM_PERSISTENT
+ PSS_SAME_TOP_INTERVAL, // PROC_MEM_TOP
+ PSS_SAME_IMPORTANT_INTERVAL, // PROC_MEM_IMPORTANT
+ PSS_SAME_SERVICE_INTERVAL, // PROC_MEM_SERVICE
+ PSS_SAME_CACHED_INTERVAL, // PROC_MEM_CACHED
};
private static final long[] sFirstAsleepPssTimes = new long[] {
- PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
- PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
- PSS_FIRST_ASLEEP_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
- PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
- PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
- PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
- PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
- PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BACKUP
- PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_SERVICE
- PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_RECEIVER
- PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
- PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
- PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HOME
- PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
- PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
- PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
- PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_RECENT
- PSS_FIRST_ASLEEP_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL, // PROC_MEM_PERSISTENT
+ PSS_FIRST_ASLEEP_TOP_INTERVAL, // PROC_MEM_TOP
+ PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // PROC_MEM_IMPORTANT
+ PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL, // PROC_MEM_SERVICE
+ PSS_FIRST_ASLEEP_CACHED_INTERVAL, // PROC_MEM_CACHED
};
private static final long[] sSameAsleepPssTimes = new long[] {
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
- PSS_SAME_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
- PSS_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BACKUP
- PSS_SAME_SERVICE_INTERVAL, // ActivityManager.PROCESS_STATE_SERVICE
- PSS_SAME_SERVICE_INTERVAL, // ActivityManager.PROCESS_STATE_RECEIVER
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_HOME
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_RECENT
- PSS_SAME_CACHED_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ PSS_SAME_PERSISTENT_INTERVAL, // PROC_MEM_PERSISTENT
+ PSS_SAME_TOP_INTERVAL, // PROC_MEM_TOP
+ PSS_SAME_IMPORTANT_INTERVAL, // PROC_MEM_IMPORTANT
+ PSS_SAME_SERVICE_INTERVAL, // PROC_MEM_SERVICE
+ PSS_SAME_CACHED_INTERVAL, // PROC_MEM_CACHED
};
private static final long[] sTestFirstPssTimes = new long[] {
- PSS_TEST_FIRST_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
- PSS_TEST_FIRST_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
- PSS_TEST_FIRST_TOP_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BACKUP
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_SERVICE
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_RECEIVER
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_HOME
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_RECENT
- PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ PSS_TEST_FIRST_TOP_INTERVAL, // PROC_MEM_PERSISTENT
+ PSS_TEST_FIRST_TOP_INTERVAL, // PROC_MEM_TOP
+ PSS_TEST_FIRST_BACKGROUND_INTERVAL, // PROC_MEM_IMPORTANT
+ PSS_TEST_FIRST_BACKGROUND_INTERVAL, // PROC_MEM_SERVICE
+ PSS_TEST_FIRST_BACKGROUND_INTERVAL, // PROC_MEM_CACHED
};
private static final long[] sTestSamePssTimes = new long[] {
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
- PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_TOP
- PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
- PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
- PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
- PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
- PSS_TEST_SAME_IMPORTANT_INTERVAL, // ActivityManager.PROCESS_STATE_BACKUP
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_SERVICE
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_RECEIVER
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_HOME
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_RECENT
- PSS_TEST_SAME_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+ PSS_TEST_SAME_BACKGROUND_INTERVAL, // PROC_MEM_PERSISTENT
+ PSS_TEST_SAME_IMPORTANT_INTERVAL, // PROC_MEM_TOP
+ PSS_TEST_SAME_IMPORTANT_INTERVAL, // PROC_MEM_IMPORTANT
+ PSS_TEST_SAME_BACKGROUND_INTERVAL, // PROC_MEM_SERVICE
+ PSS_TEST_SAME_BACKGROUND_INTERVAL, // PROC_MEM_CACHED
};
+ public static final class ProcStateMemTracker {
+ final int[] mHighestMem = new int[PROC_MEM_NUM];
+ int mTotalHighestMem = PROC_MEM_CACHED;
+ float mCurFactor = 1.0f;
+
+ int mPendingMemState;
+ int mPendingHighestMemState;
+ boolean mPendingSame;
+
+ public ProcStateMemTracker() {
+ for (int i = PROC_MEM_PERSISTENT; i < PROC_MEM_NUM; i++) {
+ mHighestMem[i] = PROC_MEM_NUM;
+ }
+ mPendingMemState = -1;
+ }
+
+ public void dumpLine(PrintWriter pw) {
+ pw.print("best=");
+ pw.print(mTotalHighestMem);
+ pw.print(" ");
+ pw.print(mCurFactor);
+ pw.print("x (");
+ for (int i = 0; i < PROC_MEM_NUM; i++) {
+ if (i != 0) {
+ pw.print(", ");
+ }
+ pw.print(i);
+ pw.print("=");
+ pw.print(mHighestMem[i]);
+ }
+ pw.print(")");
+ if (mPendingMemState >= 0) {
+ pw.print(" / pending state=");
+ pw.print(mPendingMemState);
+ pw.print(" highest=");
+ pw.print(mPendingHighestMemState);
+ pw.print(" same=");
+ pw.print(mPendingSame);
+ }
+ pw.println();
+ }
+ }
+
public static boolean procStatesDifferForMem(int procState1, int procState2) {
return sProcStateToProcMem[procState1] != sProcStateToProcMem[procState2];
}
@@ -707,16 +671,50 @@
return test ? PSS_TEST_MIN_TIME_FROM_STATE_CHANGE : PSS_MIN_TIME_FROM_STATE_CHANGE;
}
- public static long computeNextPssTime(int procState, boolean first, boolean test,
+ public static void commitNextPssTime(ProcStateMemTracker tracker) {
+ if (tracker.mPendingMemState >= 0) {
+ tracker.mHighestMem[tracker.mPendingMemState] = tracker.mPendingHighestMemState;
+ tracker.mTotalHighestMem = tracker.mPendingHighestMemState;
+ if (tracker.mPendingSame) {
+ tracker.mCurFactor *= 1.5f;
+ } else {
+ tracker.mCurFactor = 1;
+ }
+ tracker.mPendingMemState = -1;
+ }
+ }
+
+ public static void abortNextPssTime(ProcStateMemTracker tracker) {
+ tracker.mPendingMemState = -1;
+ }
+
+ public static long computeNextPssTime(int procState, ProcStateMemTracker tracker, boolean test,
boolean sleeping, long now) {
+ boolean first;
+ final int memState = sProcStateToProcMem[procState];
+ if (tracker != null) {
+ final int highestMemState = memState < tracker.mTotalHighestMem
+ ? memState : tracker.mTotalHighestMem;
+ first = highestMemState < tracker.mHighestMem[memState];
+ tracker.mPendingMemState = memState;
+ tracker.mPendingHighestMemState = highestMemState;
+ tracker.mPendingSame = !first;
+ } else {
+ first = true;
+ }
final long[] table = test
? (first
- ? sTestFirstPssTimes
- : sTestSamePssTimes)
+ ? sTestFirstPssTimes
+ : sTestSamePssTimes)
: (first
- ? (sleeping ? sFirstAsleepPssTimes : sFirstAwakePssTimes)
- : (sleeping ? sSameAsleepPssTimes : sSameAwakePssTimes));
- return now + table[procState];
+ ? (sleeping ? sFirstAsleepPssTimes : sFirstAwakePssTimes)
+ : (sleeping ? sSameAsleepPssTimes : sSameAwakePssTimes));
+ long delay = (long)(table[memState] * (tracker != null && !first
+ ? tracker.mCurFactor : 1.0f));
+ if (delay > PSS_MAX_INTERVAL) {
+ delay = PSS_MAX_INTERVAL;
+ }
+ return now + delay;
}
long getMemLevel(int adjustment) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 03e140d..1f60755 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -66,6 +66,8 @@
final String processName; // name of the process
// List of packages running in the process
final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList = new ArrayMap<>();
+ final ProcessList.ProcStateMemTracker procStateMemTracker
+ = new ProcessList.ProcStateMemTracker();
UidRecord uidRecord; // overall state of process's uid.
ArraySet<String> pkgDeps; // additional packages we have a dependency on
IApplicationThread thread; // the actual proc... may be null only if
@@ -102,6 +104,7 @@
int repProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state
int setProcState = PROCESS_STATE_NONEXISTENT; // Last set process state in process tracker
int pssProcState = PROCESS_STATE_NONEXISTENT; // Currently requesting pss for
+ int pssStatType; // The type of stat collection that we are currently requesting
int savedPriority; // Previous priority value if we're switching to non-SCHED_OTHER
int renderThreadTid; // TID for RenderThread
boolean serviceb; // Process currently is on the service B list
@@ -285,6 +288,7 @@
TimeUtils.formatDuration(lastActivityTime, nowUptime, pw);
pw.print(" lastPssTime=");
TimeUtils.formatDuration(lastPssTime, nowUptime, pw);
+ pw.print(" pssStatType="); pw.print(pssStatType);
pw.print(" nextPssTime=");
TimeUtils.formatDuration(nextPssTime, nowUptime, pw);
pw.println();
@@ -295,6 +299,8 @@
pw.print(" lastCachedPss="); DebugUtils.printSizeValue(pw, lastCachedPss*1024);
pw.print(" lastCachedSwapPss="); DebugUtils.printSizeValue(pw, lastCachedSwapPss*1024);
pw.println();
+ pw.print(prefix); pw.print("procStateMemTracker: ");
+ procStateMemTracker.dumpLine(pw);
pw.print(prefix); pw.print("cached="); pw.print(cached);
pw.print(" empty="); pw.println(empty);
if (serviceb) {
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index 5f9d616..8bf320e 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -220,8 +220,9 @@
}
public void writeStateLocked(boolean sync, final boolean commit) {
+ final long totalTime;
synchronized (mPendingWriteLock) {
- long now = SystemClock.uptimeMillis();
+ final long now = SystemClock.uptimeMillis();
if (mPendingWrite == null || !mPendingWriteCommitted) {
mPendingWrite = Parcel.obtain();
mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
@@ -238,19 +239,19 @@
updateFile();
}
mLastWriteTime = SystemClock.uptimeMillis();
- if (DEBUG) Slog.d(TAG, "Prepared write state in "
- + (SystemClock.uptimeMillis()-now) + "ms");
+ totalTime = SystemClock.uptimeMillis() - now;
+ if (DEBUG) Slog.d(TAG, "Prepared write state in " + now + "ms");
if (!sync) {
BackgroundThread.getHandler().post(new Runnable() {
@Override public void run() {
- performWriteState();
+ performWriteState(totalTime);
}
});
return;
}
}
- performWriteState();
+ performWriteState(totalTime);
}
private void updateFile() {
@@ -259,7 +260,7 @@
mLastWriteTime = SystemClock.uptimeMillis();
}
- void performWriteState() {
+ void performWriteState(long initialTime) {
if (DEBUG) Slog.d(TAG, "Performing write to " + mFile.getBaseFile());
Parcel data;
AtomicFile file;
@@ -275,12 +276,15 @@
mWriteLock.lock();
}
+ final long startTime = SystemClock.uptimeMillis();
FileOutputStream stream = null;
try {
stream = file.startWrite();
stream.write(data.marshall());
stream.flush();
file.finishWrite(stream);
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "procstats", SystemClock.uptimeMillis() - startTime + initialTime);
if (DEBUG) Slog.d(TAG, "Write completed successfully!");
} catch (IOException e) {
Slog.w(TAG, "Error writing process statistics", e);
@@ -1048,7 +1052,7 @@
}
}
- private void dumpAggregatedStats(ProtoOutputStream proto, int aggregateHours, long now) {
+ private void dumpAggregatedStats(ProtoOutputStream proto, long fieldId, int aggregateHours, long now) {
ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
- (ProcessStats.COMMIT_PERIOD/2));
if (pfd == null) {
@@ -1060,30 +1064,24 @@
if (stats.mReadError != null) {
return;
}
- stats.toProto(proto, now);
+ stats.writeToProto(proto, fieldId, now);
}
private void dumpProto(FileDescriptor fd) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
// dump current procstats
- long nowToken = proto.start(ProcessStatsServiceDumpProto.PROCSTATS_NOW);
long now;
synchronized (mAm) {
now = SystemClock.uptimeMillis();
- mProcessStats.toProto(proto, now);
+ mProcessStats.writeToProto(proto,ProcessStatsServiceDumpProto.PROCSTATS_NOW, now);
}
- proto.end(nowToken);
// aggregated over last 3 hours procstats
- long tokenOf3Hrs = proto.start(ProcessStatsServiceDumpProto.PROCSTATS_OVER_3HRS);
- dumpAggregatedStats(proto, 3, now);
- proto.end(tokenOf3Hrs);
+ dumpAggregatedStats(proto, ProcessStatsServiceDumpProto.PROCSTATS_OVER_3HRS, 3, now);
// aggregated over last 24 hours procstats
- long tokenOf24Hrs = proto.start(ProcessStatsServiceDumpProto.PROCSTATS_OVER_24HRS);
- dumpAggregatedStats(proto, 24, now);
- proto.end(tokenOf24Hrs);
+ dumpAggregatedStats(proto, ProcessStatsServiceDumpProto.PROCSTATS_OVER_24HRS, 24, now);
proto.flush();
}
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
new file mode 100644
index 0000000..e7b067b
--- /dev/null
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -0,0 +1,174 @@
+/*
+ * 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.server.am;
+
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
+import static android.view.WindowManager.TRANSIT_NONE;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
+
+import android.app.ActivityOptions;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Handler;
+import android.view.IRecentsAnimationRunner;
+import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
+import com.android.server.wm.WindowManagerService;
+
+/**
+ * Manages the recents animation, including the reordering of the stacks for the transition and
+ * cleanup. See {@link com.android.server.wm.RecentsAnimationController}.
+ */
+class RecentsAnimation implements RecentsAnimationCallbacks {
+ private static final String TAG = RecentsAnimation.class.getSimpleName();
+
+ private static final int RECENTS_ANIMATION_TIMEOUT = 10 * 1000;
+
+ private final ActivityManagerService mService;
+ private final ActivityStackSupervisor mStackSupervisor;
+ private final ActivityStartController mActivityStartController;
+ private final WindowManagerService mWindowManager;
+ private final UserController mUserController;
+ private final Handler mHandler;
+
+ private final Runnable mCancelAnimationRunnable;
+
+ // The stack to restore the home stack behind when the animation is finished
+ private ActivityStack mRestoreHomeBehindStack;
+
+ RecentsAnimation(ActivityManagerService am, ActivityStackSupervisor stackSupervisor,
+ ActivityStartController activityStartController, WindowManagerService wm,
+ UserController userController) {
+ mService = am;
+ mStackSupervisor = stackSupervisor;
+ mActivityStartController = activityStartController;
+ mHandler = new Handler(mStackSupervisor.mLooper);
+ mWindowManager = wm;
+ mUserController = userController;
+ mCancelAnimationRunnable = () -> {
+ // The caller has not finished the animation in a predefined amount of time, so
+ // force-cancel the animation
+ mWindowManager.cancelRecentsAnimation();
+ };
+ }
+
+ void startRecentsActivity(Intent intent, IRecentsAnimationRunner recentsAnimationRunner,
+ ComponentName recentsComponent, int recentsUid) {
+ mWindowManager.deferSurfaceLayout();
+ try {
+ // Cancel the previous recents animation if necessary
+ mWindowManager.cancelRecentsAnimation();
+
+ final boolean hasExistingHomeActivity = mStackSupervisor.getHomeActivity() != null;
+ if (!hasExistingHomeActivity) {
+ // No home activity
+ final ActivityOptions opts = ActivityOptions.makeBasic();
+ opts.setLaunchActivityType(ACTIVITY_TYPE_HOME);
+ opts.setAvoidMoveToFront();
+ intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);
+
+ mActivityStartController
+ .obtainStarter(intent, "startRecentsActivity_noHomeActivity")
+ .setCallingUid(recentsUid)
+ .setCallingPackage(recentsComponent.getPackageName())
+ .setActivityOptions(SafeActivityOptions.fromBundle(opts.toBundle()))
+ .setMayWait(mUserController.getCurrentUserId())
+ .execute();
+ mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
+
+ // TODO: Maybe wait for app to draw in this particular case?
+ }
+
+ final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
+ final ActivityDisplay display = homeActivity.getDisplay();
+
+ // Save the initial position of the home activity stack to be restored to after the
+ // animation completes
+ mRestoreHomeBehindStack = hasExistingHomeActivity
+ ? display.getStackAboveHome()
+ : null;
+
+ // Move the home activity into place for the animation
+ display.moveHomeStackBehindBottomMostVisibleStack();
+
+ // Mark the home activity as launch-behind to bump its visibility for the
+ // duration of the gesture that is driven by the recents component
+ homeActivity.mLaunchTaskBehind = true;
+
+ // Fetch all the surface controls and pass them to the client to get the animation
+ // started
+ mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this,
+ display.mDisplayId);
+
+ // If we updated the launch-behind state, update the visibility of the activities after
+ // we fetch the visible tasks to be controlled by the animation
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
+
+ // Post a timeout for the animation
+ mHandler.postDelayed(mCancelAnimationRunnable, RECENTS_ANIMATION_TIMEOUT);
+ } finally {
+ mWindowManager.continueSurfaceLayout();
+ }
+ }
+
+ @Override
+ public void onAnimationFinished(boolean moveHomeToTop) {
+ mHandler.removeCallbacks(mCancelAnimationRunnable);
+ synchronized (mService) {
+ if (mWindowManager.getRecentsAnimationController() == null) return;
+
+ mWindowManager.inSurfaceTransaction(() -> {
+ mWindowManager.deferSurfaceLayout();
+ try {
+ mWindowManager.cleanupRecentsAnimation();
+
+ // Move the home stack to the front
+ final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
+ if (homeActivity == null) {
+ return;
+ }
+
+ // Restore the launched-behind state
+ homeActivity.mLaunchTaskBehind = false;
+
+ if (moveHomeToTop) {
+ // Bring the home stack to the front
+ final ActivityStack homeStack = homeActivity.getStack();
+ mStackSupervisor.mNoAnimActivities.add(homeActivity);
+ homeStack.moveToFront("RecentsAnimation.onAnimationFinished()");
+ } else {
+ // Restore the home stack to its previous position
+ final ActivityDisplay display = homeActivity.getDisplay();
+ display.moveHomeStackBehindStack(mRestoreHomeBehindStack);
+ }
+
+ mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, false);
+ mStackSupervisor.resumeFocusedStackTopActivityLocked();
+
+ // No reason to wait for the pausing activity in this case, as the hiding of
+ // surfaces needs to be done immediately.
+ mWindowManager.executeAppTransition();
+ } finally {
+ mWindowManager.continueSurfaceLayout();
+ }
+ });
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 809f19f6..d679439 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -695,7 +695,7 @@
wasPaused, reason);
}
if (!animate) {
- toStack.mNoAnimActivities.add(topActivity);
+ mService.mStackSupervisor.mNoAnimActivities.add(topActivity);
}
// We might trigger a configuration change. Save the current task bounds for freezing.
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index bedf043..1825db8 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -16,11 +16,6 @@
package com.android.server.audio;
-import com.android.server.audio.AudioServiceEvents.ForceUseEvent;
-import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
-import com.android.server.audio.AudioServiceEvents.VolumeEvent;
-import com.android.server.audio.AudioServiceEvents.WiredDevConnectEvent;
-
import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK;
import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;
@@ -64,14 +59,14 @@
import android.media.AudioDevicePort;
import android.media.AudioFocusInfo;
import android.media.AudioFocusRequest;
-import android.media.AudioSystem;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
-import android.media.AudioPort;
import android.media.AudioPlaybackConfiguration;
+import android.media.AudioPort;
import android.media.AudioRecordingConfiguration;
import android.media.AudioRoutesInfo;
+import android.media.AudioSystem;
import android.media.IAudioFocusDispatcher;
import android.media.IAudioRoutesObserver;
import android.media.IAudioService;
@@ -80,12 +75,12 @@
import android.media.IRingtonePlayer;
import android.media.IVolumeController;
import android.media.MediaPlayer;
-import android.media.SoundPool;
-import android.media.VolumePolicy;
-import android.media.audiofx.AudioEffect;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.PlayerBase;
+import android.media.SoundPool;
+import android.media.VolumePolicy;
+import android.media.audiofx.AudioEffect;
import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.AudioPolicyConfig;
@@ -110,6 +105,7 @@
import android.os.Vibrator;
import android.provider.Settings;
import android.provider.Settings.System;
+import android.service.notification.ZenModeConfig;
import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
@@ -129,10 +125,15 @@
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.audio.AudioServiceEvents.ForceUseEvent;
+import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
+import com.android.server.audio.AudioServiceEvents.VolumeEvent;
+import com.android.server.audio.AudioServiceEvents.WiredDevConnectEvent;
import com.android.server.pm.UserManagerService;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
@@ -1328,8 +1329,20 @@
/** @see AudioManager#adjustVolume(int, int) */
public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
String callingPackage, String caller) {
- adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
- caller, Binder.getCallingUid());
+ final IAudioPolicyCallback extVolCtlr;
+ synchronized (mExtVolumeControllerLock) {
+ extVolCtlr = mExtVolumeController;
+ }
+ if (extVolCtlr != null) {
+ try {
+ mExtVolumeController.notifyVolumeAdjust(direction);
+ } catch(RemoteException e) {
+ // nothing we can do about this. Do not log error, too much potential for spam
+ }
+ } else {
+ adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
+ caller, Binder.getCallingUid());
+ }
}
private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
@@ -1852,10 +1865,12 @@
sendVolumeUpdate(streamType, oldIndex, index, flags);
}
- // No ringer affected streams can be changed in total silence mode except those that
- // will cause the device to exit total silence mode.
+ // No ringer affected streams can be changed in total silence mode or priority-only
+ // (with alarms/media toggled off) except those that will cause the device to exit
+ // the mode.
private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
- if (mNm.getZenMode() == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
+ if ((mNm.getZenMode() == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
+ || mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
&& isStreamMutedByRingerMode(streamTypeAlias)) {
if (!(((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(streamTypeAlias == getUiSoundsStreamType()))) {
@@ -2277,7 +2292,9 @@
// only mute for the current user
if (getCurrentUserId() == userId) {
final boolean currentMute = AudioSystem.isMicrophoneMuted();
+ final long identity = Binder.clearCallingIdentity();
AudioSystem.muteMicrophone(on);
+ Binder.restoreCallingIdentity(identity);
if (on != currentMute) {
mContext.sendBroadcast(new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
@@ -2380,11 +2397,30 @@
// Unmute stream if previously muted by ringer mode and ringer mode
// is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
int numStreamTypes = AudioSystem.getNumStreamTypes();
+
+ if (mNm == null) {
+ mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
+ // in priority only dnd, alarms and media streams can be muted when ringer is not muted
+ boolean isZenPriorityMode = mNm.getZenMode() ==
+ Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ NotificationManager.Policy zenPolicy = mNm.getNotificationPolicy();
+ boolean muteAlarms = isZenPriorityMode && ((zenPolicy.priorityCategories
+ & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0);
+ boolean muteMedia = isZenPriorityMode && ((zenPolicy.priorityCategories
+ & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) == 0);
+
final boolean ringerModeMute = mRingerMode == AudioManager.RINGER_MODE_VIBRATE
|| mRingerMode == AudioManager.RINGER_MODE_SILENT;
+
for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
final boolean isMuted = isStreamMutedByRingerMode(streamType);
- final boolean shouldMute = ringerModeMute && isStreamAffectedByRingerMode(streamType);
+
+ final boolean shouldZenMute = (isAlarm(streamType) && muteAlarms)
+ || (isMedia(streamType) && muteMedia);
+ final boolean shouldMute = (shouldZenMute || ringerModeMute)
+ && isStreamAffectedByRingerMode(streamType);
if (isMuted == shouldMute) continue;
if (!shouldMute) {
// unmute
@@ -2420,6 +2456,19 @@
}
}
+ private boolean isAlarm(int streamType) {
+ return streamType == AudioSystem.STREAM_ALARM;
+ }
+
+ private boolean isNotificationOrRinger(int streamType) {
+ return streamType == AudioSystem.STREAM_NOTIFICATION
+ || streamType == AudioSystem.STREAM_RING;
+ }
+
+ private boolean isMedia(int streamType) {
+ return streamType == AudioSystem.STREAM_SYSTEM || streamType == AudioSystem.STREAM_MUSIC;
+ }
+
private void setRingerModeInt(int ringerMode, boolean persist) {
final boolean change;
synchronized(mSettingsLock) {
@@ -2619,7 +2668,9 @@
}
if (actualMode != mMode) {
+ final long identity = Binder.clearCallingIdentity();
status = AudioSystem.setPhoneState(actualMode);
+ Binder.restoreCallingIdentity(identity);
if (status == AudioSystem.AUDIO_STATUS_OK) {
if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
mMode = actualMode;
@@ -4767,6 +4818,16 @@
Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
}
+ private String getSoundEffectFilePath(int effectType) {
+ String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
+ + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
+ if (!new File(filePath).isFile()) {
+ filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
+ + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
+ }
+ return filePath;
+ }
+
private boolean onLoadSoundEffects() {
int status;
@@ -4836,9 +4897,7 @@
continue;
}
if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
- String filePath = Environment.getRootDirectory()
- + SOUND_EFFECTS_PATH
- + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]);
+ String filePath = getSoundEffectFilePath(effect);
int sampleId = mSoundPool.load(filePath, 0);
if (sampleId <= 0) {
Log.w(TAG, "Soundpool could not load file: "+filePath);
@@ -4944,8 +5003,7 @@
} else {
MediaPlayer mediaPlayer = new MediaPlayer();
try {
- String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH +
- SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
+ String filePath = getSoundEffectFilePath(effectType);
mediaPlayer.setDataSource(filePath);
mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
mediaPlayer.prepare();
@@ -6922,7 +6980,7 @@
// Audio policy management
//==========================================================================================
public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
- boolean hasFocusListener, boolean isFocusPolicy) {
+ boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder()
@@ -6945,7 +7003,7 @@
return null;
}
AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
- isFocusPolicy);
+ isFocusPolicy, isVolumeController);
pcb.asBinder().linkToDeath(app, 0/*flags*/);
regId = app.getRegistrationId();
mAudioPolicies.put(pcb.asBinder(), app);
@@ -7011,6 +7069,23 @@
return AudioManager.SUCCESS;
}
+ private final Object mExtVolumeControllerLock = new Object();
+ private IAudioPolicyCallback mExtVolumeController;
+ private void setExtVolumeController(IAudioPolicyCallback apc) {
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_handleVolumeKeysInWindowManager)) {
+ Log.e(TAG, "Cannot set external volume controller: device not set for volume keys" +
+ " handled in PhoneWindowManager");
+ return;
+ }
+ synchronized (mExtVolumeControllerLock) {
+ if (mExtVolumeController != null && !mExtVolumeController.asBinder().pingBinder()) {
+ Log.e(TAG, "Cannot set external volume controller: existing controller");
+ }
+ mExtVolumeController = apc;
+ }
+ }
+
private void dumpAudioPolicies(PrintWriter pw) {
pw.println("\nAudio policies:");
synchronized (mAudioPolicies) {
@@ -7143,8 +7218,9 @@
*/
public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
private static final String TAG = "AudioPolicyProxy";
- IAudioPolicyCallback mPolicyCallback;
- boolean mHasFocusListener;
+ final IAudioPolicyCallback mPolicyCallback;
+ final boolean mHasFocusListener;
+ final boolean mIsVolumeController;
/**
* Audio focus ducking behavior for an audio policy.
* This variable reflects the value that was successfully set in
@@ -7156,11 +7232,12 @@
boolean mIsFocusPolicy = false;
AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
- boolean hasFocusListener, boolean isFocusPolicy) {
+ boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
super(config);
setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
mPolicyCallback = token;
mHasFocusListener = hasFocusListener;
+ mIsVolumeController = isVolumeController;
if (mHasFocusListener) {
mMediaFocusControl.addFocusFollower(mPolicyCallback);
// can only ever be true if there is a focus listener
@@ -7169,6 +7246,9 @@
mMediaFocusControl.setFocusPolicy(mPolicyCallback);
}
}
+ if (mIsVolumeController) {
+ setExtVolumeController(mPolicyCallback);
+ }
connectMixes();
}
@@ -7178,6 +7258,11 @@
release();
mAudioPolicies.remove(mPolicyCallback.asBinder());
}
+ if (mIsVolumeController) {
+ synchronized (mExtVolumeControllerLock) {
+ mExtVolumeController = null;
+ }
+ }
}
String getRegistrationId() {
@@ -7194,11 +7279,15 @@
if (mHasFocusListener) {
mMediaFocusControl.removeFocusFollower(mPolicyCallback);
}
+ final long identity = Binder.clearCallingIdentity();
AudioSystem.registerPolicyMixes(mMixes, false);
+ Binder.restoreCallingIdentity(identity);
}
void connectMixes() {
+ final long identity = Binder.clearCallingIdentity();
AudioSystem.registerPolicyMixes(mMixes, true);
+ Binder.restoreCallingIdentity(identity);
}
};
diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
index bd2e96e..e43d152 100644
--- a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
+++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
@@ -150,7 +150,8 @@
fillLinkInfo(ev, newNai);
ev.initialScore = newNai.getCurrentScore();
if (newNai.lastValidated) {
- logDefaultNetworkValidity(timeMs, true);
+ mIsCurrentlyValid = true;
+ mLastValidationTimeMs = timeMs;
}
} else {
mIsCurrentlyValid = false;
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 57258a8..f1a806b 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -219,11 +219,7 @@
for (INetdEventCallback callback : mNetdEventCallbackList) {
if (callback != null) {
- // TODO(rickywai): Remove this checking to collect ip in watchlist.
- if (callback ==
- mNetdEventCallbackList[INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY]) {
- callback.onConnectEvent(ipAddr, port, timestamp, uid);
- }
+ callback.onConnectEvent(ipAddr, port, timestamp, uid);
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index be6c4a1..9a9cdbd 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1095,7 +1095,8 @@
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
synchronized (mPublicSync) {
- usbManager.setCurrentFunction(enable ? UsbManager.USB_FUNCTION_RNDIS : null, false);
+ usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_RNDIS
+ : UsbManager.FUNCTION_NONE);
}
return ConnectivityManager.TETHER_ERROR_NO_ERROR;
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index b35ed75..3413291 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
+import android.os.Process;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.IpPrefix;
@@ -476,6 +477,7 @@
ConnectivityManager.getNetworkTypeName(type));
continue;
}
+ nc.setSingleUid(Process.myUid());
for (NetworkState value : netStates) {
if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) {
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index e498666..5a37ee2 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -481,9 +481,9 @@
maybeDeleteLegacyPendingInfoLocked(syncDir);
- mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
- mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
- mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
+ mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"), "sync-accounts");
+ mStatusFile = new AtomicFile(new File(syncDir, "status.bin"), "sync-status");
+ mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"), "sync-stats");
readAccountInfoLocked();
readStatusLocked();
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index e445d27..6a88b1e 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -237,8 +237,13 @@
return mScreenAutoBrightness;
}
+ public float getAutomaticScreenBrightnessAdjustment() {
+ return mScreenAutoBrightnessAdjustment;
+ }
+
public void configure(boolean enable, @Nullable BrightnessConfiguration configuration,
- float brightness, float adjustment, int displayPolicy, boolean userInitiatedChange) {
+ float brightness, boolean userChangedBrightness, float adjustment,
+ boolean userChangedAutoBrightnessAdjustment, int displayPolicy) {
// While dozing, the application processor may be suspended which will prevent us from
// receiving new information from the light sensor. On some devices, we may be able to
// switch to a wake-up light sensor instead but for now we will simply disable the sensor
@@ -247,12 +252,17 @@
boolean dozing = (displayPolicy == DisplayPowerRequest.POLICY_DOZE);
boolean changed = setBrightnessConfiguration(configuration);
changed |= setDisplayPolicy(displayPolicy);
- if (userInitiatedChange && enable && !dozing) {
- // Update the current brightness value.
+ changed |= setScreenAutoBrightnessAdjustment(adjustment);
+ if (userChangedBrightness && enable) {
+ // Update the brightness curve with the new user control point. It's critical this
+ // happens after we update the autobrightness adjustment since it may reset it.
changed |= setScreenBrightnessByUser(brightness);
+ }
+ final boolean userInitiatedChange =
+ userChangedBrightness || userChangedAutoBrightnessAdjustment;
+ if (userInitiatedChange && enable && !dozing) {
prepareBrightnessAdjustmentSample();
}
- changed |= setScreenAutoBrightnessAdjustment(adjustment);
changed |= setLightSensorEnabled(enable && !dozing);
if (changed) {
updateAutoBrightness(false /*sendUpdate*/);
@@ -290,6 +300,9 @@
return false;
}
mBrightnessMapper.addUserDataPoint(mAmbientLux, brightness);
+ // Reset the brightness adjustment so that the next time we're queried for brightness we
+ // return the value the user set.
+ mScreenAutoBrightnessAdjustment = 0.0f;
return true;
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 436ebff..001d4d9 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -182,6 +182,10 @@
/**
* Adds a user interaction data point to the brightness mapping.
*
+ * This data point <b>must</b> exist on the brightness curve as a result of this call. This is
+ * so that the next time we come to query what the screen brightness should be, we get what the
+ * user requested rather than immediately changing to some other value.
+ *
* Currently, we only keep track of one of these at a time to constrain what can happen to the
* curve.
*/
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 056c3e6..80aec42 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -805,15 +805,20 @@
mAutomaticBrightnessController.configure(autoBrightnessEnabled,
mBrightnessConfiguration,
mLastUserSetScreenBrightness / (float) PowerManager.BRIGHTNESS_ON,
- autoBrightnessAdjustment, mPowerRequest.policy, userInitiatedChange);
+ userSetBrightnessChanged, autoBrightnessAdjustment,
+ autoBrightnessAdjustmentChanged, mPowerRequest.policy);
}
// Apply auto-brightness.
boolean slowChange = false;
if (brightness < 0) {
+ float newAutoBrightnessAdjustment = autoBrightnessAdjustment;
if (autoBrightnessEnabled) {
brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();
+ newAutoBrightnessAdjustment =
+ mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment();
}
+
if (brightness >= 0) {
// Use current auto-brightness value and slowly adjust to changes.
brightness = clampScreenBrightness(brightness);
@@ -829,6 +834,11 @@
} else {
mAppliedAutoBrightness = false;
}
+ if (autoBrightnessAdjustment != newAutoBrightnessAdjustment) {
+ // If the autobrightness controller has decided to change the adjustment value
+ // used, make sure that's reflected in settings.
+ putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment);
+ }
} else {
mAppliedAutoBrightness = false;
}
@@ -839,11 +849,8 @@
}
// Apply manual brightness.
- // Use the current brightness setting from the request, which is expected
- // provide a nominal default value for the case where auto-brightness
- // is not ready yet.
if (brightness < 0) {
- brightness = clampScreenBrightness(mLastUserSetScreenBrightness);
+ brightness = clampScreenBrightness(mCurrentScreenBrightnessSetting);
}
@@ -1428,8 +1435,13 @@
private void putScreenBrightnessSetting(int brightness) {
mCurrentScreenBrightnessSetting = brightness;
Settings.System.putIntForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS, brightness,
- UserHandle.USER_CURRENT);
+ Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT);
+ }
+
+ private void putAutoBrightnessAdjustmentSetting(float adjustment) {
+ mAutoBrightnessAdjustment = adjustment;
+ Settings.System.putFloatForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adjustment, UserHandle.USER_CURRENT);
}
private boolean updateAutoBrightnessAdjustment() {
@@ -1449,6 +1461,7 @@
return false;
}
if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
+ mPendingScreenBrightnessSetting = -1;
return false;
}
mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index cbf46f8..1af03de 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -771,7 +771,8 @@
private final AtomicFile mAtomicFile;
public Injector() {
- mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml"));
+ mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml"),
+ "display-state");
}
public InputStream openRead() throws FileNotFoundException {
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index f67e0fd..372db41 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -82,7 +82,8 @@
private boolean mDirty;
public PersistentDataStore() {
- mAtomicFile = new AtomicFile(new File("/data/system/input-manager-state.xml"));
+ mAtomicFile = new AtomicFile(new File("/data/system/input-manager-state.xml"),
+ "input-state");
}
public void saveIfNeeded() {
diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/services/core/java/com/android/server/job/JobSchedulerInternal.java
index 569e9ec..08607bc 100644
--- a/services/core/java/com/android/server/job/JobSchedulerInternal.java
+++ b/services/core/java/com/android/server/job/JobSchedulerInternal.java
@@ -64,6 +64,14 @@
void removeBackingUpUid(int uid);
void clearAllBackingUpUids();
+ /**
+ * The user has started interacting with the app. Take any appropriate action.
+ */
+ void reportAppUsage(String packageName, int userId);
+
+ /**
+ * Report a snapshot of sync-related jobs back to the sync manager
+ */
JobStorePersistStats getPersistStats();
/**
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 2066f2a..e0baeee 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1071,6 +1071,11 @@
}
}
+ void reportAppUsage(String packageName, int userId) {
+ // This app just transitioned into interactive use or near equivalent, so we should
+ // take a look at its job state for feedback purposes.
+ }
+
/**
* Initializes the system service.
* <p>
@@ -1809,7 +1814,9 @@
// If the app is in a non-active standby bucket, make sure we've waited
// an appropriate amount of time since the last invocation. During device-
// wide parole, standby bucketing is ignored.
- if (!mInParole) {
+ //
+ // But if a job has FLAG_EXEMPT_FROM_APP_STANDBY, don't check it.
+ if (!mInParole && !job.getJob().isExemptedFromAppStandby()) {
final int bucket = job.getStandbyBucket();
if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
// Only skip this job if it's still waiting for the end of its (initial) nominal
@@ -2151,6 +2158,11 @@
}
@Override
+ public void reportAppUsage(String packageName, int userId) {
+ JobSchedulerService.this.reportAppUsage(packageName, userId);
+ }
+
+ @Override
public JobStorePersistStats getPersistStats() {
synchronized (mLock) {
return new JobStorePersistStats(mJobs.getPersistStats());
@@ -2194,12 +2206,7 @@
Slog.i(TAG, "Moving uid " + uid + " to bucketIndex " + bucketIndex);
}
synchronized (mLock) {
- // TODO: update to be more efficient once we can slice by source UID
- mJobs.forEachJob((JobStatus job) -> {
- if (job.getSourceUid() == uid) {
- job.setStandbyBucket(bucketIndex);
- }
- });
+ mJobs.forEachJobForSourceUid(uid, job -> job.setStandbyBucket(bucketIndex));
onControllerStateChanged();
}
});
@@ -2212,6 +2219,40 @@
}
mInParole = isParoleOn;
}
+
+ @Override
+ public void onUserInteractionStarted(String packageName, int userId) {
+ final int uid = mLocalPM.getPackageUid(packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+ if (uid < 0) {
+ // Quietly ignore; the case is already logged elsewhere
+ return;
+ }
+
+ final long sinceLast = sElapsedRealtimeClock.millis() -
+ mUsageStats.getTimeSinceLastJobRun(packageName, userId);
+ final DeferredJobCounter counter = new DeferredJobCounter();
+ synchronized (mLock) {
+ mJobs.forEachJobForSourceUid(uid, counter);
+ }
+
+ mUsageStats.reportAppJobState(packageName, userId, counter.numDeferred(), sinceLast);
+ }
+ }
+
+ static class DeferredJobCounter implements JobStatusFunctor {
+ private int mDeferred = 0;
+
+ public int numDeferred() {
+ return mDeferred;
+ }
+
+ @Override
+ public void process(JobStatus job) {
+ if (job.getWhenStandbyDeferred() > 0) {
+ mDeferred++;
+ }
+ }
}
public static int standbyBucketToBucketIndex(int bucket) {
@@ -2295,6 +2336,22 @@
return canPersist;
}
+ private void validateJobFlags(JobInfo job, int callingUid) {
+ if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
+ }
+ if ((job.getFlags() & JobInfo.FLAG_EXEMPT_FROM_APP_STANDBY) != 0) {
+ if (callingUid != Process.SYSTEM_UID) {
+ throw new SecurityException("Job has invalid flags");
+ }
+ if (job.hasLateConstraint() || job.hasEarlyConstraint()) {
+ Slog.wtf(TAG, "Jobs with time-constraints mustn't have"
+ +" FLAG_EXEMPT_FROM_APP_STANDBY. Job=" + job);
+ }
+ }
+ }
+
// IJobScheduler implementation
@Override
public int schedule(JobInfo job) throws RemoteException {
@@ -2313,10 +2370,7 @@
}
}
- if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
- }
+ validateJobFlags(job, uid);
long ident = Binder.clearCallingIdentity();
try {
@@ -2344,10 +2398,7 @@
throw new NullPointerException("work is null");
}
- if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
- }
+ validateJobFlags(job, uid);
long ident = Binder.clearCallingIdentity();
try {
@@ -2378,10 +2429,7 @@
+ " not permitted to schedule jobs for other apps");
}
- if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
- }
+ validateJobFlags(job, callerUid);
long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index f23147b..37b3990 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -24,6 +24,7 @@
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobWorkItem;
+import android.app.usage.UsageStatsManagerInternal;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -46,6 +47,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
import com.android.server.job.controllers.JobStatus;
/**
@@ -238,6 +240,11 @@
}
}
+ UsageStatsManagerInternal usageStats =
+ LocalServices.getService(UsageStatsManagerInternal.class);
+ usageStats.setLastJobRunTime(job.getSourcePackageName(), job.getSourceUserId(),
+ mExecutionStartTimeElapsed);
+
// Once we'e begun executing a job, we by definition no longer care whether
// it was inflated from disk with not-yet-coherent delay/deadline bounds.
job.clearPersistedUtcTimes();
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index a24a4ac..cf27882 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -29,6 +29,7 @@
import android.os.Handler;
import android.os.PersistableBundle;
import android.os.Process;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.text.format.DateUtils;
import android.util.ArraySet;
@@ -61,6 +62,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.function.Predicate;
/**
* Maintains the master list of jobs that the job scheduler is tracking. These jobs are compared by
@@ -84,7 +86,7 @@
private static final int MAX_OPS_BEFORE_WRITE = 1;
final Object mLock;
- final JobSet mJobSet; // per-caller-uid tracking
+ final JobSet mJobSet; // per-caller-uid and per-source-uid tracking
final Context mContext;
// Bookkeeping around incorrect boot-time system clock
@@ -133,7 +135,7 @@
File systemDir = new File(dataDir, "system");
File jobDir = new File(systemDir, "job");
jobDir.mkdirs();
- mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml"));
+ mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml"), "jobs");
mJobSet = new JobSet();
@@ -361,6 +363,7 @@
int numSystemJobs = 0;
int numSyncJobs = 0;
try {
+ final long startTime = SystemClock.uptimeMillis();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XmlSerializer out = new FastXmlSerializer();
out.setOutput(baos, StandardCharsets.UTF_8.name());
@@ -393,7 +396,7 @@
out.endDocument();
// Write out to disk in one fell swoop.
- FileOutputStream fos = mJobsFile.startWrite();
+ FileOutputStream fos = mJobsFile.startWrite(startTime);
fos.write(baos.toByteArray());
mJobsFile.finishWrite(fos);
mDirtyOperations = 0;
@@ -998,10 +1001,11 @@
}
static final class JobSet {
- // Key is the getUid() originator of the jobs in each sheaf
- private SparseArray<ArraySet<JobStatus>> mJobs;
- // Same data but with the key as getSourceUid() of the jobs in each sheaf
- private SparseArray<ArraySet<JobStatus>> mJobsPerSourceUid;
+ @VisibleForTesting // Key is the getUid() originator of the jobs in each sheaf
+ final SparseArray<ArraySet<JobStatus>> mJobs;
+
+ @VisibleForTesting // Same data but with the key as getSourceUid() of the jobs in each sheaf
+ final SparseArray<ArraySet<JobStatus>> mJobsPerSourceUid;
public JobSet() {
mJobs = new SparseArray<ArraySet<JobStatus>>();
@@ -1044,7 +1048,13 @@
jobsForSourceUid = new ArraySet<>();
mJobsPerSourceUid.put(sourceUid, jobsForSourceUid);
}
- return jobs.add(job) && jobsForSourceUid.add(job);
+ final boolean added = jobs.add(job);
+ final boolean addedInSource = jobsForSourceUid.add(job);
+ if (added != addedInSource) {
+ Slog.wtf(TAG, "mJobs and mJobsPerSourceUid mismatch; caller= " + added
+ + " source= " + addedInSource);
+ }
+ return added || addedInSource;
}
public boolean remove(JobStatus job) {
@@ -1073,27 +1083,40 @@
/**
* Removes the jobs of all users not specified by the whitelist of user ids.
- * The jobs scheduled by non existent users will not be removed if they were
+ * This will remove jobs scheduled *by* non-existent users as well as jobs scheduled *for*
+ * non-existent users
*/
- public void removeJobsOfNonUsers(int[] whitelist) {
- for (int jobSetIndex = mJobsPerSourceUid.size() - 1; jobSetIndex >= 0; jobSetIndex--) {
- final int jobUserId = UserHandle.getUserId(mJobsPerSourceUid.keyAt(jobSetIndex));
- if (!ArrayUtils.contains(whitelist, jobUserId)) {
- mJobsPerSourceUid.removeAt(jobSetIndex);
- }
- }
+ public void removeJobsOfNonUsers(final int[] whitelist) {
+ final Predicate<JobStatus> noSourceUser =
+ job -> !ArrayUtils.contains(whitelist, job.getSourceUserId());
+ final Predicate<JobStatus> noCallingUser =
+ job -> !ArrayUtils.contains(whitelist, job.getUserId());
+ removeAll(noSourceUser.or(noCallingUser));
+ }
+
+ private void removeAll(Predicate<JobStatus> predicate) {
for (int jobSetIndex = mJobs.size() - 1; jobSetIndex >= 0; jobSetIndex--) {
- final ArraySet<JobStatus> jobsForUid = mJobs.valueAt(jobSetIndex);
- for (int jobIndex = jobsForUid.size() - 1; jobIndex >= 0; jobIndex--) {
- final int jobUserId = jobsForUid.valueAt(jobIndex).getUserId();
- if (!ArrayUtils.contains(whitelist, jobUserId)) {
- jobsForUid.removeAt(jobIndex);
+ final ArraySet<JobStatus> jobs = mJobs.valueAt(jobSetIndex);
+ for (int jobIndex = jobs.size() - 1; jobIndex >= 0; jobIndex--) {
+ if (predicate.test(jobs.valueAt(jobIndex))) {
+ jobs.removeAt(jobIndex);
}
}
- if (jobsForUid.size() == 0) {
+ if (jobs.size() == 0) {
mJobs.removeAt(jobSetIndex);
}
}
+ for (int jobSetIndex = mJobsPerSourceUid.size() - 1; jobSetIndex >= 0; jobSetIndex--) {
+ final ArraySet<JobStatus> jobs = mJobsPerSourceUid.valueAt(jobSetIndex);
+ for (int jobIndex = jobs.size() - 1; jobIndex >= 0; jobIndex--) {
+ if (predicate.test(jobs.valueAt(jobIndex))) {
+ jobs.removeAt(jobIndex);
+ }
+ }
+ if (jobs.size() == 0) {
+ mJobsPerSourceUid.removeAt(jobSetIndex);
+ }
+ }
}
public boolean contains(JobStatus job) {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 31c20cb..28fa86b 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1348,11 +1348,11 @@
.verifyChallenge(userId, 0, willStore.hash, credential.getBytes());
setUserKeyProtection(userId, credential, convertResponse(gkResponse));
fixateNewestUserKeyAuth(userId);
- mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential,
- userId);
// Refresh the auth token
doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */);
synchronizeUnifiedWorkChallengeForProfiles(userId, null);
+ mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential,
+ userId);
} else {
throw new RemoteException("Failed to enroll " +
(credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password"
@@ -1982,8 +1982,8 @@
}
@Override
- public KeyChainSnapshot getRecoveryData(@NonNull byte[] account) throws RemoteException {
- return mRecoverableKeyStoreManager.getRecoveryData(account);
+ public KeyChainSnapshot getKeyChainSnapshot() throws RemoteException {
+ return mRecoverableKeyStoreManager.getKeyChainSnapshot();
}
public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent)
@@ -2494,6 +2494,7 @@
(response != null ? "rate limit exceeded" : "failed"));
return;
}
+ mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId);
}
@Override
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index db46c3d..662ffc8 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -72,7 +72,7 @@
private final int mCredentialType;
private final String mCredential;
private final boolean mCredentialUpdated;
- private final PlatformKeyManager.Factory mPlatformKeyManagerFactory;
+ private final PlatformKeyManager mPlatformKeyManager;
private final RecoverySnapshotStorage mRecoverySnapshotStorage;
private final RecoverySnapshotListenersStorage mSnapshotListenersStorage;
@@ -94,7 +94,7 @@
credentialType,
credential,
credentialUpdated,
- () -> PlatformKeyManager.getInstance(context, recoverableKeyStoreDb));
+ PlatformKeyManager.getInstance(context, recoverableKeyStoreDb));
}
/**
@@ -105,9 +105,7 @@
* @param credentialType The type of credential as defined in {@code LockPatternUtils}
* @param credential The credential, encoded as a {@link String}.
* @param credentialUpdated signals weather credentials were updated.
- * @param platformKeyManagerFactory Instantiates a {@link PlatformKeyManager} for the user.
- * This is a factory to enable unit testing, as otherwise it would be impossible to test
- * without a screen unlock occurring!
+ * @param platformKeyManager platform key manager
*/
@VisibleForTesting
KeySyncTask(
@@ -118,14 +116,14 @@
int credentialType,
String credential,
boolean credentialUpdated,
- PlatformKeyManager.Factory platformKeyManagerFactory) {
+ PlatformKeyManager platformKeyManager) {
mSnapshotListenersStorage = recoverySnapshotListenersStorage;
mRecoverableKeyStoreDb = recoverableKeyStoreDb;
mUserId = userId;
mCredentialType = credentialType;
mCredential = credential;
mCredentialUpdated = credentialUpdated;
- mPlatformKeyManagerFactory = platformKeyManagerFactory;
+ mPlatformKeyManager = platformKeyManager;
mRecoverySnapshotStorage = snapshotStorage;
}
@@ -145,6 +143,8 @@
if (mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
// Application keys for the user will not be available for sync.
Log.w(TAG, "Credentials are not set for user " + mUserId);
+ int generation = mPlatformKeyManager.getGenerationId(mUserId);
+ mPlatformKeyManager.invalidatePlatformKey(mUserId, generation);
return;
}
@@ -158,9 +158,17 @@
}
private void syncKeysForAgent(int recoveryAgentUid) {
+ boolean recreateCurrentVersion = false;
if (!shoudCreateSnapshot(recoveryAgentUid)) {
- Log.d(TAG, "Key sync not needed.");
- return;
+ recreateCurrentVersion =
+ (mRecoverableKeyStoreDb.getSnapshotVersion(mUserId, recoveryAgentUid) != null)
+ && (mRecoverySnapshotStorage.get(recoveryAgentUid) == null);
+ if (recreateCurrentVersion) {
+ Log.d(TAG, "Recreating most recent snapshot");
+ } else {
+ Log.d(TAG, "Key sync not needed.");
+ return;
+ }
}
if (!mSnapshotListenersStorage.hasListener(recoveryAgentUid)) {
@@ -253,23 +261,21 @@
Log.e(TAG,"Could not encrypt with recovery key", e);
return;
}
- // TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later
- // TODO: use Builder.
- KeyChainProtectionParams metadata = new KeyChainProtectionParams(
- /*userSecretType=*/ TYPE_LOCKSCREEN,
- /*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential),
- /*keyDerivationParams=*/ KeyDerivationParams.createSha256Params(salt),
- /*secret=*/ new byte[0]);
+ KeyChainProtectionParams metadata = new KeyChainProtectionParams.Builder()
+ .setUserSecretType(TYPE_LOCKSCREEN)
+ .setLockScreenUiFormat(getUiFormat(mCredentialType, mCredential))
+ .setKeyDerivationParams(KeyDerivationParams.createSha256Params(salt))
+ .setSecret(new byte[0])
+ .build();
+
ArrayList<KeyChainProtectionParams> metadataList = new ArrayList<>();
metadataList.add(metadata);
- int snapshotVersion = incrementSnapshotVersion(recoveryAgentUid);
-
// If application keys are not updated, snapshot will not be created on next unlock.
mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);
mRecoverySnapshotStorage.put(recoveryAgentUid, new KeyChainSnapshot.Builder()
- .setSnapshotVersion(snapshotVersion)
+ .setSnapshotVersion(getSnapshotVersion(recoveryAgentUid, recreateCurrentVersion))
.setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS)
.setCounterId(counterId)
.setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey))
@@ -283,9 +289,14 @@
}
@VisibleForTesting
- int incrementSnapshotVersion(int recoveryAgentUid) {
+ int getSnapshotVersion(int recoveryAgentUid, boolean recreateCurrentVersion) {
Long snapshotVersion = mRecoverableKeyStoreDb.getSnapshotVersion(mUserId, recoveryAgentUid);
- snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion + 1;
+ if (recreateCurrentVersion) {
+ // version shouldn't be null at this moment.
+ snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion;
+ } else {
+ snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion + 1;
+ }
mRecoverableKeyStoreDb.setSnapshotVersion(mUserId, recoveryAgentUid, snapshotVersion);
return snapshotVersion.intValue();
@@ -304,8 +315,7 @@
throws InsecureUserException, KeyStoreException, UnrecoverableKeyException,
NoSuchAlgorithmException, NoSuchPaddingException, BadPlatformKeyException,
InvalidKeyException, InvalidAlgorithmParameterException {
- PlatformKeyManager platformKeyManager = mPlatformKeyManagerFactory.newInstance();
- PlatformDecryptionKey decryptKey = platformKeyManager.getDecryptKey(mUserId);;
+ PlatformDecryptionKey decryptKey = mPlatformKeyManager.getDecryptKey(mUserId);;
Map<String, WrappedKey> wrappedKeys = mRecoverableKeyStoreDb.getAllKeys(
mUserId, recoveryAgentUid, decryptKey.getGenerationId());
return WrappedKey.unwrapKeys(decryptKey, wrappedKeys);
@@ -414,10 +424,10 @@
Map<String, byte[]> encryptedApplicationKeys) {
ArrayList<WrappedApplicationKey> keyEntries = new ArrayList<>();
for (String alias : encryptedApplicationKeys.keySet()) {
- keyEntries.add(
- new WrappedApplicationKey(
- alias,
- encryptedApplicationKeys.get(alias)));
+ keyEntries.add(new WrappedApplicationKey.Builder()
+ .setAlias(alias)
+ .setEncryptedKeyMaterial(encryptedApplicationKeys.get(alias))
+ .build());
}
return keyEntries;
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
index ee6a893..3a78f95 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
@@ -129,6 +129,26 @@
}
/**
+ * Removes the platform key from Android KeyStore.
+ * It is triggered when user disables lock screen.
+ *
+ * @param userId The ID of the user to whose lock screen the platform key must be bound.
+ * @param generationId Generation id.
+ *
+ * @hide
+ */
+ public void invalidatePlatformKey(int userId, int generationId) {
+ if (generationId != -1) {
+ try {
+ mKeyStore.deleteEntry(getEncryptAlias(userId, generationId));
+ mKeyStore.deleteEntry(getDecryptAlias(userId, generationId));
+ } catch (KeyStoreException e) {
+ // Ignore failed attempt to delete key.
+ }
+ }
+ }
+
+ /**
* Generates a new key and increments the generation ID. Should be invoked if the platform key
* is corrupted and needs to be rotated.
* Updates status of old keys to {@code RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE}.
@@ -152,6 +172,7 @@
if (generationId == -1) {
nextId = 1;
} else {
+ invalidatePlatformKey(userId, generationId);
nextId = generationId + 1;
}
generateAndLoadKey(userId, nextId);
@@ -197,8 +218,12 @@
private PlatformEncryptionKey getEncryptKeyInternal(int userId) throws KeyStoreException,
UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
int generationId = getGenerationId(userId);
+ String alias = getEncryptAlias(userId, generationId);
+ if (!mKeyStore.containsAlias(alias)) {
+ throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias);
+ }
AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
- getEncryptAlias(userId, generationId), /*password=*/ null);
+ alias, /*password=*/ null);
return new PlatformEncryptionKey(generationId, key);
}
@@ -242,8 +267,12 @@
private PlatformDecryptionKey getDecryptKeyInternal(int userId) throws KeyStoreException,
UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
int generationId = getGenerationId(userId);
+ String alias = getDecryptAlias(userId, generationId);
+ if (!mKeyStore.containsAlias(alias)) {
+ throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias);
+ }
AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
- getDecryptAlias(userId, generationId), /*password=*/ null);
+ alias, /*password=*/ null);
return new PlatformDecryptionKey(generationId, key);
}
@@ -405,16 +434,4 @@
return keyStore;
}
- /**
- * @hide
- */
- public interface Factory {
- /**
- * New PlatformKeyManager instance.
- *
- * @hide
- */
- PlatformKeyManager newInstance()
- throws NoSuchAlgorithmException, InsecureUserException, KeyStoreException;
- }
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 0d567d1..ec72b22 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -171,7 +171,7 @@
* @hide
*/
public @NonNull
- KeyChainSnapshot getRecoveryData(@NonNull byte[] account)
+ KeyChainSnapshot getKeyChainSnapshot()
throws RemoteException {
checkRecoverKeyStorePermission();
int uid = Binder.getCallingUid();
@@ -456,29 +456,24 @@
private byte[] decryptRecoveryKey(
RecoverySessionStorage.Entry sessionEntry, byte[] encryptedClaimResponse)
throws RemoteException, ServiceSpecificException {
- // TODO: Remove the extensive loggings in this function
byte[] locallyEncryptedKey;
try {
+ // TODO: Remove the extraneous logging here
+ Log.e(TAG, constructLoggingMessage("sessionEntry.getKeyClaimant()",
+ sessionEntry.getKeyClaimant()));
+ Log.e(TAG, constructLoggingMessage("sessionEntry.getVaultParams()",
+ sessionEntry.getVaultParams()));
+ Log.e(TAG, constructLoggingMessage("encryptedClaimResponse", encryptedClaimResponse));
locallyEncryptedKey = KeySyncUtils.decryptRecoveryClaimResponse(
sessionEntry.getKeyClaimant(),
sessionEntry.getVaultParams(),
encryptedClaimResponse);
} catch (InvalidKeyException e) {
Log.e(TAG, "Got InvalidKeyException during decrypting recovery claim response", e);
- Log.e(TAG, constructLoggingMessage("sessionEntry.getKeyClaimant()",
- sessionEntry.getKeyClaimant()));
- Log.e(TAG, constructLoggingMessage("sessionEntry.getVaultParams()",
- sessionEntry.getVaultParams()));
- Log.e(TAG, constructLoggingMessage("encryptedClaimResponse", encryptedClaimResponse));
throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
"Failed to decrypt recovery key " + e.getMessage());
} catch (AEADBadTagException e) {
Log.e(TAG, "Got AEADBadTagException during decrypting recovery claim response", e);
- Log.e(TAG, constructLoggingMessage("sessionEntry.getKeyClaimant()",
- sessionEntry.getKeyClaimant()));
- Log.e(TAG, constructLoggingMessage("sessionEntry.getVaultParams()",
- sessionEntry.getVaultParams()));
- Log.e(TAG, constructLoggingMessage("encryptedClaimResponse", encryptedClaimResponse));
throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
"Failed to decrypt recovery key " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
@@ -487,19 +482,17 @@
}
try {
- return KeySyncUtils.decryptRecoveryKey(sessionEntry.getLskfHash(), locallyEncryptedKey);
- } catch (InvalidKeyException e) {
- Log.e(TAG, "Got InvalidKeyException during decrypting recovery key", e);
+ // TODO: Remove the extraneous logging here
Log.e(TAG, constructLoggingMessage("sessionEntry.getLskfHash()",
sessionEntry.getLskfHash()));
Log.e(TAG, constructLoggingMessage("locallyEncryptedKey", locallyEncryptedKey));
+ return KeySyncUtils.decryptRecoveryKey(sessionEntry.getLskfHash(), locallyEncryptedKey);
+ } catch (InvalidKeyException e) {
+ Log.e(TAG, "Got InvalidKeyException during decrypting recovery key", e);
throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
"Failed to decrypt recovery key " + e.getMessage());
} catch (AEADBadTagException e) {
Log.e(TAG, "Got AEADBadTagException during decrypting recovery key", e);
- Log.e(TAG, constructLoggingMessage("sessionEntry.getLskfHash()",
- sessionEntry.getLskfHash()));
- Log.e(TAG, constructLoggingMessage("locallyEncryptedKey", locallyEncryptedKey));
throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
"Failed to decrypt recovery key " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
@@ -531,6 +524,9 @@
byte[] encryptedKeyMaterial = applicationKey.getEncryptedKeyMaterial();
try {
+ // TODO: Remove the extraneous logging here
+ Log.e(TAG, constructLoggingMessage("recoveryKey", recoveryKey));
+ Log.e(TAG, constructLoggingMessage("encryptedKeyMaterial", encryptedKeyMaterial));
byte[] keyMaterial =
KeySyncUtils.decryptApplicationKey(recoveryKey, encryptedKeyMaterial);
keyMaterialByAlias.put(alias, keyMaterial);
@@ -538,7 +534,15 @@
Log.wtf(TAG, "Missing SecureBox algorithm. AOSP required to support this.", e);
throw new ServiceSpecificException(
ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
- } catch (InvalidKeyException | AEADBadTagException e) {
+ } catch (InvalidKeyException e) {
+ Log.e(TAG, "Got InvalidKeyException during decrypting application key with alias: "
+ + alias, e);
+ throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
+ "Failed to recover key with alias '" + alias + "': " + e.getMessage());
+ } catch (AEADBadTagException e) {
+ // TODO: Remove the extraneous logging here
+ Log.e(TAG, "Got AEADBadTagException during decrypting application key with alias: "
+ + alias, e);
throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED,
"Failed to recover key with alias '" + alias + "': " + e.getMessage());
}
@@ -579,6 +583,7 @@
/**
* This function can only be used inside LockSettingsService.
+ *
* @param storedHashType from {@code CredentialHash}
* @param credential - unencrypted String
* @param userId for the user whose lock screen credentials were changed.
@@ -604,7 +609,7 @@
} catch (KeyStoreException e) {
Log.e(TAG, "Key store error encountered during recoverable key sync", e);
} catch (InsecureUserException e) {
- Log.wtf(TAG, "Impossible - insecure user, but user just entered lock screen", e);
+ Log.e(TAG, "InsecureUserException during lock screen secret update", e);
}
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/PersistentKeyChainSnapshot.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/PersistentKeyChainSnapshot.java
new file mode 100644
index 0000000..52381b8
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/PersistentKeyChainSnapshot.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.locksettings.recoverablekeystore.storage;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.security.keystore.recovery.KeyChainProtectionParams;
+import android.security.keystore.recovery.KeyChainSnapshot;
+import android.security.keystore.recovery.KeyDerivationParams;
+import android.security.keystore.recovery.WrappedApplicationKey;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides helper methods serialize and deserialize {@link KeyChainSnapshot}.
+ *
+ * <p> It is necessary since {@link android.os.Parcelable} is not designed for persistent storage.
+ *
+ * <p> For every list, length is stored before the elements.
+ *
+ */
+public class PersistentKeyChainSnapshot {
+ private static final int VERSION = 1;
+ private static final int NULL_LIST_LENGTH = -1;
+
+ private DataInputStream mInput;
+ private DataOutputStream mOut;
+ private ByteArrayOutputStream mOutStream;
+
+ @VisibleForTesting
+ PersistentKeyChainSnapshot() {
+ }
+
+ @VisibleForTesting
+ void initReader(byte[] input) {
+ mInput = new DataInputStream(new ByteArrayInputStream(input));
+ }
+
+ @VisibleForTesting
+ void initWriter() {
+ mOutStream = new ByteArrayOutputStream();
+ mOut = new DataOutputStream(mOutStream);
+ }
+
+ @VisibleForTesting
+ byte[] getOutput() {
+ return mOutStream.toByteArray();
+ }
+
+ /**
+ * Converts {@link KeyChainSnapshot} to its binary representation.
+ *
+ * @param snapshot The snapshot.
+ *
+ * @throws IOException if serialization failed.
+ */
+ public static byte[] serialize(@NonNull KeyChainSnapshot snapshot) throws IOException {
+ PersistentKeyChainSnapshot writer = new PersistentKeyChainSnapshot();
+ writer.initWriter();
+ writer.writeInt(VERSION);
+ writer.writeKeyChainSnapshot(snapshot);
+ return writer.getOutput();
+ }
+
+ /**
+ * deserializes {@link KeyChainSnapshot}.
+ *
+ * @input input - byte array produced by {@link serialize} method.
+ * @throws IOException if parsing failed.
+ */
+ public static @NonNull KeyChainSnapshot deserialize(@NonNull byte[] input)
+ throws IOException {
+ PersistentKeyChainSnapshot reader = new PersistentKeyChainSnapshot();
+ reader.initReader(input);
+ try {
+ int version = reader.readInt();
+ if (version != VERSION) {
+ throw new IOException("Unsupported version " + version);
+ }
+ return reader.readKeyChainSnapshot();
+ } catch (IOException e) {
+ throw new IOException("Malformed KeyChainSnapshot", e);
+ }
+ }
+
+ /**
+ * Must be in sync with {@link KeyChainSnapshot.writeToParcel}
+ */
+ @VisibleForTesting
+ void writeKeyChainSnapshot(KeyChainSnapshot snapshot) throws IOException {
+ writeInt(snapshot.getSnapshotVersion());
+ writeProtectionParamsList(snapshot.getKeyChainProtectionParams());
+ writeBytes(snapshot.getEncryptedRecoveryKeyBlob());
+ writeKeysList(snapshot.getWrappedApplicationKeys());
+
+ writeInt(snapshot.getMaxAttempts());
+ writeLong(snapshot.getCounterId());
+ writeBytes(snapshot.getServerParams());
+ writeBytes(snapshot.getTrustedHardwarePublicKey());
+ }
+
+ @VisibleForTesting
+ KeyChainSnapshot readKeyChainSnapshot() throws IOException {
+ int snapshotVersion = readInt();
+ List<KeyChainProtectionParams> protectionParams = readProtectionParamsList();
+ byte[] encryptedRecoveryKey = readBytes();
+ List<WrappedApplicationKey> keysList = readKeysList();
+
+ int maxAttempts = readInt();
+ long conterId = readLong();
+ byte[] serverParams = readBytes();
+ byte[] trustedHardwarePublicKey = readBytes();
+
+ return new KeyChainSnapshot.Builder()
+ .setSnapshotVersion(snapshotVersion)
+ .setKeyChainProtectionParams(protectionParams)
+ .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey)
+ .setWrappedApplicationKeys(keysList)
+ .setMaxAttempts(maxAttempts)
+ .setCounterId(conterId)
+ .setServerParams(serverParams)
+ .setTrustedHardwarePublicKey(trustedHardwarePublicKey)
+ .build();
+ }
+
+ @VisibleForTesting
+ void writeProtectionParamsList(
+ @NonNull List<KeyChainProtectionParams> ProtectionParamsList) throws IOException {
+ writeInt(ProtectionParamsList.size());
+ for (KeyChainProtectionParams protectionParams : ProtectionParamsList) {
+ writeProtectionParams(protectionParams);
+ }
+ }
+
+ @VisibleForTesting
+ List<KeyChainProtectionParams> readProtectionParamsList() throws IOException {
+ int length = readInt();
+ List<KeyChainProtectionParams> result = new ArrayList<>(length);
+ for (int i = 0; i < length; i++) {
+ result.add(readProtectionParams());
+ }
+ return result;
+ }
+
+ /**
+ * Must be in sync with {@link KeyChainProtectionParams.writeToParcel}
+ */
+ @VisibleForTesting
+ void writeProtectionParams(@NonNull KeyChainProtectionParams protectionParams)
+ throws IOException {
+ if (!ArrayUtils.isEmpty(protectionParams.getSecret())) {
+ // Extra security check.
+ throw new RuntimeException("User generated secret should not be stored");
+ }
+ writeInt(protectionParams.getUserSecretType());
+ writeInt(protectionParams.getLockScreenUiFormat());
+ writeKeyDerivationParams(protectionParams.getKeyDerivationParams());
+ writeBytes(protectionParams.getSecret());
+ }
+
+ @VisibleForTesting
+ KeyChainProtectionParams readProtectionParams() throws IOException {
+ int userSecretType = readInt();
+ int lockScreenUiFormat = readInt();
+ KeyDerivationParams derivationParams = readKeyDerivationParams();
+ byte[] secret = readBytes();
+ return new KeyChainProtectionParams.Builder()
+ .setUserSecretType(userSecretType)
+ .setLockScreenUiFormat(lockScreenUiFormat)
+ .setKeyDerivationParams(derivationParams)
+ .setSecret(secret)
+ .build();
+ }
+
+ /**
+ * Must be in sync with {@link KeyDerivationParams.writeToParcel}
+ */
+ @VisibleForTesting
+ void writeKeyDerivationParams(@NonNull KeyDerivationParams Params) throws IOException {
+ writeInt(Params.getAlgorithm());
+ writeBytes(Params.getSalt());
+ }
+
+ @VisibleForTesting
+ KeyDerivationParams readKeyDerivationParams() throws IOException {
+ int algorithm = readInt();
+ byte[] salt = readBytes();
+ return KeyDerivationParams.createSha256Params(salt);
+ }
+
+ @VisibleForTesting
+ void writeKeysList(@NonNull List<WrappedApplicationKey> applicationKeys) throws IOException {
+ writeInt(applicationKeys.size());
+ for (WrappedApplicationKey keyEntry : applicationKeys) {
+ writeKeyEntry(keyEntry);
+ }
+ }
+
+ @VisibleForTesting
+ List<WrappedApplicationKey> readKeysList() throws IOException {
+ int length = readInt();
+ List<WrappedApplicationKey> result = new ArrayList<>(length);
+ for (int i = 0; i < length; i++) {
+ result.add(readKeyEntry());
+ }
+ return result;
+ }
+
+ /**
+ * Must be in sync with {@link WrappedApplicationKey.writeToParcel}
+ */
+ @VisibleForTesting
+ void writeKeyEntry(@NonNull WrappedApplicationKey keyEntry) throws IOException {
+ mOut.writeUTF(keyEntry.getAlias());
+ writeBytes(keyEntry.getEncryptedKeyMaterial());
+ writeBytes(keyEntry.getAccount());
+ }
+
+ @VisibleForTesting
+ WrappedApplicationKey readKeyEntry() throws IOException {
+ String alias = mInput.readUTF();
+ byte[] keyMaterial = readBytes();
+ byte[] account = readBytes();
+ return new WrappedApplicationKey.Builder()
+ .setAlias(alias)
+ .setEncryptedKeyMaterial(keyMaterial)
+ .setAccount(account)
+ .build();
+ }
+
+ @VisibleForTesting
+ void writeInt(int value) throws IOException {
+ mOut.writeInt(value);
+ }
+
+ @VisibleForTesting
+ int readInt() throws IOException {
+ return mInput.readInt();
+ }
+
+ @VisibleForTesting
+ void writeLong(long value) throws IOException {
+ mOut.writeLong(value);
+ }
+
+ @VisibleForTesting
+ long readLong() throws IOException {
+ return mInput.readLong();
+ }
+
+ @VisibleForTesting
+ void writeBytes(@Nullable byte[] value) throws IOException {
+ if (value == null) {
+ writeInt(NULL_LIST_LENGTH);
+ return;
+ }
+ writeInt(value.length);
+ mOut.write(value, 0, value.length);
+ }
+
+ /**
+ * Reads @code{byte[]} from current position. Converts {@code null} to an empty array.
+ */
+ @VisibleForTesting
+ @NonNull byte[] readBytes() throws IOException {
+ int length = readInt();
+ if (length == NULL_LIST_LENGTH) {
+ return new byte[]{};
+ }
+ byte[] result = new byte[length];
+ mInput.read(result, 0, result.length);
+ return result;
+ }
+}
+
diff --git a/services/core/java/com/android/server/media/MediaSession2Record.java b/services/core/java/com/android/server/media/MediaSession2Record.java
index 4000a11..97c7bf6c 100644
--- a/services/core/java/com/android/server/media/MediaSession2Record.java
+++ b/services/core/java/com/android/server/media/MediaSession2Record.java
@@ -16,19 +16,13 @@
package com.android.server.media;
-import android.annotation.CallSuper;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.Context;
-import android.media.IMediaSession2;
import android.media.MediaController2;
import android.media.MediaSession2;
import android.media.SessionToken2;
-import android.os.Handler;
-import android.os.Looper;
import android.util.Log;
import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
/**
* Records a {@link MediaSession2} and holds {@link MediaController2}.
@@ -44,138 +38,88 @@
private static final boolean DEBUG = true; // TODO(jaewan): Change
private final Context mContext;
+ private final SessionToken2 mSessionToken;
private final SessionDestroyedListener mSessionDestroyedListener;
// TODO(jaewan): Replace these with the mContext.getMainExecutor()
- private final Handler mMainHandler;
private final Executor mMainExecutor;
private MediaController2 mController;
- private ControllerCallback mControllerCallback;
-
- private int mSessionPid;
/**
* Constructor
*/
- public MediaSession2Record(@NonNull Context context,
+ public MediaSession2Record(@NonNull Context context, @NonNull SessionToken2 token,
@NonNull SessionDestroyedListener listener) {
mContext = context;
+ mSessionToken = token;
mSessionDestroyedListener = listener;
-
- mMainHandler = new Handler(Looper.getMainLooper());
- mMainExecutor = (runnable) -> {
- mMainHandler.post(runnable);
- };
- }
-
- public int getSessionPid() {
- return mSessionPid;
+ mMainExecutor = (runnable) -> runnable.run();
}
public Context getContext() {
return mContext;
}
- @CallSuper
public void onSessionDestroyed() {
if (mController != null) {
- mControllerCallback.destroy();
mController.close();
+ // close() triggers ControllerCallback.onDisconnected() here already.
mController = null;
}
- mSessionPid = 0;
}
- /**
- * Create session token and tell server that session is now active.
- *
- * @param sessionPid session's pid
- * @return a token if successfully set, {@code null} if sanity check fails.
- */
- // TODO(jaewan): also add uid for multiuser support
- @CallSuper
- public @Nullable
- SessionToken2 createSessionToken(int sessionPid, String packageName, String id,
- IMediaSession2 sessionBinder) {
+ public boolean onSessionCreated(SessionToken2 token) {
if (mController != null) {
- if (mSessionPid != sessionPid) {
- // A package uses the same id for session across the different process.
- return null;
- }
- // If a session becomes inactive and then active again very quickly, previous 'inactive'
- // may not have delivered yet. Check if it's the case and destroy controller before
- // creating its session record to prevents getXXTokens() API from returning duplicated
- // tokens.
- // TODO(jaewan): Change this. If developer is really creating two sessions with the same
- // id, this will silently invalidate previous session and no way for
- // developers to know that.
- // Instead, keep the list of static session ids from our APIs.
- // Also change Controller2Impl.onConnectionChanged / getController.
- // Also clean up ControllerCallback#destroy().
- if (DEBUG) {
- Log.d(TAG, "Session is recreated almost immediately. " + this);
- }
- onSessionDestroyed();
+ // Disclaimer: This may fail if following happens for an app.
+ // Step 1) Create a session in the process #1
+ // Step 2) Process #1 is killed
+ // Step 3) Before the death of process #1 is delivered,
+ // (i.e. ControllerCallback#onDisconnected is called),
+ // new process is started and create another session with the same
+ // id in the new process.
+ // Step 4) fail!!! But this is tricky case that wouldn't happen in normal.
+ Log.w(TAG, "Cannot create a new session with the id=" + token.getId() + " in the"
+ + " pkg=" + token.getPackageName() + ". ID should be unique in a package");
+ return false;
}
- mController = onCreateMediaController(packageName, id, sessionBinder);
- mSessionPid = sessionPid;
- return mController.getSessionToken();
+ mController = new MediaController2(mContext, token, mMainExecutor,
+ new ControllerCallback());
+ return true;
}
/**
- * Called when session becomes active and needs controller to listen session's activeness.
- * <p>
- * Should be overridden by subclasses to create token with its own extra information.
- */
- MediaController2 onCreateMediaController(
- String packageName, String id, IMediaSession2 sessionBinder) {
- SessionToken2 token = new SessionToken2(
- SessionToken2.TYPE_SESSION, packageName, id, null, sessionBinder);
- return createMediaController(token);
- }
-
- final MediaController2 createMediaController(SessionToken2 token) {
- mControllerCallback = new ControllerCallback();
- return new MediaController2(mContext, token, mMainExecutor, mControllerCallback);
- }
-
- /**
- * @return controller. Note that framework can only call oneway calls.
+ * @return token
*/
public SessionToken2 getToken() {
- return mController == null ? null : mController.getSessionToken();
+ return mSessionToken;
+ }
+
+ /**
+ * @return controller
+ */
+ public MediaController2 getController() {
+ return mController;
}
@Override
public String toString() {
return getToken() == null
- ? "Token {null}"
- : "SessionRecord {pid=" + mSessionPid + ", " + getToken().toString() + "}";
+ ? "Token {null}" : "SessionRecord {" + getToken().toString() + "}";
}
private class ControllerCallback extends MediaController2.ControllerCallback {
- private final AtomicBoolean mIsActive = new AtomicBoolean(true);
-
- // This is called on the main thread with no lock. So place ensure followings.
+ // This is called on the random thread with no lock. So place ensure followings.
// 1. Don't touch anything in the parent class that needs synchronization.
// All other APIs in the MediaSession2Record assumes that server would use them with
// the lock hold.
- // 2. This can be called after the controller registered is released.
+ // 2. This can be called after the controller registered is closed.
@Override
public void onDisconnected() {
- if (!mIsActive.get()) {
- return;
- }
if (DEBUG) {
Log.d(TAG, "onDisconnected, token=" + getToken());
}
mSessionDestroyedListener.onSessionDestroyed(MediaSession2Record.this);
}
-
- // TODO(jaewan): Remove this API when we revisit createSessionToken()
- public void destroy() {
- mIsActive.set(false);
- }
};
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index c7f6014..b877184 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -16,6 +16,8 @@
package com.android.server.media;
+import static android.media.SessionToken2.TYPE_SESSION;
+
import android.app.ActivityManager;
import android.app.INotificationManager;
import android.app.KeyguardManager;
@@ -28,6 +30,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
@@ -36,8 +39,8 @@
import android.media.AudioPlaybackConfiguration;
import android.media.AudioSystem;
import android.media.IAudioService;
-import android.media.IMediaSession2;
import android.media.IRemoteVolumeController;
+import android.media.ISessionTokensListener;
import android.media.MediaLibraryService2;
import android.media.MediaSessionService2;
import android.media.SessionToken2;
@@ -130,15 +133,9 @@
private final List<MediaSession2Record> mSessions = new ArrayList<>();
private final MediaSession2Record.SessionDestroyedListener mSessionDestroyedListener =
- (MediaSession2Record record) -> {
+ (record) -> {
synchronized (mLock) {
- if (DEBUG) {
- Log.d(TAG, record.toString() + " becomes inactive");
- }
- record.onSessionDestroyed();
- if (!(record instanceof MediaSessionService2Record)) {
- mSessions.remove(record);
- }
+ destroySessionLocked(record);
}
};
@@ -446,14 +443,16 @@
}
// TODO(jaewan): Query per users.
+ // TODO(jaewan): Similar codes are also at the updatable. Can't we share codes?
+ PackageManager manager = getContext().getPackageManager();
List<ResolveInfo> services = new ArrayList<>();
// If multiple actions are declared for a service, browser gets higher priority.
- List<ResolveInfo> libraryServices = getContext().getPackageManager().queryIntentServices(
+ List<ResolveInfo> libraryServices = manager.queryIntentServices(
new Intent(MediaLibraryService2.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
if (libraryServices != null) {
services.addAll(libraryServices);
}
- List<ResolveInfo> sessionServices = getContext().getPackageManager().queryIntentServices(
+ List<ResolveInfo> sessionServices = manager.queryIntentServices(
new Intent(MediaSessionService2.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
if (sessionServices != null) {
services.addAll(sessionServices);
@@ -468,24 +467,23 @@
continue;
}
ServiceInfo serviceInfo = services.get(i).serviceInfo;
- String id = (serviceInfo.metaData != null) ? serviceInfo.metaData.getString(
- MediaSessionService2.SERVICE_META_DATA) : null;
- // Do basic sanity check
- // TODO(jaewan): also santity check if it's protected with the system|privileged
- // permission
- boolean conflict = (getSessionRecordLocked(serviceInfo.name, id) != null);
- if (conflict) {
- Log.w(TAG, serviceInfo.packageName + " contains multiple"
- + " MediaSessionService2s declared in the manifest with"
- + " the same ID=" + id + ". Ignoring "
- + serviceInfo.packageName + "/" + serviceInfo.name);
- } else {
- int type = (libraryServices.contains(services.get(i)))
- ? SessionToken2.TYPE_LIBRARY_SERVICE : SessionToken2.TYPE_SESSION_SERVICE;
- MediaSessionService2Record record =
- new MediaSessionService2Record(getContext(), mSessionDestroyedListener,
- type, serviceInfo.packageName, serviceInfo.name, id);
+ int uid;
+ try {
+ // TODO(jaewan): Do this per user.
+ uid = manager.getPackageUid(serviceInfo.packageName,
+ PackageManager.GET_META_DATA);
+ } catch (NameNotFoundException e) {
+ continue;
+ }
+
+ try {
+ SessionToken2 token = new SessionToken2(getContext(),
+ serviceInfo.packageName, serviceInfo.name, uid);
+ MediaSession2Record record = new MediaSession2Record(getContext(),
+ token, mSessionDestroyedListener);
mSessions.add(record);
+ } catch (IllegalArgumentException e) {
+ Log.d(TAG, "Invalid session service", e);
}
}
}
@@ -497,17 +495,27 @@
}
}
- MediaSession2Record getSessionRecordLocked(String packageName, String id) {
+ private MediaSession2Record getSessionRecordLocked(int uid, String packageName, String id) {
for (int i = 0; i < mSessions.size(); i++) {
- MediaSession2Record record = mSessions.get(i);
- if (record.getToken().getPackageName().equals(packageName)
- && record.getToken().getId().equals(id)) {
- return record;
+ SessionToken2 token = mSessions.get(i).getToken();
+ if (token.getUid() == uid && token.getPackageName().equals(packageName)
+ && token.getId().equals(id)) {
+ return mSessions.get(i);
}
}
return null;
}
+ private void destroySessionLocked(MediaSession2Record record) {
+ if (DEBUG) {
+ Log.d(TAG, record.toString() + " becomes inactive");
+ }
+ record.onSessionDestroyed();
+ if (record.getToken().getType() == TYPE_SESSION) {
+ mSessions.remove(record);
+ }
+ }
+
private void enforcePackageName(String packageName, int uid) {
if (TextUtils.isEmpty(packageName)) {
throw new IllegalArgumentException("packageName may not be empty");
@@ -1406,37 +1414,72 @@
mUserRecords.valueAt(i).dumpLocked(pw, "");
}
mAudioPlayerStateMonitor.dump(getContext(), pw, "");
+
+ // TODO(jaewan): Remove this debug command before ship.
+ if (args != null && args.length > 0 && "--purge".equals(args[0])) {
+ mSessions.clear();
+ }
+ pw.println();
+ pw.println("Session2: size=" + mSessions.size());
+ for (int i = 0; i < mSessions.size(); i++) {
+ pw.println(" " + mSessions.get(i));
+ }
}
}
@Override
- public Bundle createSessionToken(String sessionPackage, String id,
- IMediaSession2 sessionBinder) throws RemoteException {
- int uid = Binder.getCallingUid();
- int pid = Binder.getCallingPid();
-
- MediaSession2Record record;
- SessionToken2 token;
- // TODO(jaewan): Add sanity check for the token if calling package is from uid.
+ public boolean onSessionCreated(Bundle sessionToken) {
+ final int uid = Binder.getCallingUid();
+ final int pid = Binder.getCallingPid();
+ final SessionToken2 token = SessionToken2.fromBundle(getContext(), sessionToken);
+ if (token == null || token.getUid() != uid) {
+ Log.w(TAG, "onSessionCreated failed, expected caller uid=" + token.getUid()
+ + " but from uid=" + uid);
+ }
+ if (DEBUG) {
+ Log.d(TAG, "onSessionCreated " + token);
+ }
synchronized (mLock) {
- record = getSessionRecordLocked(sessionPackage, id);
- if (record == null) {
- record = new MediaSession2Record(getContext(), mSessionDestroyedListener);
- mSessions.add(record);
- }
- token = record.createSessionToken(pid, sessionPackage, id, sessionBinder);
- if (token == null) {
- Log.d(TAG, "failed to create session token for " + sessionPackage
- + " from pid=" + pid + ". Previously " + record);
+ MediaSession2Record record = getSessionRecordLocked(
+ uid, token.getPackageName(), token.getId());
+ if (record != null) {
+ return record.onSessionCreated(token);
} else {
- Log.d(TAG, "session " + token + " is created");
+ record = new MediaSession2Record(
+ getContext(), token, mSessionDestroyedListener);
+ mSessions.add(record);
+ return record.onSessionCreated(token);
}
}
- return token == null ? null : token.toBundle();
+ }
+
+ @Override
+ public void onSessionDestroyed(Bundle sessionToken) {
+ final int uid = Binder.getCallingUid();
+ final int pid = Binder.getCallingPid();
+ final SessionToken2 token = SessionToken2.fromBundle(getContext(), sessionToken);
+ if (token == null || token.getUid() != uid) {
+ Log.w(TAG, "onSessionDestroyed failed, expected caller uid=" + token.getUid()
+ + " but from uid=" + uid);
+ }
+ if (DEBUG) {
+ Log.d(TAG, "onSessionDestroyed " + token);
+ }
+ synchronized (mLock) {
+ MediaSession2Record record = getSessionRecordLocked(
+ uid, token.getPackageName(), token.getId());
+ if (record != null) {
+ record.onSessionDestroyed();
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Cannot find a session record to destroy. uid=" + uid
+ + ", pkg=" + token.getPackageName() + ", id=" + token.getId());
+ }
+ }
+ }
}
// TODO(jaewan): Protect this API with permission
- // TODO(jaewan): Add listeners for change in operations..
@Override
public List<Bundle> getSessionTokens(boolean activeSessionOnly,
boolean sessionServiceOnly) throws RemoteException {
@@ -1444,8 +1487,8 @@
synchronized (mLock) {
for (int i = 0; i < mSessions.size(); i++) {
MediaSession2Record record = mSessions.get(i);
- boolean isSessionService = (record instanceof MediaSessionService2Record);
- boolean isActive = record.getSessionPid() != 0;
+ boolean isSessionService = (record.getToken().getType() != TYPE_SESSION);
+ boolean isActive = record.getController() != null;
if ((!activeSessionOnly && isSessionService)
|| (!sessionServiceOnly && isActive)) {
SessionToken2 token = record.getToken();
@@ -1460,6 +1503,17 @@
return tokens;
}
+ @Override
+ public void addSessionTokensListener(ISessionTokensListener listener, int userId,
+ String packageName) {
+ // TODO(jaewan): Implement.
+ }
+
+ @Override
+ public void removeSessionTokensListener(ISessionTokensListener listener) {
+ // TODO(jaewan): Implement
+ }
+
private int verifySessionsRequest(ComponentName componentName, int userId, final int pid,
final int uid) {
String packageName = null;
diff --git a/services/core/java/com/android/server/media/MediaSessionService2Record.java b/services/core/java/com/android/server/media/MediaSessionService2Record.java
deleted file mode 100644
index d033f55..0000000
--- a/services/core/java/com/android/server/media/MediaSessionService2Record.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.server.media;
-
-import android.content.Context;
-import android.media.IMediaSession2;
-import android.media.MediaController2;
-import android.media.SessionToken2;
-import android.media.MediaSessionService2;
-
-/**
- * Records a {@link MediaSessionService2}.
- * <p>
- * Owner of this object should handle synchronization.
- */
-class MediaSessionService2Record extends MediaSession2Record {
- private static final boolean DEBUG = true; // TODO(jaewan): Modify
- private static final String TAG = "SessionService2Record";
-
- private final int mType;
- private final String mServiceName;
- private final SessionToken2 mToken;
-
- public MediaSessionService2Record(Context context,
- SessionDestroyedListener sessionDestroyedListener, int type,
- String packageName, String serviceName, String id) {
- super(context, sessionDestroyedListener);
- mType = type;
- mServiceName = serviceName;
- mToken = new SessionToken2(mType, packageName, id, mServiceName, null);
- }
-
- /**
- * Overriden to change behavior of
- * {@link #createSessionToken(int, String, String, IMediaSession2)}}.
- */
- @Override
- MediaController2 onCreateMediaController(
- String packageName, String id, IMediaSession2 sessionBinder) {
- SessionToken2 token = new SessionToken2(mType, packageName, id, mServiceName, sessionBinder);
- return createMediaController(token);
- }
-
- /**
- * @return token with no session binder information.
- */
- @Override
- public SessionToken2 getToken() {
- return mToken;
- }
-}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 0e54768..f09de52 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -551,7 +551,7 @@
mSuppressDefaultPolicy = suppressDefaultPolicy;
- mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
+ mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"), "net-policy");
mAppOps = context.getSystemService(AppOpsManager.class);
diff --git a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
index 7165e60..5f4e471 100644
--- a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
+++ b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
@@ -23,8 +23,10 @@
import android.net.metrics.IpConnectivityLog;
import android.os.Binder;
import android.os.Process;
+import android.os.ResultReceiver;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.SystemProperties;
import android.provider.Settings;
import android.text.TextUtils;
@@ -80,6 +82,7 @@
return;
}
try {
+ mService.init();
mService.initIpConnectivityMetrics();
mService.startWatchlistLogging();
} catch (RemoteException e) {
@@ -127,6 +130,10 @@
mIpConnectivityMetrics = ipConnectivityMetrics;
}
+ private void init() {
+ mConfig.removeTestModeConfig();
+ }
+
private void initIpConnectivityMetrics() {
mIpConnectivityMetrics = (IIpConnectivityMetrics) IIpConnectivityMetrics.Stub.asInterface(
ServiceManager.getService(IpConnectivityLog.SERVICE_NAME));
@@ -151,6 +158,22 @@
}
};
+ private boolean isCallerShell() {
+ final int callingUid = Binder.getCallingUid();
+ return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
+ }
+
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+ if (!isCallerShell()) {
+ Slog.w(TAG, "Only shell is allowed to call network watchlist shell commands");
+ return;
+ }
+ (new NetworkWatchlistShellCommand(mContext)).exec(this, in, out, err, args, callback,
+ resultReceiver);
+ }
+
@VisibleForTesting
protected boolean startWatchlistLoggingImpl() throws RemoteException {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
new file mode 100644
index 0000000..9533823
--- /dev/null
+++ b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
@@ -0,0 +1,94 @@
+/*
+ * 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.server.net.watchlist;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.NetworkWatchlistManager;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+/**
+ * Network watchlist shell commands class, to provide a way to set temporary watchlist config for
+ * testing in shell, so CTS / GTS can use it to verify if watchlist feature is working properly.
+ */
+class NetworkWatchlistShellCommand extends ShellCommand {
+
+ final NetworkWatchlistManager mNetworkWatchlistManager;
+
+ NetworkWatchlistShellCommand(Context context) {
+ mNetworkWatchlistManager = new NetworkWatchlistManager(context);
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ switch(cmd) {
+ case "set-test-config":
+ return runSetTestConfig();
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ } catch (RemoteException e) {
+ pw.println("Remote exception: " + e);
+ }
+ return -1;
+ }
+
+ /**
+ * Method to get fd from input xml path, and set it as temporary watchlist config.
+ */
+ private int runSetTestConfig() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ final String configXmlPath = getNextArgRequired();
+ final ParcelFileDescriptor pfd = openFileForSystem(configXmlPath, "r");
+ if (pfd != null) {
+ final InputStream fileStream = new FileInputStream(pfd.getFileDescriptor());
+ WatchlistConfig.getInstance().setTestMode(fileStream);
+ }
+ pw.println("Success!");
+ } catch (RuntimeException | IOException ex) {
+ pw.println("Error: " + ex.toString());
+ return -1;
+ }
+ return 0;
+ }
+
+ @Override
+ public void onHelp() {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println("Network watchlist manager commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println("");
+ pw.println(" set-test-config your_watchlist_config.xml");
+ pw.println();
+ Intent.printIntentArgsHelp(pw , "");
+ }
+}
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
index 7387ad4..2714d5e 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
@@ -16,6 +16,7 @@
package com.android.server.net.watchlist;
+import android.os.FileUtils;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
@@ -32,6 +33,7 @@
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
@@ -50,6 +52,8 @@
// Watchlist config that pushed by ConfigUpdater.
private static final String NETWORK_WATCHLIST_DB_PATH =
"/data/misc/network_watchlist/network_watchlist.xml";
+ private static final String NETWORK_WATCHLIST_DB_FOR_TEST_PATH =
+ "/data/misc/network_watchlist/network_watchlist_for_test.xml";
// Hash for null / unknown config, a 32 byte array filled with content 0x00
private static final byte[] UNKNOWN_CONFIG_HASH = new byte[32];
@@ -80,7 +84,7 @@
private boolean mIsSecureConfig = true;
private final static WatchlistConfig sInstance = new WatchlistConfig();
- private final File mXmlFile;
+ private File mXmlFile;
private volatile CrcShaDigests mDomainDigests;
private volatile CrcShaDigests mIpDigests;
@@ -232,7 +236,38 @@
return UNKNOWN_CONFIG_HASH;
}
+ /**
+ * This method will copy temporary test config and temporary override network watchlist config
+ * in memory. When device is rebooted, temporary test config will be removed, and system will
+ * use back the original watchlist config.
+ * Also, as temporary network watchlist config is not secure, we will mark it as insecure
+ * config and will be applied to testOnly applications only.
+ */
+ public void setTestMode(InputStream testConfigInputStream) throws IOException {
+ Log.i(TAG, "Setting watchlist testing config");
+ // Copy test config
+ FileUtils.copyToFileOrThrow(testConfigInputStream,
+ new File(NETWORK_WATCHLIST_DB_FOR_TEST_PATH));
+ // Mark config as insecure, so it will be applied to testOnly applications only
+ mIsSecureConfig = false;
+ // Reload watchlist config using test config file
+ mXmlFile = new File(NETWORK_WATCHLIST_DB_FOR_TEST_PATH);
+ reloadConfig();
+ }
+
+ public void removeTestModeConfig() {
+ try {
+ final File f = new File(NETWORK_WATCHLIST_DB_FOR_TEST_PATH);
+ if (f.exists()) {
+ f.delete();
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to delete test config");
+ }
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("Watchlist config hash: " + HexDump.toHexString(getWatchlistConfigHash()));
pw.println("Domain CRC32 digest list:");
if (mDomainDigests != null) {
mDomainDigests.crc32Digests.dump(fd, pw, args);
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
index 3b6d59e..c4de4ac 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
@@ -118,6 +118,25 @@
}
/**
+ * Return if a given package has testOnly is true.
+ */
+ private boolean isPackageTestOnly(int uid) {
+ final ApplicationInfo ai;
+ try {
+ final String[] packageNames = mPm.getPackagesForUid(uid);
+ if (packageNames == null || packageNames.length == 0) {
+ Slog.e(TAG, "Couldn't find package: " + packageNames);
+ return false;
+ }
+ ai = mPm.getApplicationInfo(packageNames[0],0);
+ } catch (NameNotFoundException e) {
+ // Should not happen.
+ return false;
+ }
+ return (ai.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0;
+ }
+
+ /**
* Report network watchlist records if we collected enough data.
*/
public void reportWatchlistIfNecessary() {
@@ -146,16 +165,21 @@
}
final String cncDomain = searchAllSubDomainsInWatchlist(hostname);
if (cncDomain != null) {
- insertRecord(getDigestFromUid(uid), cncDomain, timestamp);
+ insertRecord(uid, cncDomain, timestamp);
} else {
final String cncIp = searchIpInWatchlist(ipAddresses);
if (cncIp != null) {
- insertRecord(getDigestFromUid(uid), cncIp, timestamp);
+ insertRecord(uid, cncIp, timestamp);
}
}
}
- private boolean insertRecord(byte[] digest, String cncHost, long timestamp) {
+ private boolean insertRecord(int uid, String cncHost, long timestamp) {
+ if (!mConfig.isConfigSecure() && !isPackageTestOnly(uid)) {
+ // Skip package if config is not secure and package is not TestOnly app.
+ return true;
+ }
+ final byte[] digest = getDigestFromUid(uid);
final boolean result = mDbHelper.insertNewRecord(digest, cncHost, timestamp);
tryAggregateRecords();
return result;
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java b/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
index c73b0cf..4b577bb 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
@@ -141,20 +141,19 @@
}
/**
- * Aggregate the records in database, and return a rappor encoded result.
+ * Aggregate all records before most recent local midnight in database, and return a
+ * rappor encoded result.
*/
public AggregatedResult getAggregatedRecords() {
- final long twoDaysBefore = getTwoDaysBeforeTimestamp();
- final long yesterday = getYesterdayTimestamp();
- final String selectStatement = WhiteListReportContract.TIMESTAMP + " >= ? AND " +
- WhiteListReportContract.TIMESTAMP + " <= ?";
+ final long lastMidnightTime = getLastMidnightTime();
+ final String selectStatement = WhiteListReportContract.TIMESTAMP + " < ?";
final SQLiteDatabase db = getReadableDatabase();
Cursor c = null;
try {
c = db.query(true /* distinct */,
WhiteListReportContract.TABLE, DIGEST_DOMAIN_PROJECTION, selectStatement,
- new String[]{"" + twoDaysBefore, "" + yesterday}, null, null,
+ new String[]{"" + lastMidnightTime}, null, null,
null, null);
if (c == null) {
return null;
@@ -182,23 +181,19 @@
}
/**
- * Remove all the records before yesterday.
+ * Remove all the records before most recent local midnight.
*
* @return True if success.
*/
public boolean cleanup() {
final SQLiteDatabase db = getWritableDatabase();
- final long twoDaysBefore = getTwoDaysBeforeTimestamp();
- final String clause = WhiteListReportContract.TIMESTAMP + "< " + twoDaysBefore;
+ final long midnightTime = getLastMidnightTime();
+ final String clause = WhiteListReportContract.TIMESTAMP + "< " + midnightTime;
return db.delete(WhiteListReportContract.TABLE, clause, null) != 0;
}
- static long getTwoDaysBeforeTimestamp() {
- return getMidnightTimestamp(2);
- }
-
- static long getYesterdayTimestamp() {
- return getMidnightTimestamp(1);
+ static long getLastMidnightTime() {
+ return getMidnightTimestamp(0);
}
static long getMidnightTimestamp(int daysBefore) {
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java b/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
index b78fe4d..f5ba889 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
@@ -77,7 +77,7 @@
@VisibleForTesting
protected WatchlistSettings(File xmlFile) {
- mXmlFile = new AtomicFile(xmlFile);
+ mXmlFile = new AtomicFile(xmlFile, "net-watchlist");
reloadSettings();
if (mPrivacySecretKey == null) {
// Generate a new secret key and save settings
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4c9da89..727e7ee 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -111,6 +111,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.IDeviceIdleController;
import android.os.IInterface;
import android.os.Looper;
import android.os.Message;
@@ -286,6 +287,7 @@
private AlarmManager mAlarmManager;
private ICompanionDeviceManager mCompanionManager;
private AccessibilityManager mAccessibilityManager;
+ private IDeviceIdleController mDeviceIdleController;
final IBinder mForegroundToken = new Binder();
private WorkerHandler mHandler;
@@ -659,6 +661,7 @@
@Override
public void onNotificationClick(int callingUid, int callingPid, String key) {
+ exitIdle();
synchronized (mNotificationLock) {
NotificationRecord r = mNotificationsByKey.get(key);
if (r == null) {
@@ -683,6 +686,7 @@
@Override
public void onNotificationActionClick(int callingUid, int callingPid, String key,
int actionIndex) {
+ exitIdle();
synchronized (mNotificationLock) {
NotificationRecord r = mNotificationsByKey.get(key);
if (r == null) {
@@ -812,6 +816,7 @@
@Override
public void onNotificationDirectReplied(String key) {
+ exitIdle();
synchronized (mNotificationLock) {
NotificationRecord r = mNotificationsByKey.get(key);
if (r != null) {
@@ -1280,6 +1285,8 @@
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mCompanionManager = companionManager;
mActivityManager = activityManager;
+ mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
mHandler = new WorkerHandler(looper);
mRankingThread.start();
@@ -1406,7 +1413,7 @@
AppGlobals.getPackageManager()),
new ConditionProviders(getContext(), mUserProfiles, AppGlobals.getPackageManager()),
null, snoozeHelper, new NotificationUsageStats(getContext()),
- new AtomicFile(new File(systemDir, "notification_policy.xml")),
+ new AtomicFile(new File(systemDir, "notification_policy.xml"), "notification-policy"),
(ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE),
getGroupHelper());
@@ -1533,6 +1540,15 @@
sendRegisteredOnlyBroadcast(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
}
+ private void exitIdle() {
+ try {
+ if (mDeviceIdleController != null) {
+ mDeviceIdleController.exitIdle("notification interaction");
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
private void updateNotificationChannelInt(String pkg, int uid, NotificationChannel channel,
boolean fromListener) {
if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
@@ -3421,7 +3437,7 @@
long zenLog = proto.start(NotificationServiceDumpProto.ZEN);
mZenModeHelper.dump(proto);
for (ComponentName suppressor : mEffectsSuppressors) {
- proto.write(ZenModeProto.SUPPRESSORS, suppressor.toString());
+ suppressor.writeToProto(proto, ZenModeProto.SUPPRESSORS);
}
proto.end(zenLog);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 932e4f9..7e3b551 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -129,7 +129,6 @@
mFiltering = new ZenModeFiltering(mContext);
mConditions = new ZenModeConditions(this, conditionProviders);
mServiceConfig = conditionProviders.getConfig();
-
}
public Looper getLooper() {
@@ -553,16 +552,15 @@
}
void dump(ProtoOutputStream proto) {
-
proto.write(ZenModeProto.ZEN_MODE, mZenMode);
synchronized (mConfig) {
if (mConfig.manualRule != null) {
- proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, mConfig.manualRule.toString());
+ mConfig.manualRule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
}
for (ZenRule rule : mConfig.automaticRules.values()) {
if (rule.enabled && rule.condition.state == Condition.STATE_TRUE
&& !rule.snoozing) {
- proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, rule.toString());
+ rule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
}
}
mConfig.toNotificationPolicy().writeToProto(proto, ZenModeProto.POLICY);
@@ -823,7 +821,7 @@
@VisibleForTesting
protected void applyRestrictions() {
final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
- final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+ final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
// notification restrictions
@@ -839,7 +837,7 @@
final boolean muteMediaAndSystemSounds = zenPriorityOnly && !mConfig.allowMediaSystemOther;
// total silence restrictions
final boolean muteEverything = zenSilence
- || (zenPriorityOnly && areAllBehaviorSoundsMuted());
+ || (zenPriorityOnly && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConfig));
for (int usage : AudioAttributes.SDK_USAGES) {
final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
@@ -872,12 +870,6 @@
exceptionPackages);
}
- private boolean areAllBehaviorSoundsMuted() {
- return !mConfig.allowAlarms && !mConfig.allowMediaSystemOther && !mConfig.allowReminders
- && !mConfig.allowCalls && !mConfig.allowMessages && !mConfig.allowEvents
- && !mConfig.allowRepeatCallers;
- }
-
private void applyZenToRingerMode() {
if (mAudioManager == null) return;
// force the ringer mode into compliance
@@ -892,6 +884,18 @@
}
break;
case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+ if (ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) {
+ if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
+ setPreviousRingerModeSetting(ringerModeInternal);
+ newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
+ }
+ } else {
+ if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
+ newRingerModeInternal = getPreviousRingerModeSetting();
+ setPreviousRingerModeSetting(null);
+ }
+ }
+ break;
case Global.ZEN_MODE_OFF:
if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
newRingerModeInternal = getPreviousRingerModeSetting();
@@ -1000,8 +1004,7 @@
switch (ringerModeNew) {
case AudioManager.RINGER_MODE_SILENT:
if (isChange && policy.doNotDisturbWhenSilent) {
- if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS
- && mZenMode != Global.ZEN_MODE_ALARMS) {
+ if (mZenMode == Global.ZEN_MODE_OFF) {
newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
}
setPreviousRingerModeSetting(ringerModeOld);
@@ -1011,7 +1014,10 @@
case AudioManager.RINGER_MODE_NORMAL:
if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
&& (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
- || mZenMode == Global.ZEN_MODE_ALARMS)) {
+ || mZenMode == Global.ZEN_MODE_ALARMS
+ || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+ && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
+ mConfig)))) {
newZen = Global.ZEN_MODE_OFF;
} else if (mZenMode != Global.ZEN_MODE_OFF) {
ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
@@ -1079,10 +1085,24 @@
(1 << AudioSystem.STREAM_NOTIFICATION) |
(1 << AudioSystem.STREAM_SYSTEM);
- // alarm and music streams are only affected by ringer mode when in total silence
if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+ // alarm and music streams affected by ringer mode when in total silence
streams |= (1 << AudioSystem.STREAM_ALARM) |
(1 << AudioSystem.STREAM_MUSIC);
+ } else if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
+ // alarm and music streams affected by ringer mode when in priority only with
+ // media and alarms not allowed to bypass dnd
+ if (!mConfig.allowMediaSystemOther) {
+ streams |= (1 << AudioSystem.STREAM_MUSIC);
+ } else {
+ streams &= ~(1 << AudioSystem.STREAM_MUSIC);
+ }
+
+ if (!mConfig.allowAlarms) {
+ streams |= (1 << AudioSystem.STREAM_ALARM);
+ } else {
+ streams &= ~(1 << AudioSystem.STREAM_ALARM);
+ }
} else {
streams &= ~((1 << AudioSystem.STREAM_ALARM) |
(1 << AudioSystem.STREAM_MUSIC));
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 2041de6..4bc4a7e 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -228,7 +228,7 @@
@NonNull final Installer installer) {
super(context);
mSettingsFile =
- new AtomicFile(new File(Environment.getDataSystemDirectory(), "overlays.xml"));
+ new AtomicFile(new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
mPackageManager = new PackageManagerHelper();
mUserManager = UserManagerService.getInstance();
IdmapManager im = new IdmapManager(installer);
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index af20cd7..30088dd 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -44,6 +44,7 @@
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.Xml;
+
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.SomeArgs;
@@ -51,6 +52,7 @@
import com.android.internal.util.XmlUtils;
import libcore.io.IoUtils;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -295,25 +297,26 @@
continue;
}
+ String cookieName = currentCookieFile.getName();
+ String currentCookieSha256 =
+ cookieName.substring(INSTANT_APP_COOKIE_FILE_PREFIX.length(),
+ cookieName.length() - INSTANT_APP_COOKIE_FILE_SIFFIX.length());
+
// Before we used only the first signature to compute the SHA 256 but some
// apps could be singed by multiple certs and the cert order is undefined.
// We prefer the modern computation procedure where all certs are taken
// into account but also allow the value from the old computation to avoid
// data loss.
- final String[] signaturesSha256Digests = PackageUtils.computeSignaturesSha256Digests(
- pkg.mSigningDetails.signatures);
- final String signaturesSha256Digest = PackageUtils.computeSignaturesSha256Digest(
- signaturesSha256Digests);
-
- // We prefer a match based on all signatures
- if (currentCookieFile.equals(computeInstantCookieFile(pkg.packageName,
- signaturesSha256Digest, userId))) {
+ if (pkg.mSigningDetails.checkCapability(currentCookieSha256,
+ PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
return;
}
- // For backwards compatibility we accept match based on first signature
- if (pkg.mSigningDetails.signatures.length > 1 && currentCookieFile.equals(computeInstantCookieFile(
- pkg.packageName, signaturesSha256Digests[0], userId))) {
+ // For backwards compatibility we accept match based on first signature only in the case
+ // of multiply-signed packagse
+ final String[] signaturesSha256Digests =
+ PackageUtils.computeSignaturesSha256Digests(pkg.mSigningDetails.signatures);
+ if (signaturesSha256Digests[0].equals(currentCookieSha256)) {
return;
}
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index 30072d4..af446ba 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -40,26 +40,33 @@
import android.content.pm.InstantAppResolveInfo;
import android.content.pm.InstantAppResolveInfo.InstantAppDigest;
import android.metrics.LogMaker;
+import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
+import android.text.TextUtils;
import android.util.Log;
+import android.util.Slog;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.server.pm.EphemeralResolverConnection.ConnectionException;
-import com.android.server.pm.EphemeralResolverConnection.PhaseTwoCallback;
+import com.android.server.pm.InstantAppResolverConnection.ConnectionException;
+import com.android.server.pm.InstantAppResolverConnection.PhaseTwoCallback;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import java.util.UUID;
/** @hide */
public abstract class InstantAppResolver {
- private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
+ private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;
private static final String TAG = "PackageManager";
private static final int RESOLUTION_SUCCESS = 0;
@@ -79,6 +86,7 @@
public @interface ResolutionStatus {}
private static MetricsLogger sMetricsLogger;
+
private static MetricsLogger getLogger() {
if (sMetricsLogger == null) {
sMetricsLogger = new MetricsLogger();
@@ -86,26 +94,49 @@
return sMetricsLogger;
}
- public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne(Context context,
- EphemeralResolverConnection connection, InstantAppRequest requestObj) {
+ /**
+ * Returns an intent with potential PII removed from the original intent. Fields removed
+ * include extras and the host + path of the data, if defined.
+ */
+ public static Intent sanitizeIntent(Intent origIntent) {
+ final Intent sanitizedIntent;
+ sanitizedIntent = new Intent(origIntent.getAction());
+ Set<String> categories = origIntent.getCategories();
+ if (categories != null) {
+ for (String category : categories) {
+ sanitizedIntent.addCategory(category);
+ }
+ }
+ Uri sanitizedUri = origIntent.getData() == null
+ ? null
+ : Uri.fromParts(origIntent.getScheme(), "", "");
+ sanitizedIntent.setDataAndType(sanitizedUri, origIntent.getType());
+ sanitizedIntent.addFlags(origIntent.getFlags());
+ sanitizedIntent.setPackage(origIntent.getPackage());
+ return sanitizedIntent;
+ }
+
+ public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne(
+ InstantAppResolverConnection connection, InstantAppRequest requestObj) {
final long startTime = System.currentTimeMillis();
final String token = UUID.randomUUID().toString();
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Log.d(TAG, "[" + token + "] Phase1; resolving");
}
- final Intent intent = requestObj.origIntent;
- final InstantAppDigest digest =
- new InstantAppDigest(intent.getData().getHost(), 5 /*maxDigests*/);
+ final Intent origIntent = requestObj.origIntent;
+ final Intent sanitizedIntent = sanitizeIntent(origIntent);
+
+ final InstantAppDigest digest = getInstantAppDigest(origIntent);
final int[] shaPrefix = digest.getDigestPrefix();
AuxiliaryResolveInfo resolveInfo = null;
@ResolutionStatus int resolutionStatus = RESOLUTION_SUCCESS;
try {
final List<InstantAppResolveInfo> instantAppResolveInfoList =
- connection.getInstantAppResolveInfoList(shaPrefix, token);
+ connection.getInstantAppResolveInfoList(sanitizedIntent, shaPrefix, token);
if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) {
resolveInfo = InstantAppResolver.filterInstantAppIntent(
- instantAppResolveInfoList, intent, requestObj.resolvedType,
- requestObj.userId, intent.getPackage(), digest, token);
+ instantAppResolveInfoList, origIntent, requestObj.resolvedType,
+ requestObj.userId, origIntent.getPackage(), digest, token);
}
} catch (ConnectionException e) {
if (e.failure == ConnectionException.FAILURE_BIND) {
@@ -121,7 +152,7 @@
logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE, startTime, token,
resolutionStatus);
}
- if (DEBUG_EPHEMERAL && resolveInfo == null) {
+ if (DEBUG_INSTANT && resolveInfo == null) {
if (resolutionStatus == RESOLUTION_BIND_TIMEOUT) {
Log.d(TAG, "[" + token + "] Phase1; bind timed out");
} else if (resolutionStatus == RESOLUTION_CALL_TIMEOUT) {
@@ -135,81 +166,67 @@
return resolveInfo;
}
+ private static InstantAppDigest getInstantAppDigest(Intent origIntent) {
+ return origIntent.getData() != null && !TextUtils.isEmpty(origIntent.getData().getHost())
+ ? new InstantAppDigest(origIntent.getData().getHost(), 5 /*maxDigests*/)
+ : InstantAppDigest.UNDEFINED;
+ }
+
public static void doInstantAppResolutionPhaseTwo(Context context,
- EphemeralResolverConnection connection, InstantAppRequest requestObj,
+ InstantAppResolverConnection connection, InstantAppRequest requestObj,
ActivityInfo instantAppInstaller, Handler callbackHandler) {
final long startTime = System.currentTimeMillis();
final String token = requestObj.responseObj.token;
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Log.d(TAG, "[" + token + "] Phase2; resolving");
}
- final Intent intent = requestObj.origIntent;
- final String hostName = intent.getData().getHost();
- final InstantAppDigest digest = new InstantAppDigest(hostName, 5 /*maxDigests*/);
+ final Intent origIntent = requestObj.origIntent;
+ final Intent sanitizedIntent = sanitizeIntent(origIntent);
+ final InstantAppDigest digest = getInstantAppDigest(origIntent);
final int[] shaPrefix = digest.getDigestPrefix();
final PhaseTwoCallback callback = new PhaseTwoCallback() {
@Override
void onPhaseTwoResolved(List<InstantAppResolveInfo> instantAppResolveInfoList,
long startTime) {
- final String packageName;
- final String splitName;
- final long versionCode;
final Intent failureIntent;
- final Bundle extras;
if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) {
final AuxiliaryResolveInfo instantAppIntentInfo =
InstantAppResolver.filterInstantAppIntent(
- instantAppResolveInfoList, intent, null /*resolvedType*/,
- 0 /*userId*/, intent.getPackage(), digest, token);
- if (instantAppIntentInfo != null
- && instantAppIntentInfo.resolveInfo != null) {
- packageName = instantAppIntentInfo.resolveInfo.getPackageName();
- splitName = instantAppIntentInfo.splitName;
- versionCode = instantAppIntentInfo.resolveInfo.getVersionCode();
+ instantAppResolveInfoList, origIntent, null /*resolvedType*/,
+ 0 /*userId*/, origIntent.getPackage(), digest, token);
+ if (instantAppIntentInfo != null) {
failureIntent = instantAppIntentInfo.failureIntent;
- extras = instantAppIntentInfo.resolveInfo.getExtras();
} else {
- packageName = null;
- splitName = null;
- versionCode = -1;
failureIntent = null;
- extras = null;
}
} else {
- packageName = null;
- splitName = null;
- versionCode = -1;
failureIntent = null;
- extras = null;
}
final Intent installerIntent = buildEphemeralInstallerIntent(
- Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE,
requestObj.origIntent,
+ sanitizedIntent,
failureIntent,
requestObj.callingPackage,
requestObj.verificationBundle,
requestObj.resolvedType,
requestObj.userId,
- packageName,
- splitName,
requestObj.responseObj.installFailureActivity,
- versionCode,
token,
- extras,
- false /*needsPhaseTwo*/);
+ false /*needsPhaseTwo*/,
+ requestObj.responseObj.filters);
installerIntent.setComponent(new ComponentName(
instantAppInstaller.packageName, instantAppInstaller.name));
logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO, startTime, token,
- packageName != null ? RESOLUTION_SUCCESS : RESOLUTION_FAILURE);
+ requestObj.responseObj.filters != null ? RESOLUTION_SUCCESS : RESOLUTION_FAILURE);
context.startActivity(installerIntent);
}
};
try {
- connection.getInstantAppIntentFilterList(
- shaPrefix, token, hostName, callback, callbackHandler, startTime);
+ connection.getInstantAppIntentFilterList(sanitizedIntent, shaPrefix, token, callback,
+ callbackHandler, startTime);
} catch (ConnectionException e) {
@ResolutionStatus int resolutionStatus = RESOLUTION_FAILURE;
if (e.failure == ConnectionException.FAILURE_BIND) {
@@ -217,7 +234,7 @@
}
logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO, startTime, token,
resolutionStatus);
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
if (resolutionStatus == RESOLUTION_BIND_TIMEOUT) {
Log.d(TAG, "[" + token + "] Phase2; bind timed out");
} else {
@@ -231,49 +248,53 @@
* Builds and returns an intent to launch the instant installer.
*/
public static Intent buildEphemeralInstallerIntent(
- @NonNull String action,
@NonNull Intent origIntent,
- @NonNull Intent failureIntent,
+ @NonNull Intent sanitizedIntent,
+ @Nullable Intent failureIntent,
@NonNull String callingPackage,
@Nullable Bundle verificationBundle,
@NonNull String resolvedType,
int userId,
- @NonNull String instantAppPackageName,
- @Nullable String instantAppSplitName,
@Nullable ComponentName installFailureActivity,
- long versionCode,
@Nullable String token,
- @Nullable Bundle extras,
- boolean needsPhaseTwo) {
+ boolean needsPhaseTwo,
+ List<AuxiliaryResolveInfo.AuxiliaryFilter> filters) {
// Construct the intent that launches the instant installer
int flags = origIntent.getFlags();
- final Intent intent = new Intent(action);
+ final Intent intent = new Intent();
intent.setFlags(flags
| Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
if (token != null) {
+ // TODO(b/72700831): remove populating old extra
intent.putExtra(Intent.EXTRA_EPHEMERAL_TOKEN, token);
+ intent.putExtra(Intent.EXTRA_INSTANT_APP_TOKEN, token);
}
if (origIntent.getData() != null) {
+ // TODO(b/72700831): remove populating old extra
intent.putExtra(Intent.EXTRA_EPHEMERAL_HOSTNAME, origIntent.getData().getHost());
+ intent.putExtra(Intent.EXTRA_INSTANT_APP_HOSTNAME, origIntent.getData().getHost());
}
intent.putExtra(Intent.EXTRA_INSTANT_APP_ACTION, origIntent.getAction());
- if (extras != null) {
- intent.putExtra(Intent.EXTRA_INSTANT_APP_EXTRAS, extras);
- }
+ intent.putExtra(Intent.EXTRA_INTENT, sanitizedIntent);
- // We have all of the data we need; just start the installer without a second phase
- if (!needsPhaseTwo) {
- // Intent that is launched if the package couldn't be installed for any reason.
+ if (needsPhaseTwo) {
+ intent.setAction(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE);
+ } else {
+ // We have all of the data we need; just start the installer without a second phase
if (failureIntent != null || installFailureActivity != null) {
+ // Intent that is launched if the package couldn't be installed for any reason.
try {
final Intent onFailureIntent;
if (installFailureActivity != null) {
onFailureIntent = new Intent();
onFailureIntent.setComponent(installFailureActivity);
- onFailureIntent.putExtra(Intent.EXTRA_SPLIT_NAME, instantAppSplitName);
+ if (filters != null && filters.size() == 1) {
+ onFailureIntent.putExtra(Intent.EXTRA_SPLIT_NAME,
+ filters.get(0).splitName);
+ }
onFailureIntent.putExtra(Intent.EXTRA_INTENT, origIntent);
} else {
onFailureIntent = failureIntent;
@@ -288,8 +309,10 @@
| PendingIntent.FLAG_ONE_SHOT
| PendingIntent.FLAG_IMMUTABLE,
null /*bOptions*/, userId);
- intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE,
- new IntentSender(failureIntentTarget));
+ IntentSender failureSender = new IntentSender(failureIntentTarget);
+ // TODO(b/72700831): remove populating old extra
+ intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, failureSender);
+ intent.putExtra(Intent.EXTRA_INSTANT_APP_FAILURE, failureSender);
} catch (RemoteException ignore) { /* ignore; same process */ }
}
@@ -306,20 +329,40 @@
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
| PendingIntent.FLAG_IMMUTABLE,
null /*bOptions*/, userId);
- intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS,
- new IntentSender(successIntentTarget));
+ IntentSender successSender = new IntentSender(successIntentTarget);
+ // TODO(b/72700831): remove populating old extra
+ intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, successSender);
+ intent.putExtra(Intent.EXTRA_INSTANT_APP_SUCCESS, successSender);
} catch (RemoteException ignore) { /* ignore; same process */ }
-
- intent.putExtra(Intent.EXTRA_PACKAGE_NAME, instantAppPackageName);
- intent.putExtra(Intent.EXTRA_SPLIT_NAME, instantAppSplitName);
- intent.putExtra(Intent.EXTRA_VERSION_CODE, (int) (versionCode & 0x7fffffff));
- intent.putExtra(Intent.EXTRA_LONG_VERSION_CODE, versionCode);
- intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage);
if (verificationBundle != null) {
intent.putExtra(Intent.EXTRA_VERIFICATION_BUNDLE, verificationBundle);
}
- }
+ intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage);
+ if (filters != null) {
+ Bundle resolvableFilters[] = new Bundle[filters.size()];
+ for (int i = 0, max = filters.size(); i < max; i++) {
+ Bundle resolvableFilter = new Bundle();
+ AuxiliaryResolveInfo.AuxiliaryFilter filter = filters.get(i);
+ resolvableFilter.putBoolean(Intent.EXTRA_UNKNOWN_INSTANT_APP,
+ filter.resolveInfo != null
+ && filter.resolveInfo.shouldLetInstallerDecide());
+ resolvableFilter.putString(Intent.EXTRA_PACKAGE_NAME, filter.packageName);
+ resolvableFilter.putString(Intent.EXTRA_SPLIT_NAME, filter.splitName);
+ resolvableFilter.putLong(Intent.EXTRA_LONG_VERSION_CODE, filter.versionCode);
+ resolvableFilter.putBundle(Intent.EXTRA_INSTANT_APP_EXTRAS, filter.extras);
+ resolvableFilters[i] = resolvableFilter;
+ if (i == 0) {
+ // for backwards compat, always set the first result on the intent and add
+ // the int version code
+ intent.putExtras(resolvableFilter);
+ intent.putExtra(Intent.EXTRA_VERSION_CODE, (int) filter.versionCode);
+ }
+ }
+ intent.putExtra(Intent.EXTRA_INSTANT_APP_BUNDLES, resolvableFilters);
+ }
+ intent.setAction(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE);
+ }
return intent;
}
@@ -330,69 +373,134 @@
final int[] shaPrefix = digest.getDigestPrefix();
final byte[][] digestBytes = digest.getDigestBytes();
final Intent failureIntent = new Intent(origIntent);
+ boolean requiresSecondPhase = false;
failureIntent.setFlags(failureIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
failureIntent.setLaunchToken(token);
- // Go in reverse order so we match the narrowest scope first.
- for (int i = shaPrefix.length - 1; i >= 0 ; --i) {
- for (InstantAppResolveInfo instantAppInfo : instantAppResolveInfoList) {
- if (!Arrays.equals(digestBytes[i], instantAppInfo.getDigestBytes())) {
+ ArrayList<AuxiliaryResolveInfo.AuxiliaryFilter> filters = null;
+ boolean isWebIntent = origIntent.isBrowsableWebIntent();
+ for (InstantAppResolveInfo instantAppResolveInfo : instantAppResolveInfoList) {
+ if (shaPrefix.length > 0 && instantAppResolveInfo.shouldLetInstallerDecide()) {
+ Slog.e(TAG, "InstantAppResolveInfo with mShouldLetInstallerDecide=true when digest"
+ + " provided; ignoring");
+ continue;
+ }
+ byte[] filterDigestBytes = instantAppResolveInfo.getDigestBytes();
+ // Only include matching digests if we have a prefix and we're either dealing with a
+ // web intent or the resolveInfo specifies digest details.
+ if (shaPrefix.length > 0 && (isWebIntent || filterDigestBytes.length > 0)) {
+ boolean matchFound = false;
+ // Go in reverse order so we match the narrowest scope first.
+ for (int i = shaPrefix.length - 1; i >= 0; --i) {
+ if (Arrays.equals(digestBytes[i], filterDigestBytes)) {
+ matchFound = true;
+ break;
+ }
+ }
+ if (!matchFound) {
continue;
}
- if (packageName != null
- && !packageName.equals(instantAppInfo.getPackageName())) {
- continue;
+ }
+ // We matched a resolve info; resolve the filters to see if anything matches completely.
+ List<AuxiliaryResolveInfo.AuxiliaryFilter> matchFilters = computeResolveFilters(
+ origIntent, resolvedType, userId, packageName, token, instantAppResolveInfo);
+ if (matchFilters != null) {
+ if (matchFilters.isEmpty()) {
+ requiresSecondPhase = true;
}
- final List<InstantAppIntentFilter> instantAppFilters =
- instantAppInfo.getIntentFilters();
- // No filters; we need to start phase two
- if (instantAppFilters == null || instantAppFilters.isEmpty()) {
- if (DEBUG_EPHEMERAL) {
- Log.d(TAG, "No app filters; go to phase 2");
- }
- return new AuxiliaryResolveInfo(instantAppInfo,
- new IntentFilter(Intent.ACTION_VIEW) /*intentFilter*/,
- null /*splitName*/, token, true /*needsPhase2*/,
- null /*failureIntent*/);
- }
- // We have a domain match; resolve the filters to see if anything matches.
- final PackageManagerService.EphemeralIntentResolver instantAppResolver =
- new PackageManagerService.EphemeralIntentResolver();
- for (int j = instantAppFilters.size() - 1; j >= 0; --j) {
- final InstantAppIntentFilter instantAppFilter = instantAppFilters.get(j);
- final List<IntentFilter> splitFilters = instantAppFilter.getFilters();
- if (splitFilters == null || splitFilters.isEmpty()) {
- continue;
- }
- for (int k = splitFilters.size() - 1; k >= 0; --k) {
- final AuxiliaryResolveInfo intentInfo =
- new AuxiliaryResolveInfo(instantAppInfo,
- splitFilters.get(k), instantAppFilter.getSplitName(),
- token, false /*needsPhase2*/, failureIntent);
- instantAppResolver.addFilter(intentInfo);
- }
- }
- List<AuxiliaryResolveInfo> matchedResolveInfoList = instantAppResolver.queryIntent(
- origIntent, resolvedType, false /*defaultOnly*/, userId);
- if (!matchedResolveInfoList.isEmpty()) {
- if (DEBUG_EPHEMERAL) {
- final AuxiliaryResolveInfo info = matchedResolveInfoList.get(0);
- Log.d(TAG, "[" + token + "] Found match;"
- + " package: " + info.packageName
- + ", split: " + info.splitName
- + ", versionCode: " + info.versionCode);
- }
- return matchedResolveInfoList.get(0);
- } else if (DEBUG_EPHEMERAL) {
- Log.d(TAG, "[" + token + "] No matches found"
- + " package: " + instantAppInfo.getPackageName()
- + ", versionCode: " + instantAppInfo.getVersionCode());
+ if (filters == null) {
+ filters = new ArrayList<>(matchFilters);
+ } else {
+ filters.addAll(matchFilters);
}
}
}
+ if (filters != null && !filters.isEmpty()) {
+ return new AuxiliaryResolveInfo(token, requiresSecondPhase, failureIntent, filters);
+ }
// Hash or filter mis-match; no instant apps for this domain.
return null;
}
+ /**
+ * Returns one of three states: <p/>
+ * <ul>
+ * <li>{@code null} if there are no matches will not be; resolution is unnecessary.</li>
+ * <li>An empty list signifying that a 2nd phase of resolution is required.</li>
+ * <li>A populated list meaning that matches were found and should be sent directly to the
+ * installer</li>
+ * </ul>
+ *
+ */
+ private static List<AuxiliaryResolveInfo.AuxiliaryFilter> computeResolveFilters(
+ Intent origIntent, String resolvedType, int userId, String packageName, String token,
+ InstantAppResolveInfo instantAppInfo) {
+ if (instantAppInfo.shouldLetInstallerDecide()) {
+ return Collections.singletonList(
+ new AuxiliaryResolveInfo.AuxiliaryFilter(
+ instantAppInfo, null /* splitName */,
+ instantAppInfo.getExtras()));
+ }
+ if (packageName != null
+ && !packageName.equals(instantAppInfo.getPackageName())) {
+ return null;
+ }
+ final List<InstantAppIntentFilter> instantAppFilters =
+ instantAppInfo.getIntentFilters();
+ if (instantAppFilters == null || instantAppFilters.isEmpty()) {
+ // No filters on web intent; no matches, 2nd phase unnecessary.
+ if (origIntent.isBrowsableWebIntent()) {
+ return null;
+ }
+ // No filters; we need to start phase two
+ if (DEBUG_INSTANT) {
+ Log.d(TAG, "No app filters; go to phase 2");
+ }
+ return Collections.emptyList();
+ }
+ final PackageManagerService.InstantAppIntentResolver instantAppResolver =
+ new PackageManagerService.InstantAppIntentResolver();
+ for (int j = instantAppFilters.size() - 1; j >= 0; --j) {
+ final InstantAppIntentFilter instantAppFilter = instantAppFilters.get(j);
+ final List<IntentFilter> splitFilters = instantAppFilter.getFilters();
+ if (splitFilters == null || splitFilters.isEmpty()) {
+ continue;
+ }
+ for (int k = splitFilters.size() - 1; k >= 0; --k) {
+ IntentFilter filter = splitFilters.get(k);
+ Iterator<IntentFilter.AuthorityEntry> authorities =
+ filter.authoritiesIterator();
+ // ignore http/s-only filters.
+ if ((authorities == null || !authorities.hasNext())
+ && (filter.hasDataScheme("http") || filter.hasDataScheme("https"))
+ && filter.hasAction(Intent.ACTION_VIEW)
+ && filter.hasCategory(Intent.CATEGORY_BROWSABLE)) {
+ continue;
+ }
+ instantAppResolver.addFilter(
+ new AuxiliaryResolveInfo.AuxiliaryFilter(
+ filter,
+ instantAppInfo,
+ instantAppFilter.getSplitName(),
+ instantAppInfo.getExtras()
+ ));
+ }
+ }
+ List<AuxiliaryResolveInfo.AuxiliaryFilter> matchedResolveInfoList =
+ instantAppResolver.queryIntent(
+ origIntent, resolvedType, false /*defaultOnly*/, userId);
+ if (!matchedResolveInfoList.isEmpty()) {
+ if (DEBUG_INSTANT) {
+ Log.d(TAG, "[" + token + "] Found match(es); " + matchedResolveInfoList);
+ }
+ return matchedResolveInfoList;
+ } else if (DEBUG_INSTANT) {
+ Log.d(TAG, "[" + token + "] No matches found"
+ + " package: " + instantAppInfo.getPackageName()
+ + ", versionCode: " + instantAppInfo.getVersionCode());
+ }
+ return null;
+ }
+
private static void logMetrics(int action, long startTime, String token,
@ResolutionStatus int status) {
final LogMaker logMaker = new LogMaker(action)
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/InstantAppResolverConnection.java
similarity index 85%
rename from services/core/java/com/android/server/pm/EphemeralResolverConnection.java
rename to services/core/java/com/android/server/pm/InstantAppResolverConnection.java
index b5ddf8c..a9ee411 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolverConnection.java
@@ -37,33 +37,29 @@
import android.util.TimedRemoteCaller;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.os.TransferPipe;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeoutException;
/**
- * Represents a remote ephemeral resolver. It is responsible for binding to the remote
+ * Represents a remote instant app resolver. It is responsible for binding to the remote
* service and handling all interactions in a timely manner.
* @hide
*/
-final class EphemeralResolverConnection implements DeathRecipient {
+final class InstantAppResolverConnection implements DeathRecipient {
private static final String TAG = "PackageManager";
// This is running in a critical section and the timeout must be sufficiently low
private static final long BIND_SERVICE_TIMEOUT_MS =
Build.IS_ENG ? 500 : 300;
private static final long CALL_SERVICE_TIMEOUT_MS =
Build.IS_ENG ? 200 : 100;
- private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
+ private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;
private final Object mLock = new Object();
- private final GetEphemeralResolveInfoCaller mGetEphemeralResolveInfoCaller =
- new GetEphemeralResolveInfoCaller();
+ private final GetInstantAppResolveInfoCaller mGetInstantAppResolveInfoCaller =
+ new GetInstantAppResolveInfoCaller();
private final ServiceConnection mServiceConnection = new MyServiceConnection();
private final Context mContext;
/** Intent used to bind to the service */
@@ -78,14 +74,14 @@
@GuardedBy("mLock")
private IInstantAppResolver mRemoteInstance;
- public EphemeralResolverConnection(
+ public InstantAppResolverConnection(
Context context, ComponentName componentName, String action) {
mContext = context;
mIntent = new Intent(action).setComponent(componentName);
}
- public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(int hashPrefix[],
- String token) throws ConnectionException {
+ public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(Intent sanitizedIntent,
+ int hashPrefix[], String token) throws ConnectionException {
throwIfCalledOnMainThread();
IInstantAppResolver target = null;
try {
@@ -97,8 +93,8 @@
throw new ConnectionException(ConnectionException.FAILURE_INTERRUPTED);
}
try {
- return mGetEphemeralResolveInfoCaller
- .getEphemeralResolveInfoList(target, hashPrefix, token);
+ return mGetInstantAppResolveInfoCaller
+ .getInstantAppResolveInfoList(target, sanitizedIntent, hashPrefix, token);
} catch (TimeoutException e) {
throw new ConnectionException(ConnectionException.FAILURE_CALL);
} catch (RemoteException ignore) {
@@ -111,26 +107,22 @@
return null;
}
- public final void getInstantAppIntentFilterList(int hashPrefix[], String token,
- String hostName, PhaseTwoCallback callback, Handler callbackHandler,
- final long startTime) throws ConnectionException {
+ public final void getInstantAppIntentFilterList(Intent sanitizedIntent, int hashPrefix[],
+ String token, PhaseTwoCallback callback, Handler callbackHandler, final long startTime)
+ throws ConnectionException {
final IRemoteCallback remoteCallback = new IRemoteCallback.Stub() {
@Override
public void sendResult(Bundle data) throws RemoteException {
final ArrayList<InstantAppResolveInfo> resolveList =
data.getParcelableArrayList(
InstantAppResolverService.EXTRA_RESOLVE_INFO);
- callbackHandler.post(new Runnable() {
- @Override
- public void run() {
- callback.onPhaseTwoResolved(resolveList, startTime);
- }
- });
+ callbackHandler.post(() -> callback.onPhaseTwoResolved(resolveList, startTime));
}
};
try {
getRemoteInstanceLazy(token)
- .getInstantAppIntentFilterList(hashPrefix, token, hostName, remoteCallback);
+ .getInstantAppIntentFilterList(sanitizedIntent, hashPrefix, token,
+ remoteCallback);
} catch (TimeoutException e) {
throw new ConnectionException(ConnectionException.FAILURE_BIND);
} catch (InterruptedException e) {
@@ -174,7 +166,7 @@
if (mBindState == STATE_PENDING) {
// there is a pending bind, let's see if we can use it.
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.i(TAG, "[" + token + "] Previous bind timed out; waiting for connection");
}
try {
@@ -191,7 +183,7 @@
if (mBindState == STATE_BINDING) {
// someone was binding when we called bind(), or they raced ahead while we were
// waiting in the PENDING case; wait for their result instead. Last chance!
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.i(TAG, "[" + token + "] Another thread is binding; waiting for connection");
}
waitForBindLocked(token);
@@ -209,12 +201,12 @@
IInstantAppResolver instance = null;
try {
if (doUnbind) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.i(TAG, "[" + token + "] Previous connection never established; rebinding");
}
mContext.unbindService(mServiceConnection);
}
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "[" + token + "] Binding to instant app resolver");
}
final int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
@@ -250,7 +242,7 @@
@Override
public void binderDied() {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.d(TAG, "Binder to instant app resolver died");
}
synchronized (mLock) {
@@ -289,7 +281,7 @@
private final class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.d(TAG, "Connected to instant app resolver");
}
synchronized (mLock) {
@@ -298,7 +290,7 @@
mBindState = STATE_IDLE;
}
try {
- service.linkToDeath(EphemeralResolverConnection.this, 0 /*flags*/);
+ service.linkToDeath(InstantAppResolverConnection.this, 0 /*flags*/);
} catch (RemoteException e) {
handleBinderDiedLocked();
}
@@ -308,7 +300,7 @@
@Override
public void onServiceDisconnected(ComponentName name) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.d(TAG, "Disconnected from instant app resolver");
}
synchronized (mLock) {
@@ -317,11 +309,11 @@
}
}
- private static final class GetEphemeralResolveInfoCaller
+ private static final class GetInstantAppResolveInfoCaller
extends TimedRemoteCaller<List<InstantAppResolveInfo>> {
private final IRemoteCallback mCallback;
- public GetEphemeralResolveInfoCaller() {
+ public GetInstantAppResolveInfoCaller() {
super(CALL_SERVICE_TIMEOUT_MS);
mCallback = new IRemoteCallback.Stub() {
@Override
@@ -336,11 +328,12 @@
};
}
- public List<InstantAppResolveInfo> getEphemeralResolveInfoList(
- IInstantAppResolver target, int hashPrefix[], String token)
+ public List<InstantAppResolveInfo> getInstantAppResolveInfoList(
+ IInstantAppResolver target, Intent sanitizedIntent, int hashPrefix[], String token)
throws RemoteException, TimeoutException {
final int sequence = onBeforeRemoteCall();
- target.getInstantAppResolveInfoList(hashPrefix, token, sequence, mCallback);
+ target.getInstantAppResolveInfoList(sanitizedIntent, hashPrefix, token, sequence,
+ mCallback);
return getResultTimed(sequence);
}
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 5bf38dc..10e05cf 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -362,9 +362,10 @@
continue;
}
- // If the path is in /system or /vendor, ignore. It will have been ota-dexopted into
- // /data/ota and moved into the dalvik-cache already.
- if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")) {
+ // If the path is in /system, /vendor or /product, ignore. It will have been
+ // ota-dexopted into /data/ota and moved into the dalvik-cache already.
+ if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")
+ || pkg.codePath.startsWith("/product")) {
continue;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 16fae99..59f9dae 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -58,6 +58,7 @@
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SELinux;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
@@ -193,7 +194,8 @@
mCallbacks = new Callbacks(mInstallThread.getLooper());
mSessionsFile = new AtomicFile(
- new File(Environment.getDataSystemDirectory(), "install_sessions.xml"));
+ new File(Environment.getDataSystemDirectory(), "install_sessions.xml"),
+ "package-session");
mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
mSessionsDir.mkdirs();
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 837a118..89fbd17 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -108,8 +108,6 @@
import static com.android.server.pm.PackageManagerServiceUtils.getCompressedFiles;
import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTime;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
-import static com.android.server.pm.PackageManagerServiceUtils.signingDetailsHasCertificate;
-import static com.android.server.pm.PackageManagerServiceUtils.signingDetailsHasSha256Certificate;
import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS;
@@ -246,6 +244,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Base64;
+import android.util.ByteStringUtils;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.ExceptionUtils;
@@ -424,7 +423,7 @@
public static final boolean DEBUG_DEXOPT = false;
private static final boolean DEBUG_ABI_SELECTION = false;
- private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
+ private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;
private static final boolean DEBUG_TRIAGED_MISSING = false;
private static final boolean DEBUG_APP_DATA = false;
@@ -441,6 +440,7 @@
private static final int NFC_UID = Process.NFC_UID;
private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
private static final int SHELL_UID = Process.SHELL_UID;
+ private static final int SE_UID = Process.SE_UID;
// Suffix used during package installation when copying/moving
// package apks to install directory.
@@ -466,6 +466,7 @@
static final int SCAN_AS_PRIVILEGED = 1<<18;
static final int SCAN_AS_OEM = 1<<19;
static final int SCAN_AS_VENDOR = 1<<20;
+ static final int SCAN_AS_PRODUCT = 1<<21;
@IntDef(flag = true, prefix = { "SCAN_" }, value = {
SCAN_NO_DEX,
@@ -570,6 +571,8 @@
private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
+ private static final String PRODUCT_OVERLAY_DIR = "/product/overlay";
+
private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB = "pm.dexopt.priv-apps-oob";
/** Canonical intent used to identify what counts as a "web browser" app */
@@ -579,6 +582,7 @@
sBrowserIntent.setAction(Intent.ACTION_VIEW);
sBrowserIntent.addCategory(Intent.CATEGORY_BROWSABLE);
sBrowserIntent.setData(Uri.parse("http:"));
+ sBrowserIntent.addFlags(Intent.FLAG_IGNORE_EPHEMERAL);
}
/**
@@ -977,7 +981,7 @@
private int mIntentFilterVerificationToken = 0;
/** The service connection to the ephemeral resolver */
- final EphemeralResolverConnection mInstantAppResolverConnection;
+ final InstantAppResolverConnection mInstantAppResolverConnection;
/** Component used to show resolver settings for Instant Apps */
final ComponentName mInstantAppResolverSettingsComponent;
@@ -2405,6 +2409,8 @@
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+ mSettings.addSharedUserLPw("android.uid.se", SE_UID,
+ ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
@@ -2552,7 +2558,7 @@
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}
- // Collect vendor overlay packages. (Do this before scanning any apps.)
+ // Collect vendor/product overlay packages. (Do this before scanning any apps.)
// For security and version matching reason, only consider
// overlay packages if they reside in the right directory.
scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
@@ -2562,6 +2568,13 @@
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR,
0);
+ scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT,
+ 0);
mParallelPackageParserCallback.findStaticOverlayPackages();
@@ -2595,8 +2608,7 @@
0);
// Collected privileged vendor packages.
- File privilegedVendorAppDir = new File(Environment.getVendorDirectory(),
- "priv-app");
+ File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
try {
privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
} catch (IOException e) {
@@ -2636,6 +2648,37 @@
| SCAN_AS_OEM,
0);
+ // Collected privileged product packages.
+ File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
+ try {
+ privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
+ scanDirTracedLI(privilegedProductAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT
+ | SCAN_AS_PRIVILEGED,
+ 0);
+
+ // Collect ordinary product packages.
+ File productAppDir = new File(Environment.getProductDirectory(), "app");
+ try {
+ productAppDir = productAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
+ scanDirTracedLI(productAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT,
+ 0);
+
// Prune any system packages that no longer exist.
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
// Stub packages must either be replaced with full versions in the /data
@@ -2842,6 +2885,23 @@
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_OEM;
+ } else if (FileUtils.contains(privilegedProductAppDir, scanFile)) {
+ reparseFlags =
+ mDefParseFlags |
+ PackageParser.PARSE_IS_SYSTEM_DIR;
+ rescanFlags =
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT
+ | SCAN_AS_PRIVILEGED;
+ } else if (FileUtils.contains(productAppDir, scanFile)) {
+ reparseFlags =
+ mDefParseFlags |
+ PackageParser.PARSE_IS_SYSTEM_DIR;
+ rescanFlags =
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT;
} else {
Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
continue;
@@ -3089,10 +3149,10 @@
final Pair<ComponentName, String> instantAppResolverComponent =
getInstantAppResolverLPr();
if (instantAppResolverComponent != null) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent);
}
- mInstantAppResolverConnection = new EphemeralResolverConnection(
+ mInstantAppResolverConnection = new InstantAppResolverConnection(
mContext, instantAppResolverComponent.first,
instantAppResolverComponent.second);
mInstantAppResolverSettingsComponent =
@@ -3472,7 +3532,7 @@
final String[] packageArray =
mContext.getResources().getStringArray(R.array.config_ephemeralResolverPackage);
if (packageArray.length == 0 && !Build.IS_DEBUGGABLE) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.d(TAG, "Ephemeral resolver NOT found; empty package list");
}
return null;
@@ -3487,19 +3547,9 @@
final Intent resolverIntent = new Intent(actionName);
List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
- // temporarily look for the old action
- if (resolvers.size() == 0) {
- if (DEBUG_EPHEMERAL) {
- Slog.d(TAG, "Ephemeral resolver not found with new action; try old one");
- }
- actionName = Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE;
- resolverIntent.setAction(actionName);
- resolvers = queryIntentServicesInternal(resolverIntent, null,
- resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
- }
final int N = resolvers.size();
if (N == 0) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.d(TAG, "Ephemeral resolver NOT found; no matching intent filters");
}
return null;
@@ -3515,44 +3565,53 @@
final String packageName = info.serviceInfo.packageName;
if (!possiblePackages.contains(packageName) && !Build.IS_DEBUGGABLE) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.d(TAG, "Ephemeral resolver not in allowed package list;"
+ " pkg: " + packageName + ", info:" + info);
}
continue;
}
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "Ephemeral resolver found;"
+ " pkg: " + packageName + ", info:" + info);
}
return new Pair<>(new ComponentName(packageName, info.serviceInfo.name), actionName);
}
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "Ephemeral resolver NOT found");
}
return null;
}
private @Nullable ActivityInfo getInstantAppInstallerLPr() {
- final Intent intent = new Intent(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
+ String[] orderedActions = Build.IS_ENG
+ ? new String[]{
+ Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE + "_TEST",
+ Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE}
+ : new String[]{
+ Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE};
final int resolveFlags =
MATCH_DIRECT_BOOT_AWARE
- | MATCH_DIRECT_BOOT_UNAWARE
- | (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
- List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
- resolveFlags, UserHandle.USER_SYSTEM);
- // temporarily look for the old action
- if (matches.isEmpty()) {
- if (DEBUG_EPHEMERAL) {
- Slog.d(TAG, "Ephemeral installer not found with new action; try old one");
- }
- intent.setAction(Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE);
+ | MATCH_DIRECT_BOOT_UNAWARE
+ | Intent.FLAG_IGNORE_EPHEMERAL
+ | (!Build.IS_ENG ? MATCH_SYSTEM_ONLY : 0);
+ final Intent intent = new Intent();
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
+ List<ResolveInfo> matches = null;
+ for (String action : orderedActions) {
+ intent.setAction(action);
matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
resolveFlags, UserHandle.USER_SYSTEM);
+ if (matches.isEmpty()) {
+ if (DEBUG_INSTANT) {
+ Slog.d(TAG, "Instant App installer not found with " + action);
+ }
+ } else {
+ break;
+ }
}
Iterator<ResolveInfo> iter = matches.iterator();
while (iter.hasNext()) {
@@ -3560,7 +3619,8 @@
final PackageSetting ps = mSettings.mPackages.get(rInfo.activityInfo.packageName);
if (ps != null) {
final PermissionsState permissionsState = ps.getPermissionsState();
- if (permissionsState.hasPermission(Manifest.permission.INSTALL_PACKAGES, 0)) {
+ if (permissionsState.hasPermission(Manifest.permission.INSTALL_PACKAGES, 0)
+ || Build.IS_ENG) {
continue;
}
}
@@ -3584,15 +3644,6 @@
final int resolveFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
UserHandle.USER_SYSTEM);
- // temporarily look for the old action
- if (matches.isEmpty()) {
- if (DEBUG_EPHEMERAL) {
- Slog.d(TAG, "Ephemeral resolver settings not found with new action; try old one");
- }
- intent.setAction(Intent.ACTION_EPHEMERAL_RESOLVER_SETTINGS);
- matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
- UserHandle.USER_SYSTEM);
- }
if (matches.isEmpty()) {
return null;
}
@@ -4719,10 +4770,7 @@
flags |= PackageManager.MATCH_INSTANT;
} else {
final boolean wantMatchInstant = (flags & PackageManager.MATCH_INSTANT) != 0;
- final boolean allowMatchInstant =
- (wantInstantApps
- && Intent.ACTION_VIEW.equals(intent.getAction())
- && hasWebURI(intent))
+ final boolean allowMatchInstant = wantInstantApps
|| (wantMatchInstant && canViewInstantApps(callingUid, userId));
flags &= ~(PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY
| PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY);
@@ -5477,9 +5525,9 @@
}
switch (type) {
case CERT_INPUT_RAW_X509:
- return signingDetailsHasCertificate(certificate, p.mSigningDetails);
+ return p.mSigningDetails.hasCertificate(certificate);
case CERT_INPUT_SHA256:
- return signingDetailsHasSha256Certificate(certificate, p.mSigningDetails);
+ return p.mSigningDetails.hasSha256Certificate(certificate);
default:
return false;
}
@@ -5518,9 +5566,9 @@
}
switch (type) {
case CERT_INPUT_RAW_X509:
- return signingDetailsHasCertificate(certificate, signingDetails);
+ return signingDetails.hasCertificate(certificate);
case CERT_INPUT_SHA256:
- return signingDetailsHasSha256Certificate(certificate, signingDetails);
+ return signingDetails.hasSha256Certificate(certificate);
default:
return false;
}
@@ -5912,8 +5960,14 @@
if (!skipPackageCheck && intent.getPackage() != null) {
return false;
}
- final boolean isWebUri = hasWebURI(intent);
- if (!isWebUri || intent.getData().getHost() == null) {
+ if (!intent.isBrowsableWebIntent()) {
+ // for non web intents, we should not resolve externally if an app already exists to
+ // handle it or if the caller didn't explicitly request it.
+ if ((resolvedActivities != null && resolvedActivities.size() != 0)
+ || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) == 0) {
+ return false;
+ }
+ } else if (intent.getData() == null || TextUtils.isEmpty(intent.getData().getHost())) {
return false;
}
// Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
@@ -5932,7 +5986,7 @@
final int status = (int) (packedStatus >> 32);
if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS
|| status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "DENY instant app;"
+ " pkg: " + packageName + ", status: " + status);
}
@@ -5940,7 +5994,7 @@
}
}
if (ps.getInstantApp(userId)) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "DENY instant app installed;"
+ " pkg: " + packageName);
}
@@ -6311,7 +6365,7 @@
if (matches.get(i).getTargetUserId() == targetUserId) return true;
}
}
- if (hasWebURI(intent)) {
+ if (intent.hasWebURI()) {
// cross-profile app linking works only towards the parent.
final int callingUid = Binder.getCallingUid();
final UserInfo parent = getProfileParent(sourceUserId);
@@ -6486,7 +6540,7 @@
sortResult = true;
}
}
- if (hasWebURI(intent)) {
+ if (intent.hasWebURI()) {
CrossProfileDomainInfo xpDomainInfo = null;
final UserInfo parent = getProfileParent(userId);
if (parent != null) {
@@ -6572,12 +6626,11 @@
if (ps.getInstantApp(userId)) {
final long packedStatus = getDomainVerificationStatusLPr(ps, userId);
final int status = (int)(packedStatus >> 32);
- final int linkGeneration = (int)(packedStatus & 0xFFFFFFFF);
if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
// there's a local instant application installed, but, the user has
// chosen to never use it; skip resolution and don't acknowledge
// an instant application is even available
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "Instant app marked to never run; pkg: " + packageName);
}
blockResolution = true;
@@ -6585,7 +6638,7 @@
} else {
// we have a locally installed instant application; skip resolution
// but acknowledge there's an instant application available
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "Found installed instant app; pkg: " + packageName);
}
localInstantApp = info;
@@ -6604,9 +6657,8 @@
null /*responseObj*/, intent /*origIntent*/, resolvedType,
null /*callingPackage*/, userId, null /*verificationBundle*/,
resolveForStart);
- auxiliaryResponse =
- InstantAppResolver.doInstantAppResolutionPhaseOne(
- mContext, mInstantAppResolverConnection, requestObject);
+ auxiliaryResponse = InstantAppResolver.doInstantAppResolutionPhaseOne(
+ mInstantAppResolverConnection, requestObject);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
} else {
// we have an instant application locally, but, we can't admit that since
@@ -6615,35 +6667,40 @@
// instant application available externally. when it comes time to start
// the instant application, we'll do the right thing.
final ApplicationInfo ai = localInstantApp.activityInfo.applicationInfo;
- auxiliaryResponse = new AuxiliaryResolveInfo(
- ai.packageName, null /*splitName*/, null /*failureActivity*/,
- ai.versionCode, null /*failureIntent*/);
+ auxiliaryResponse = new AuxiliaryResolveInfo(null /* failureActivity */,
+ ai.packageName, ai.versionCode, null /* splitName */);
}
}
- if (auxiliaryResponse != null) {
- if (DEBUG_EPHEMERAL) {
- Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
- }
- final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo);
- final PackageSetting ps =
- mSettings.mPackages.get(mInstantAppInstallerActivity.packageName);
- if (ps != null) {
- ephemeralInstaller.activityInfo = PackageParser.generateActivityInfo(
- mInstantAppInstallerActivity, 0, ps.readUserState(userId), userId);
- ephemeralInstaller.activityInfo.launchToken = auxiliaryResponse.token;
- ephemeralInstaller.auxiliaryInfo = auxiliaryResponse;
- // make sure this resolver is the default
- ephemeralInstaller.isDefault = true;
- ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
- | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
- // add a non-generic filter
- ephemeralInstaller.filter = new IntentFilter(intent.getAction());
- ephemeralInstaller.filter.addDataPath(
- intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL);
- ephemeralInstaller.isInstantAppAvailable = true;
- result.add(ephemeralInstaller);
- }
+ if (intent.isBrowsableWebIntent() && auxiliaryResponse == null) {
+ return result;
}
+ final PackageSetting ps = mSettings.mPackages.get(mInstantAppInstallerActivity.packageName);
+ if (ps == null) {
+ return result;
+ }
+ final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo);
+ ephemeralInstaller.activityInfo = PackageParser.generateActivityInfo(
+ mInstantAppInstallerActivity, 0, ps.readUserState(userId), userId);
+ ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
+ | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
+ // add a non-generic filter
+ ephemeralInstaller.filter = new IntentFilter();
+ if (intent.getAction() != null) {
+ ephemeralInstaller.filter.addAction(intent.getAction());
+ }
+ if (intent.getData() != null && intent.getData().getPath() != null) {
+ ephemeralInstaller.filter.addDataPath(
+ intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL);
+ }
+ ephemeralInstaller.isInstantAppAvailable = true;
+ // make sure this resolver is the default
+ ephemeralInstaller.isDefault = true;
+ ephemeralInstaller.auxiliaryInfo = auxiliaryResponse;
+ if (DEBUG_INSTANT) {
+ Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
+ }
+
+ result.add(ephemeralInstaller);
return result;
}
@@ -6758,10 +6815,11 @@
final ResolveInfo info = resolveInfos.get(i);
// allow activities that are defined in the provided package
if (allowDynamicSplits
+ && info.activityInfo != null
&& info.activityInfo.splitName != null
&& !ArrayUtils.contains(info.activityInfo.applicationInfo.splitNames,
info.activityInfo.splitName)) {
- if (mInstantAppInstallerInfo == null) {
+ if (mInstantAppInstallerActivity == null) {
if (DEBUG_INSTALL) {
Slog.v(TAG, "No installer - not adding it to the ResolveInfo list");
}
@@ -6773,14 +6831,15 @@
if (DEBUG_INSTALL) {
Slog.v(TAG, "Adding installer to the ResolveInfo list");
}
- final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
+ final ResolveInfo installerInfo = new ResolveInfo(
+ mInstantAppInstallerInfo);
final ComponentName installFailureActivity = findInstallFailureActivity(
info.activityInfo.packageName, filterCallingUid, userId);
installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
- info.activityInfo.packageName, info.activityInfo.splitName,
installFailureActivity,
+ info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode,
- null /*failureIntent*/);
+ info.activityInfo.splitName);
installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
| IntentFilter.MATCH_ADJUSTMENT_NORMAL;
// add a non-generic filter
@@ -6797,6 +6856,7 @@
installerInfo.priority = info.priority;
installerInfo.preferredOrder = info.preferredOrder;
installerInfo.isDefault = info.isDefault;
+ installerInfo.isInstantAppAvailable = true;
resolveInfos.set(i, installerInfo);
continue;
}
@@ -6854,17 +6914,6 @@
return resolveInfos.size() > 0 && resolveInfos.get(0).priority >= 0;
}
- private static boolean hasWebURI(Intent intent) {
- if (intent.getData() == null) {
- return false;
- }
- final String scheme = intent.getScheme();
- if (TextUtils.isEmpty(scheme)) {
- return false;
- }
- return scheme.equals(IntentFilter.SCHEME_HTTP) || scheme.equals(IntentFilter.SCHEME_HTTPS);
- }
-
private List<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPr(Intent intent,
int matchFlags, List<ResolveInfo> candidates, CrossProfileDomainInfo xpDomainInfo,
int userId) {
@@ -7534,14 +7583,16 @@
info.serviceInfo.splitName)) {
// requested service is defined in a split that hasn't been installed yet.
// add the installer to the resolve list
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
}
- final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
+ final ResolveInfo installerInfo = new ResolveInfo(
+ mInstantAppInstallerInfo);
installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
- info.serviceInfo.packageName, info.serviceInfo.splitName,
- null /*failureActivity*/, info.serviceInfo.applicationInfo.versionCode,
- null /*failureIntent*/);
+ null /* installFailureActivity */,
+ info.serviceInfo.packageName,
+ info.serviceInfo.applicationInfo.versionCode,
+ info.serviceInfo.splitName);
// make sure this resolver is the default
installerInfo.isDefault = true;
installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
@@ -7654,14 +7705,16 @@
info.providerInfo.splitName)) {
// requested provider is defined in a split that hasn't been installed yet.
// add the installer to the resolve list
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
}
- final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
+ final ResolveInfo installerInfo = new ResolveInfo(
+ mInstantAppInstallerInfo);
installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
- info.providerInfo.packageName, info.providerInfo.splitName,
- null /*failureActivity*/, info.providerInfo.applicationInfo.versionCode,
- null /*failureIntent*/);
+ null /*failureActivity*/,
+ info.providerInfo.packageName,
+ info.providerInfo.applicationInfo.versionCode,
+ info.providerInfo.splitName);
// make sure this resolver is the default
installerInfo.isDefault = true;
installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
@@ -8293,13 +8346,11 @@
}
private void collectCertificatesLI(PackageSetting ps, PackageParser.Package pkg,
- boolean forceCollect) throws PackageManagerException {
+ boolean forceCollect, boolean skipVerify) throws PackageManagerException {
// When upgrading from pre-N MR1, verify the package time stamp using the package
// directory and not the APK file.
final long lastModifiedTime = mIsPreNMR1Upgrade
? new File(pkg.codePath).lastModified() : getLastModifiedTime(pkg);
- // Note that currently skipVerify skips verification on both base and splits for simplicity.
- final boolean skipVerify = forceCollect && canSkipFullPackageVerification(pkg);
if (ps != null && !forceCollect
&& ps.codePathString.equals(pkg.codePath)
&& ps.timeStamp == lastModifiedTime
@@ -8672,21 +8723,24 @@
}
// Verify certificates against what was last scanned. If it is an updated priv app, we will
- // force re-collecting certificate. Full apk verification will happen unless apk verity is
- // set up for the file. In that case, only small part of the apk is verified upfront.
+ // force re-collecting certificate.
final boolean forceCollect = PackageManagerServiceUtils.isApkVerificationForced(
disabledPkgSetting);
- collectCertificatesLI(pkgSetting, pkg, forceCollect);
+ // Full APK verification can be skipped during certificate collection, only if the file is
+ // in verified partition, or can be verified on access (when apk verity is enabled). In both
+ // cases, only data in Signing Block is verified instead of the whole file.
+ final boolean skipVerify = ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) ||
+ (forceCollect && canSkipFullPackageVerification(pkg));
+ collectCertificatesLI(pkgSetting, pkg, forceCollect, skipVerify);
boolean shouldHideSystemApp = false;
// A new application appeared on /system, but, we already have a copy of
// the application installed on /data.
if (scanSystemPartition && !isSystemPkgUpdated && pkgAlreadyExists
&& !pkgSetting.isSystem()) {
- // if the signatures don't match, wipe the installed application and its data
- if (compareSignatures(pkgSetting.signatures.mSigningDetails.signatures,
- pkg.mSigningDetails.signatures)
- != PackageManager.SIGNATURE_MATCH) {
+
+ if (!pkg.mSigningDetails.checkCapability(pkgSetting.signatures.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
logCriticalInfo(Log.WARN,
"System package signature mismatch;"
+ " name: " + pkgSetting.name);
@@ -9651,34 +9705,51 @@
}
final String[] expectedCertDigests = requiredCertDigests[i];
- // For apps targeting O MR1 we require explicit enumeration of all certs.
- final String[] libCertDigests = (targetSdk > Build.VERSION_CODES.O)
- ? PackageUtils.computeSignaturesSha256Digests(
- libPkg.mSigningDetails.signatures)
- : PackageUtils.computeSignaturesSha256Digests(
- new Signature[]{libPkg.mSigningDetails.signatures[0]});
- // Take a shortcut if sizes don't match. Note that if an app doesn't
- // target O we don't parse the "additional-certificate" tags similarly
- // how we only consider all certs only for apps targeting O (see above).
- // Therefore, the size check is safe to make.
- if (expectedCertDigests.length != libCertDigests.length) {
- throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
- "Package " + packageName + " requires differently signed" +
- " static shared library; failing!");
- }
- // Use a predictable order as signature order may vary
- Arrays.sort(libCertDigests);
- Arrays.sort(expectedCertDigests);
+ if (expectedCertDigests.length > 1) {
- final int certCount = libCertDigests.length;
- for (int j = 0; j < certCount; j++) {
- if (!libCertDigests[j].equalsIgnoreCase(expectedCertDigests[j])) {
+ // For apps targeting O MR1 we require explicit enumeration of all certs.
+ final String[] libCertDigests = (targetSdk > Build.VERSION_CODES.O)
+ ? PackageUtils.computeSignaturesSha256Digests(
+ libPkg.mSigningDetails.signatures)
+ : PackageUtils.computeSignaturesSha256Digests(
+ new Signature[]{libPkg.mSigningDetails.signatures[0]});
+
+ // Take a shortcut if sizes don't match. Note that if an app doesn't
+ // target O we don't parse the "additional-certificate" tags similarly
+ // how we only consider all certs only for apps targeting O (see above).
+ // Therefore, the size check is safe to make.
+ if (expectedCertDigests.length != libCertDigests.length) {
throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
"Package " + packageName + " requires differently signed" +
" static shared library; failing!");
}
+
+ // Use a predictable order as signature order may vary
+ Arrays.sort(libCertDigests);
+ Arrays.sort(expectedCertDigests);
+
+ final int certCount = libCertDigests.length;
+ for (int j = 0; j < certCount; j++) {
+ if (!libCertDigests[j].equalsIgnoreCase(expectedCertDigests[j])) {
+ throw new PackageManagerException(
+ INSTALL_FAILED_MISSING_SHARED_LIBRARY,
+ "Package " + packageName + " requires differently signed" +
+ " static shared library; failing!");
+ }
+ }
+ } else {
+
+ // lib signing cert could have rotated beyond the one expected, check to see
+ // if the new one has been blessed by the old
+ if (!libPkg.mSigningDetails.hasSha256Certificate(
+ ByteStringUtils.fromHexToByteArray(expectedCertDigests[0]))) {
+ throw new PackageManagerException(
+ INSTALL_FAILED_MISSING_SHARED_LIBRARY,
+ "Package " + packageName + " requires differently signed" +
+ " static shared library; failing!");
+ }
}
}
@@ -9862,6 +9933,7 @@
* <li>{@link #SCAN_AS_PRIVILEGED}</li>
* <li>{@link #SCAN_AS_OEM}</li>
* <li>{@link #SCAN_AS_VENDOR}</li>
+ * <li>{@link #SCAN_AS_PRODUCT}</li>
* <li>{@link #SCAN_AS_INSTANT_APP}</li>
* <li>{@link #SCAN_AS_VIRTUAL_PRELOAD}</li>
* </ul>
@@ -9884,6 +9956,10 @@
& ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0) {
scanFlags |= SCAN_AS_VENDOR;
}
+ if ((disabledPkgSetting.pkgPrivateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0) {
+ scanFlags |= SCAN_AS_PRODUCT;
+ }
}
if (pkgSetting != null) {
final int userId = ((user == null) ? 0 : user.getIdentifier());
@@ -9909,8 +9985,7 @@
// priv-apps.
synchronized (mPackages) {
PackageSetting platformPkgSetting = mSettings.mPackages.get("android");
- if (!pkg.packageName.equals("android")
- && (compareSignatures(platformPkgSetting.signatures.mSigningDetails.signatures,
+ if ((compareSignatures(platformPkgSetting.signatures.mSigningDetails.signatures,
pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH)) {
scanFlags |= SCAN_AS_PRIVILEGED;
}
@@ -10090,6 +10165,15 @@
// We just determined the app is signed correctly, so bring
// over the latest parsed certs.
pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
+
+
+ // if this is is a sharedUser, check to see if the new package is signed by a newer
+ // signing certificate than the existing one, and if so, copy over the new details
+ if (signatureCheckPs.sharedUser != null
+ && pkg.mSigningDetails.hasAncestor(
+ signatureCheckPs.sharedUser.signatures.mSigningDetails)) {
+ signatureCheckPs.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails;
+ }
} catch (PackageManagerException e) {
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
throw e;
@@ -10116,6 +10200,13 @@
String msg = "System package " + pkg.packageName
+ " signature changed; retaining data.";
reportSettingsProblem(Log.WARN, msg);
+ } catch (IllegalArgumentException e) {
+
+ // should never happen: certs matched when checking, but not when comparing
+ // old to new for sharedUser
+ throw new PackageManagerException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
+ "Signing certificates comparison made on incomparable signing details"
+ + " but somehow passed verifySignatures!");
}
}
@@ -10361,7 +10452,20 @@
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
- SELinuxMMAC.assignSeInfoValue(pkg);
+ // 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;
+ // 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.mExtras = pkgSetting;
pkg.applicationInfo.processName = fixProcessName(
@@ -10662,6 +10766,10 @@
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VENDOR;
}
+ if ((scanFlags & SCAN_AS_PRODUCT) != 0) {
+ pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT;
+ }
+
if (!isSystemApp(pkg)) {
// Only system apps can use these features.
pkg.mOriginalPackages = null;
@@ -11674,14 +11782,14 @@
private void setUpInstantAppInstallerActivityLP(ActivityInfo installerActivity) {
if (installerActivity == null) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.d(TAG, "Clear ephemeral installer activity");
}
mInstantAppInstallerActivity = null;
return;
}
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.d(TAG, "Set ephemeral installer activity: "
+ installerActivity.getComponentName());
}
@@ -11692,7 +11800,7 @@
mInstantAppInstallerActivity.exported = true;
mInstantAppInstallerActivity.enabled = true;
mInstantAppInstallerInfo.activityInfo = mInstantAppInstallerActivity;
- mInstantAppInstallerInfo.priority = 0;
+ mInstantAppInstallerInfo.priority = 1;
mInstantAppInstallerInfo.preferredOrder = 1;
mInstantAppInstallerInfo.isDefault = true;
mInstantAppInstallerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
@@ -11708,6 +11816,8 @@
codeRoot = Environment.getOemDirectory();
} else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) {
codeRoot = Environment.getVendorDirectory();
+ } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) {
+ codeRoot = Environment.getProductDirectory();
} else {
// Unrecognized code path; take its top real segment as the apk root:
// e.g. /something/app/blah.apk => /something
@@ -13139,8 +13249,9 @@
private int mFlags;
}
- static final class EphemeralIntentResolver
- extends IntentResolver<AuxiliaryResolveInfo, AuxiliaryResolveInfo> {
+ static final class InstantAppIntentResolver
+ extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter,
+ AuxiliaryResolveInfo.AuxiliaryFilter> {
/**
* The result that has the highest defined order. Ordering applies on a
* per-package basis. Mapping is from package name to Pair of order and
@@ -13155,18 +13266,19 @@
final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult = new ArrayMap<>();
@Override
- protected AuxiliaryResolveInfo[] newArray(int size) {
- return new AuxiliaryResolveInfo[size];
+ protected AuxiliaryResolveInfo.AuxiliaryFilter[] newArray(int size) {
+ return new AuxiliaryResolveInfo.AuxiliaryFilter[size];
}
@Override
- protected boolean isPackageForFilter(String packageName, AuxiliaryResolveInfo responseObj) {
+ protected boolean isPackageForFilter(String packageName,
+ AuxiliaryResolveInfo.AuxiliaryFilter responseObj) {
return true;
}
@Override
- protected AuxiliaryResolveInfo newResult(AuxiliaryResolveInfo responseObj, int match,
- int userId) {
+ protected AuxiliaryResolveInfo.AuxiliaryFilter newResult(
+ AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId) {
if (!sUserManager.exists(userId)) {
return null;
}
@@ -13187,7 +13299,7 @@
}
@Override
- protected void filterResults(List<AuxiliaryResolveInfo> results) {
+ protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
// only do work if ordering is enabled [most of the time it won't be]
if (mOrderResult.size() == 0) {
return;
@@ -13507,7 +13619,7 @@
IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
String installerPackageName, int installerUid, UserHandle user,
PackageParser.SigningDetails signingDetails) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
if ((sessionParams.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
Slog.d(TAG, "Ephemeral install of " + packageName);
}
@@ -14991,7 +15103,7 @@
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
packageAbiOverride);
- if (DEBUG_EPHEMERAL && ephemeral) {
+ if (DEBUG_INSTANT && ephemeral) {
Slog.v(TAG, "pkgLite for install: " + pkgLite);
}
@@ -15058,7 +15170,7 @@
installFlags |= PackageManager.INSTALL_EXTERNAL;
installFlags &= ~PackageManager.INSTALL_INTERNAL;
} else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) {
- if (DEBUG_EPHEMERAL) {
+ if (DEBUG_INSTANT) {
Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag");
}
installFlags |= PackageManager.INSTALL_INSTANT_APP;
@@ -15974,10 +16086,10 @@
return;
}
} else {
+
// default to original signature matching
- if (compareSignatures(oldPackage.mSigningDetails.signatures,
- pkg.mSigningDetails.signatures)
- != PackageManager.SIGNATURE_MATCH) {
+ if (!pkg.mSigningDetails.checkCapability(oldPackage.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
"New package has a different signature: " + pkgName);
return;
@@ -16110,7 +16222,7 @@
boolean sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
- // Set the system/privileged/oem/vendor flags as needed
+ // Set the system/privileged/oem/vendor/product flags as needed
final boolean privileged =
(oldPackage.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
@@ -16120,12 +16232,16 @@
final boolean vendor =
(oldPackage.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
+ final boolean product =
+ (oldPackage.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
final @ParseFlags int systemParseFlags = parseFlags;
final @ScanFlags int systemScanFlags = scanFlags
| SCAN_AS_SYSTEM
| (privileged ? SCAN_AS_PRIVILEGED : 0)
| (oem ? SCAN_AS_OEM : 0)
- | (vendor ? SCAN_AS_VENDOR : 0);
+ | (vendor ? SCAN_AS_VENDOR : 0)
+ | (product ? SCAN_AS_PRODUCT : 0);
replaceSystemPackageLIF(oldPackage, pkg, systemParseFlags, systemScanFlags,
user, allUsers, installerPackageName, res, installReason);
@@ -16967,9 +17083,25 @@
sourcePackageSetting, scanFlags))) {
sigsOk = ksms.checkUpgradeKeySetLocked(sourcePackageSetting, pkg);
} else {
- sigsOk = compareSignatures(
- sourcePackageSetting.signatures.mSigningDetails.signatures,
- pkg.mSigningDetails.signatures) == PackageManager.SIGNATURE_MATCH;
+
+ // in the event of signing certificate rotation, we need to see if the
+ // package's certificate has rotated from the current one, or if it is an
+ // older certificate with which the current is ok with sharing permissions
+ if (sourcePackageSetting.signatures.mSigningDetails.checkCapability(
+ pkg.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
+ sigsOk = true;
+ } else if (pkg.mSigningDetails.checkCapability(
+ sourcePackageSetting.signatures.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
+
+ // the scanned package checks out, has signing certificate rotation
+ // history, and is newer; bring it over
+ sourcePackageSetting.signatures.mSigningDetails = pkg.mSigningDetails;
+ sigsOk = true;
+ } else {
+ sigsOk = false;
+ }
}
if (!sigsOk) {
// If the owning package is the system itself, we log but allow
@@ -17373,6 +17505,10 @@
return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
+ private static boolean isProductApp(PackageParser.Package pkg) {
+ return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
+ }
+
private static boolean hasDomainURLs(PackageParser.Package pkg) {
return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
}
@@ -18112,8 +18248,10 @@
try {
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
+ final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
return path.startsWith(privilegedAppDir.getCanonicalPath())
- || path.startsWith(privilegedVendorAppDir.getCanonicalPath());
+ || path.startsWith(privilegedVendorAppDir.getCanonicalPath())
+ || path.startsWith(privilegedProductAppDir.getCanonicalPath());
} catch (IOException e) {
Slog.e(TAG, "Unable to access code path " + path);
}
@@ -18138,6 +18276,15 @@
return false;
}
+ static boolean locationIsProduct(String path) {
+ try {
+ return path.startsWith(Environment.getProductDirectory().getCanonicalPath());
+ } catch (IOException e) {
+ Slog.e(TAG, "Unable to access code path " + path);
+ }
+ return false;
+ }
+
/*
* Tries to delete system package.
*/
@@ -18262,6 +18409,9 @@
if (locationIsVendor(codePathString)) {
scanFlags |= SCAN_AS_VENDOR;
}
+ if (locationIsProduct(codePathString)) {
+ scanFlags |= SCAN_AS_PRODUCT;
+ }
final File codePath = new File(codePathString);
final PackageParser.Package pkg =
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 76c199b..c02331d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -531,18 +531,29 @@
// migrate the old signatures to the new scheme
packageSignatures.mSigningDetails = parsedSignatures;
return true;
+ } else if (parsedSignatures.hasPastSigningCertificates()) {
+
+ // well this sucks: the parsed package has probably rotated signing certificates, but
+ // we don't have enough information to determine if the new signing certificate was
+ // blessed by the old one
+ logCriticalInfo(Log.INFO, "Existing package " + packageName + " has flattened signing "
+ + "certificate chain. Unable to install newer version with rotated signing "
+ + "certificate.");
}
return false;
}
- private static boolean matchSignaturesRecover(String packageName,
- Signature[] existingSignatures, Signature[] parsedSignatures) {
+ private static boolean matchSignaturesRecover(
+ String packageName,
+ PackageParser.SigningDetails existingSignatures,
+ PackageParser.SigningDetails parsedSignatures,
+ @PackageParser.SigningDetails.CertCapabilities int flags) {
String msg = null;
try {
- if (Signature.areEffectiveMatch(existingSignatures, parsedSignatures)) {
- logCriticalInfo(Log.INFO,
- "Recovered effectively matching certificates for " + packageName);
- return true;
+ if (parsedSignatures.checkCapabilityRecover(existingSignatures, flags)) {
+ logCriticalInfo(Log.INFO, "Recovered effectively matching certificates for "
+ + packageName);
+ return true;
}
} catch (CertificateException e) {
msg = e.getMessage();
@@ -563,9 +574,11 @@
PackageSetting disabledPkgSetting) {
try {
PackageParser.collectCertificates(disabledPkgSetting.pkg, true /* skipVerify */);
- if (compareSignatures(pkgSetting.signatures.mSigningDetails.signatures,
- disabledPkgSetting.signatures.mSigningDetails.signatures)
- != PackageManager.SIGNATURE_MATCH) {
+ if (pkgSetting.signatures.mSigningDetails.checkCapability(
+ disabledPkgSetting.signatures.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
+ return true;
+ } else {
logCriticalInfo(Log.ERROR, "Updated system app mismatches cert on /system: " +
pkgSetting.name);
return false;
@@ -575,69 +588,6 @@
e.getMessage());
return false;
}
- return true;
- }
-
- /**
- * Checks the signing certificates to see if the provided certificate is a member. Invalid for
- * {@code SigningDetails} with multiple signing certificates.
- * @param certificate certificate to check for membership
- * @param signingDetails signing certificates record whose members are to be searched
- * @return true if {@code certificate} is in {@code signingDetails}
- */
- public static boolean signingDetailsHasCertificate(
- byte[] certificate, PackageParser.SigningDetails signingDetails) {
- if (signingDetails == PackageParser.SigningDetails.UNKNOWN) {
- return false;
- }
- Signature signature = new Signature(certificate);
- if (signingDetails.hasPastSigningCertificates()) {
- for (int i = 0; i < signingDetails.pastSigningCertificates.length; i++) {
- if (signingDetails.pastSigningCertificates[i].equals(signature)) {
- return true;
- }
- }
- } else {
- // no signing history, just check the current signer
- if (signingDetails.signatures.length == 1
- && signingDetails.signatures[0].equals(signature)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks the signing certificates to see if the provided certificate is a member. Invalid for
- * {@code SigningDetails} with multiple signing certificaes.
- * @param sha256Certificate certificate to check for membership
- * @param signingDetails signing certificates record whose members are to be searched
- * @return true if {@code certificate} is in {@code signingDetails}
- */
- public static boolean signingDetailsHasSha256Certificate(
- byte[] sha256Certificate, PackageParser.SigningDetails signingDetails ) {
- if (signingDetails == PackageParser.SigningDetails.UNKNOWN) {
- return false;
- }
- if (signingDetails.hasPastSigningCertificates()) {
- for (int i = 0; i < signingDetails.pastSigningCertificates.length; i++) {
- byte[] digest = PackageUtils.computeSha256DigestBytes(
- signingDetails.pastSigningCertificates[i].toByteArray());
- if (Arrays.equals(sha256Certificate, digest)) {
- return true;
- }
- }
- } else {
- // no signing history, just check the current signer
- if (signingDetails.signatures.length == 1) {
- byte[] digest = PackageUtils.computeSha256DigestBytes(
- signingDetails.signatures[0].toByteArray());
- if (Arrays.equals(sha256Certificate, digest)) {
- return true;
- }
- }
- }
- return false;
}
/** Returns true if APK Verity is enabled. */
@@ -662,10 +612,11 @@
final String packageName = pkgSetting.name;
boolean compatMatch = false;
if (pkgSetting.signatures.mSigningDetails.signatures != null) {
+
// Already existing package. Make sure signatures match
- boolean match = compareSignatures(pkgSetting.signatures.mSigningDetails.signatures,
- parsedSignatures.signatures)
- == PackageManager.SIGNATURE_MATCH;
+ boolean match = parsedSignatures.checkCapability(
+ pkgSetting.signatures.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA);
if (!match && compareCompat) {
match = matchSignaturesCompat(packageName, pkgSetting.signatures,
parsedSignatures);
@@ -673,8 +624,10 @@
}
if (!match && compareRecover) {
match = matchSignaturesRecover(
- packageName, pkgSetting.signatures.mSigningDetails.signatures,
- parsedSignatures.signatures);
+ packageName,
+ pkgSetting.signatures.mSigningDetails,
+ parsedSignatures,
+ PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA);
}
if (!match && isApkVerificationForced(disabledPkgSetting)) {
@@ -689,20 +642,35 @@
}
// Check for shared user signatures
if (pkgSetting.sharedUser != null
- && pkgSetting.sharedUser.signatures.mSigningDetails.signatures != null) {
- // Already existing package. Make sure signatures match
+ && pkgSetting.sharedUser.signatures.mSigningDetails
+ != PackageParser.SigningDetails.UNKNOWN) {
+
+ // Already existing package. Make sure signatures match. In case of signing certificate
+ // rotation, the packages with newer certs need to be ok with being sharedUserId with
+ // the older ones. We check to see if either the new package is signed by an older cert
+ // with which the current sharedUser is ok, or if it is signed by a newer one, and is ok
+ // with being sharedUser with the existing signing cert.
boolean match =
- compareSignatures(
- pkgSetting.sharedUser.signatures.mSigningDetails.signatures,
- parsedSignatures.signatures) == PackageManager.SIGNATURE_MATCH;
+ parsedSignatures.checkCapability(
+ pkgSetting.sharedUser.signatures.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.SHARED_USER_ID)
+ || pkgSetting.sharedUser.signatures.mSigningDetails.checkCapability(
+ parsedSignatures,
+ PackageParser.SigningDetails.CertCapabilities.SHARED_USER_ID);
if (!match && compareCompat) {
match = matchSignaturesCompat(
packageName, pkgSetting.sharedUser.signatures, parsedSignatures);
}
if (!match && compareRecover) {
- match = matchSignaturesRecover(packageName,
- pkgSetting.sharedUser.signatures.mSigningDetails.signatures,
- parsedSignatures.signatures);
+ match =
+ matchSignaturesRecover(packageName,
+ pkgSetting.sharedUser.signatures.mSigningDetails,
+ parsedSignatures,
+ PackageParser.SigningDetails.CertCapabilities.SHARED_USER_ID)
+ || matchSignaturesRecover(packageName,
+ parsedSignatures,
+ pkgSetting.sharedUser.signatures.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.SHARED_USER_ID);
compatMatch |= match;
}
if (!match) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 47cd813..686c4a5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1555,6 +1555,15 @@
}
}
+ private boolean isProductApp(String pkg) {
+ try {
+ final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
+ return info != null && info.applicationInfo.isProduct();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
private int runGetPrivappPermissions() {
final String pkg = getNextArg();
if (pkg == null) {
@@ -1562,9 +1571,14 @@
return 1;
}
- ArraySet<String> privAppPermissions = isVendorApp(pkg) ?
- SystemConfig.getInstance().getVendorPrivAppPermissions(pkg)
- : SystemConfig.getInstance().getPrivAppPermissions(pkg);
+ ArraySet<String> privAppPermissions = null;
+ if (isVendorApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
+ } else if (isProductApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
+ } else {
+ privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
+ }
getOutPrintWriter().println(privAppPermissions == null
? "{}" : privAppPermissions.toString());
@@ -1578,9 +1592,14 @@
return 1;
}
- ArraySet<String> privAppPermissions = isVendorApp(pkg) ?
- SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg)
- : SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
+ ArraySet<String> privAppPermissions = null;
+ if (isVendorApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
+ } else if (isProductApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
+ } else {
+ privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
+ }
getOutPrintWriter().println(privAppPermissions == null
? "{}" : privAppPermissions.toString());
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 2a2430c..3e2bd4a 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -173,6 +173,10 @@
return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
+ public boolean isProduct() {
+ return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
+ }
+
public boolean isForwardLocked() {
return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 18356c5..f14a684 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -23,6 +23,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.content.pm.Signature;
import android.service.pm.PackageProto;
@@ -236,6 +237,10 @@
return signatures.mSigningDetails.signatures;
}
+ public PackageParser.SigningDetails getSigningDetails() {
+ return signatures.mSigningDetails;
+ }
+
/**
* Makes a shallow copy of the given package settings.
*
diff --git a/services/core/java/com/android/server/pm/PackageSignatures.java b/services/core/java/com/android/server/pm/PackageSignatures.java
index d471fc8..95f490e 100644
--- a/services/core/java/com/android/server/pm/PackageSignatures.java
+++ b/services/core/java/com/android/server/pm/PackageSignatures.java
@@ -182,7 +182,6 @@
Signature sig = readSignatures.get(idx);
if (sig != null) {
signatures[pos] = readSignatures.get(idx);
- pos++;
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <cert> "
@@ -202,7 +201,6 @@
Signature sig = new Signature(key);
readSignatures.set(idx, sig);
signatures[pos] = sig;
- pos++;
}
} catch (NumberFormatException e) {
PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -245,6 +243,8 @@
+ "many <cert> tags, expected " + count
+ " at " + parser.getPositionDescription());
}
+ pos++;
+ XmlUtils.skipCurrentTag(parser);
} else if (tagName.equals("pastSigs")) {
if (flags == null) {
// we haven't encountered pastSigs yet, go ahead
@@ -291,13 +291,14 @@
PackageManagerService.reportSettingsProblem(Log.WARN,
"<pastSigs> encountered multiple times under the same <sigs> at "
+ parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
}
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Unknown element under <sigs>: "
+ parser.getName());
+ XmlUtils.skipCurrentTag(parser);
}
- XmlUtils.skipCurrentTag(parser);
}
return pos;
}
@@ -330,4 +331,4 @@
}
return buf.toString();
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 2552643..a9f1528 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -61,10 +61,8 @@
/** Whether or not the policy files have been read */
private static boolean sPolicyRead;
- /** Path to MAC permissions on system image */
- private static final File[] MAC_PERMISSIONS =
- { new File(Environment.getRootDirectory(), "/etc/selinux/plat_mac_permissions.xml"),
- new File(Environment.getVendorDirectory(), "/etc/selinux/nonplat_mac_permissions.xml") };
+ /** Required MAC permissions files */
+ private static List<File> sMacPermissions = new ArrayList<>();
// Append privapp to existing seinfo label
private static final String PRIVILEGED_APP_STR = ":privapp";
@@ -75,13 +73,40 @@
// Append targetSdkVersion=n to existing seinfo label where n is the app's targetSdkVersion
private static final String TARGETSDKVERSION_STR = ":targetSdkVersion=";
+ // Only initialize sMacPermissions once.
+ static {
+ // Platform mac permissions.
+ sMacPermissions.add(new File(
+ Environment.getRootDirectory(), "/etc/selinux/plat_mac_permissions.xml"));
+
+ // Vendor mac permissions.
+ // The filename has been renamed from nonplat_mac_permissions to
+ // vendor_mac_permissions. Either of them should exist.
+ final File vendorMacPermission = new File(
+ Environment.getVendorDirectory(), "/etc/selinux/vendor_mac_permissions.xml");
+ if (vendorMacPermission.exists()) {
+ sMacPermissions.add(vendorMacPermission);
+ } else {
+ // For backward compatibility.
+ sMacPermissions.add(new File(Environment.getVendorDirectory(),
+ "/etc/selinux/nonplat_mac_permissions.xml"));
+ }
+
+ // ODM mac permissions (optional).
+ final File odmMacPermission = new File(
+ Environment.getOdmDirectory(), "/etc/selinux/odm_mac_permissions.xml");
+ if (odmMacPermission.exists()) {
+ sMacPermissions.add(odmMacPermission);
+ }
+ }
+
/**
* Load the mac_permissions.xml file containing all seinfo assignments used to
- * label apps. The loaded mac_permissions.xml file is determined by the
- * MAC_PERMISSIONS class variable which is set at class load time which itself
- * is based on the USE_OVERRIDE_POLICY class variable. For further guidance on
+ * label apps. The loaded mac_permissions.xml files are plat_mac_permissions.xml and
+ * vendor_mac_permissions.xml, on /system and /vendor partitions, respectively.
+ * odm_mac_permissions.xml on /odm partition is optional. For further guidance on
* the proper structure of a mac_permissions.xml file consult the source code
- * located at system/sepolicy/mac_permissions.xml.
+ * located at system/sepolicy/private/mac_permissions.xml.
*
* @return boolean indicating if policy was correctly loaded. A value of false
* typically indicates a structural problem with the xml or incorrectly
@@ -100,10 +125,13 @@
FileReader policyFile = null;
XmlPullParser parser = Xml.newPullParser();
- for (int i = 0; i < MAC_PERMISSIONS.length; i++) {
+
+ final int count = sMacPermissions.size();
+ for (int i = 0; i < count; ++i) {
+ final File macPermission = sMacPermissions.get(i);
try {
- policyFile = new FileReader(MAC_PERMISSIONS[i]);
- Slog.d(TAG, "Using policy file " + MAC_PERMISSIONS[i]);
+ policyFile = new FileReader(macPermission);
+ Slog.d(TAG, "Using policy file " + macPermission);
parser.setInput(policyFile);
parser.nextTag();
@@ -127,13 +155,13 @@
StringBuilder sb = new StringBuilder("Exception @");
sb.append(parser.getPositionDescription());
sb.append(" while parsing ");
- sb.append(MAC_PERMISSIONS[i]);
+ sb.append(macPermission);
sb.append(":");
sb.append(ex);
Slog.w(TAG, sb.toString());
return false;
} catch (IOException ioe) {
- Slog.w(TAG, "Exception parsing " + MAC_PERMISSIONS[i], ioe);
+ Slog.w(TAG, "Exception parsing " + macPermission, ioe);
return false;
} finally {
IoUtils.closeQuietly(policyFile);
@@ -287,7 +315,8 @@
*
* @param pkg object representing the package to be labeled.
*/
- public static void assignSeInfoValue(PackageParser.Package pkg) {
+ public static void assignSeInfoValue(PackageParser.Package pkg, boolean isPrivileged,
+ int targetSdkVersion) {
synchronized (sPolicies) {
if (!sPolicyRead) {
if (DEBUG_POLICY) {
@@ -307,10 +336,11 @@
if (pkg.applicationInfo.targetSandboxVersion == 2)
pkg.applicationInfo.seInfo += SANDBOX_V2_STR;
- if (pkg.applicationInfo.isPrivilegedApp())
+ if (isPrivileged) {
pkg.applicationInfo.seInfo += PRIVILEGED_APP_STR;
+ }
- pkg.applicationInfo.seInfo += TARGETSDKVERSION_STR + pkg.applicationInfo.targetSdkVersion;
+ pkg.applicationInfo.seInfo += TARGETSDKVERSION_STR + targetSdkVersion;
if (DEBUG_POLICY_INSTALL) {
Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " +
@@ -454,7 +484,11 @@
Signature[] certs = mCerts.toArray(new Signature[0]);
if (pkg.mSigningDetails != SigningDetails.UNKNOWN
&& !Signature.areExactMatch(certs, pkg.mSigningDetails.signatures)) {
- return null;
+
+ // certs aren't exact match, but the package may have rotated from the known system cert
+ if (certs.length > 1 || !pkg.mSigningDetails.hasCertificate(certs[0])) {
+ return null;
+ }
}
// Check for inner package name matches given that the
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 46ba006..7c92045 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -62,6 +62,7 @@
& (ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
| ApplicationInfo.PRIVATE_FLAG_OEM
| ApplicationInfo.PRIVATE_FLAG_VENDOR
+ | ApplicationInfo.PRIVATE_FLAG_PRODUCT
| ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK
| ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 8ce412e..b6e1534 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -851,6 +851,8 @@
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM;
pkgSetting.pkgPrivateFlags |=
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR;
+ pkgSetting.pkgPrivateFlags |=
+ pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT;
pkgSetting.primaryCpuAbiString = primaryCpuAbi;
pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
if (childPkgNames != null) {
@@ -1994,6 +1996,8 @@
if (DEBUG_MU) {
Log.i(TAG, "Writing package restrictions for user=" + userId);
}
+ final long startTime = SystemClock.uptimeMillis();
+
// Keep the old stopped packages around until we know the new ones have
// been successfully written.
File userPackagesStateFile = getUserPackagesStateFile(userId);
@@ -2127,6 +2131,9 @@
|FileUtils.S_IRGRP|FileUtils.S_IWGRP,
-1, -1);
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "package-user-" + userId, SystemClock.uptimeMillis() - startTime);
+
// Done, all is good!
return;
} catch(java.io.IOException e) {
@@ -2388,6 +2395,8 @@
void writeLPr() {
//Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
+ final long startTime = SystemClock.uptimeMillis();
+
// Keep the old settings around until we know the new ones have
// been successfully written.
if (mSettingsFilename.exists()) {
@@ -2533,6 +2542,8 @@
writePackageListLPr();
writeAllUsersPackageRestrictionsLPr();
writeAllRuntimePermissionsLPr();
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "package", SystemClock.uptimeMillis() - startTime);
return;
} catch(java.io.IOException e) {
@@ -4397,6 +4408,7 @@
ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY",
ApplicationInfo.PRIVATE_FLAG_VENDOR, "VENDOR",
+ ApplicationInfo.PRIVATE_FLAG_PRODUCT, "PRODUCT",
ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD",
};
@@ -5131,7 +5143,8 @@
}
private void writePermissionsSync(int userId) {
- AtomicFile destination = new AtomicFile(getUserRuntimePermissionsFile(userId));
+ AtomicFile destination = new AtomicFile(getUserRuntimePermissionsFile(userId),
+ "package-perms-" + userId);
ArrayMap<String, List<PermissionState>> permissionsForPackage = new ArrayMap<>();
ArrayMap<String, List<PermissionState>> permissionsForSharedUser = new ArrayMap<>();
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 6e07eaa..6308766 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1166,9 +1166,9 @@
final String systemPackageName = mServiceInternal.getKnownPackageName(
PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM);
final PackageParser.Package systemPackage = getPackage(systemPackageName);
- return compareSignatures(systemPackage.mSigningDetails.signatures,
- pkg.mSigningDetails.signatures)
- == PackageManager.SIGNATURE_MATCH;
+ return pkg.mSigningDetails.hasAncestorOrSelf(systemPackage.mSigningDetails)
+ || systemPackage.mSigningDetails.checkCapability(pkg.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.PERMISSION);
}
private void grantDefaultPermissionExceptions(int userId) {
@@ -1215,6 +1215,10 @@
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
}
+ dir = new File(Environment.getProductDirectory(), "etc/default-permissions");
+ if (dir.isDirectory() && dir.canRead()) {
+ Collections.addAll(ret, dir.listFiles());
+ }
return ret.isEmpty() ? null : ret.toArray(new File[0]);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 786b998..08f8bbd 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -954,9 +954,16 @@
* <p>This handles parent/child apps.
*/
private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) {
- ArraySet<String> wlPermissions = pkg.isVendor() ?
- SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName)
- : SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);
+ ArraySet<String> wlPermissions = null;
+ if (pkg.isVendor()) {
+ wlPermissions =
+ SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName);
+ } else if (pkg.isProduct()) {
+ wlPermissions =
+ SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName);
+ } else {
+ wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);
+ }
// Let's check if this package is whitelisted...
boolean whitelisted = wlPermissions != null && wlPermissions.contains(perm);
// If it's not, we'll also tail-recurse to the parent.
@@ -979,11 +986,17 @@
// Only report violations for apps on system image
if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
// it's only a reportable violation if the permission isn't explicitly denied
- final ArraySet<String> deniedPermissions = pkg.isVendor() ?
- SystemConfig.getInstance()
- .getVendorPrivAppDenyPermissions(pkg.packageName)
- : SystemConfig.getInstance()
- .getPrivAppDenyPermissions(pkg.packageName);
+ ArraySet<String> deniedPermissions = null;
+ if (pkg.isVendor()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getVendorPrivAppDenyPermissions(pkg.packageName);
+ } else if (pkg.isProduct()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getProductPrivAppDenyPermissions(pkg.packageName);
+ } else {
+ deniedPermissions = SystemConfig.getInstance()
+ .getPrivAppDenyPermissions(pkg.packageName);
+ }
final boolean permissionViolation =
deniedPermissions == null || !deniedPermissions.contains(perm);
if (permissionViolation) {
@@ -1009,12 +1022,24 @@
PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM);
final PackageParser.Package systemPackage =
mPackageManagerInt.getPackage(systemPackageName);
- boolean allowed = (PackageManagerServiceUtils.compareSignatures(
- bp.getSourceSignatures(), pkg.mSigningDetails.signatures)
- == PackageManager.SIGNATURE_MATCH)
- || (PackageManagerServiceUtils.compareSignatures(
- systemPackage.mSigningDetails.signatures, pkg.mSigningDetails.signatures)
- == PackageManager.SIGNATURE_MATCH);
+
+ // check if the package is allow to use this signature permission. A package is allowed to
+ // use a signature permission if:
+ // - it has the same set of signing certificates as the source package
+ // - or its signing certificate was rotated from the source package's certificate
+ // - or its signing certificate is a previous signing certificate of the defining
+ // package, and the defining package still trusts the old certificate for permissions
+ // - or it shares the above relationships with the system package
+ boolean allowed =
+ pkg.mSigningDetails.hasAncestorOrSelf(
+ bp.getSourcePackageSetting().getSigningDetails())
+ || bp.getSourcePackageSetting().getSigningDetails().checkCapability(
+ pkg.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.PERMISSION)
+ || pkg.mSigningDetails.hasAncestorOrSelf(systemPackage.mSigningDetails)
+ || systemPackage.mSigningDetails.checkCapability(
+ pkg.mSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.PERMISSION);
if (!allowed && (privilegedPermission || oemPermission)) {
if (pkg.isSystem()) {
// For updated system applications, a privileged/oem permission
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 0f394a4..0502848 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1025,7 +1025,7 @@
public void run() {
// send interaction hint to improve redraw performance
mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
- if (isRotationChoiceEnabled()) {
+ if (isRotationChoicePossible(mCurrentAppOrientation)) {
final boolean isValid = isValidRotationChoice(mCurrentAppOrientation,
mRotation);
sendProposedRotationChangeToStatusBarInternal(mRotation, isValid);
@@ -7144,7 +7144,7 @@
mOrientationListener.setCurrentRotation(rotation);
}
- public boolean isRotationChoiceEnabled() {
+ public boolean isRotationChoicePossible(int orientation) {
// Rotation choice is only shown when the user is in locked mode.
if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
@@ -7184,50 +7184,45 @@
return false;
}
- // Rotation isn't forced, enable choice
- return true;
+ // Ensure that some rotation choice is possible for the given orientation
+ switch (orientation) {
+ case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
+ case ActivityInfo.SCREEN_ORIENTATION_USER:
+ case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
+ case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
+ case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
+ // NOSENSOR description is ambiguous, in reality WM ignores user choice
+ return true;
+ }
+
+ // Rotation is forced, should be controlled by system
+ return false;
}
public boolean isValidRotationChoice(int orientation, final int preferredRotation) {
- // Determine if the given app orientation can be chosen and, if so, if it is compatible
- // with the provided rotation choice
-
+ // Determine if the given app orientation is compatible with the provided rotation choice
switch (orientation) {
- case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
- case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
- case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
- case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
- case ActivityInfo.SCREEN_ORIENTATION_LOCKED:
- return false; // Forced into a particular rotation, no user choice
-
- case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
- case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
- case ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR:
- case ActivityInfo.SCREEN_ORIENTATION_SENSOR:
- return false; // Sensor overrides user choice
-
- case ActivityInfo.SCREEN_ORIENTATION_NOSENSOR:
- // TODO Can sensor be used to indirectly determine the orientation?
- return false;
-
- case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
- // If the user has locked sensor-based rotation, this behaves the same as landscape
- return false; // User has locked the rotation, will behave as LANDSCAPE
- case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
- // If the user has locked sensor-based rotation, this behaves the same as portrait
- return false; // User has locked the rotation, will behave as PORTRAIT
- case ActivityInfo.SCREEN_ORIENTATION_USER:
- // Works with any rotation except upside down
- return (preferredRotation >= 0) && (preferredRotation != mUpsideDownRotation);
case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
// Works with any of the 4 rotations
return preferredRotation >= 0;
- default:
- // TODO: how to handle SCREEN_ORIENTATION_BEHIND, UNSET?
- // For UNSPECIFIED use preferred orientation matching SCREEN_ORIENTATION_USER
+ case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
+ // It's possible for the user pref to be set at 180 because of FULL_USER. This would
+ // make switching to USER_PORTRAIT appear at 180. Provide choice to back to portrait
+ // but never to go to 180.
+ return preferredRotation == mPortraitRotation;
+
+ case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
+ // Works landscape or seascape
+ return isLandscapeOrSeascape(preferredRotation);
+
+ case ActivityInfo.SCREEN_ORIENTATION_USER:
+ case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
+ // Works with any rotation except upside down
return (preferredRotation >= 0) && (preferredRotation != mUpsideDownRotation);
}
+
+ return false;
}
private boolean isLandscapeOrSeascape(int rotation) {
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
index a538967..847c90a 100644
--- a/services/core/java/com/android/server/power/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -33,6 +33,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.power.batterysaver.BatterySavingStats;
import com.android.server.power.batterysaver.CpuFrequencies;
import java.io.PrintWriter;
@@ -498,6 +499,8 @@
pw.print(" Noninteractive File values:\n");
dumpMap(pw, " ", mFilesForNoninteractive);
pw.println();
+ pw.println();
+ BatterySavingStats.getInstance().dump(pw, " ");
}
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index b986e04..bd4aa1c 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -21,6 +21,7 @@
import android.app.Dialog;
import android.app.IActivityManager;
import android.app.ProgressDialog;
+import android.app.admin.SecurityLog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -113,6 +114,7 @@
private static String METRIC_PM = "shutdown_package_manager";
private static String METRIC_RADIOS = "shutdown_radios";
private static String METRIC_RADIO = "shutdown_radio";
+ private static String METRIC_SHUTDOWN_TIME_START = "begin_shutdown";
private final Object mActionDoneSync = new Object();
private boolean mActionDone;
@@ -390,6 +392,10 @@
}
}
+ if (SecurityLog.isLoggingEnabled()) {
+ SecurityLog.writeEvent(SecurityLog.TAG_OS_SHUTDOWN);
+ }
+
// start the thread that initiates shutdown
sInstance.mHandler = new Handler() {
};
@@ -410,6 +416,7 @@
public void run() {
TimingsTraceLog shutdownTimingLog = newTimingsLog();
shutdownTimingLog.traceBegin("SystemServerShutdown");
+ metricShutdownStart();
metricStarted(METRIC_SYSTEM_SERVER);
BroadcastReceiver br = new BroadcastReceiver() {
@@ -525,7 +532,7 @@
shutdownTimingLog.traceEnd(); // SystemServerShutdown
metricEnded(METRIC_SYSTEM_SERVER);
- saveMetrics(mReboot);
+ saveMetrics(mReboot, mReason);
// Remaining work will be done by init, including vold shutdown
rebootOrShutdown(mContext, mReboot, mReason);
}
@@ -547,6 +554,12 @@
}
}
+ private static void metricShutdownStart() {
+ synchronized (TRON_METRICS) {
+ TRON_METRICS.put(METRIC_SHUTDOWN_TIME_START, System.currentTimeMillis());
+ }
+ }
+
private void setRebootProgress(final int progress, final CharSequence message) {
mHandler.post(new Runnable() {
@Override
@@ -668,10 +681,11 @@
PowerManagerService.lowLevelShutdown(reason);
}
- private static void saveMetrics(boolean reboot) {
+ private static void saveMetrics(boolean reboot, String reason) {
StringBuilder metricValue = new StringBuilder();
metricValue.append("reboot:");
metricValue.append(reboot ? "y" : "n");
+ metricValue.append(",").append("reason:").append(reason);
final int metricsSize = TRON_METRICS.size();
for (int i = 0; i < metricsSize; i++) {
final String name = TRON_METRICS.keyAt(i);
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index d4627c2..32f38b7 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -28,6 +28,7 @@
import android.content.IntentFilter;
import android.hardware.power.V1_0.PowerHint;
import android.net.Uri;
+import android.os.BatteryManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -50,6 +51,9 @@
import com.android.server.power.BatterySaverPolicy;
import com.android.server.power.BatterySaverPolicy.BatterySaverPolicyListener;
import com.android.server.power.PowerManagerService;
+import com.android.server.power.batterysaver.BatterySavingStats.BatterySaverState;
+import com.android.server.power.batterysaver.BatterySavingStats.DozeState;
+import com.android.server.power.batterysaver.BatterySavingStats.InteractiveState;
import java.util.ArrayList;
@@ -70,6 +74,8 @@
private final BatterySaverPolicy mBatterySaverPolicy;
+ private final BatterySavingStats mBatterySavingStats;
+
private static final String WARNING_LINK_URL = "http://goto.google.com/extreme-battery-saver";
@GuardedBy("mLock")
@@ -78,6 +84,9 @@
@GuardedBy("mLock")
private boolean mEnabled;
+ @GuardedBy("mLock")
+ private boolean mIsPluggedIn;
+
/**
* Previously enabled or not; only for the event logging. Only use it from
* {@link #handleBatterySaverStateChanged}.
@@ -104,15 +113,28 @@
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ if (DEBUG) {
+ Slog.d(TAG, "onReceive: " + intent);
+ }
switch (intent.getAction()) {
case Intent.ACTION_SCREEN_ON:
case Intent.ACTION_SCREEN_OFF:
if (!isEnabled()) {
+ updateBatterySavingStats();
return; // No need to send it if not enabled.
}
// Don't send the broadcast, because we never did so in this case.
mHandler.postStateChanged(/*sendBroadcast=*/ false);
break;
+ case Intent.ACTION_BATTERY_CHANGED:
+ synchronized (mLock) {
+ mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
+ }
+ // Fall-through.
+ case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
+ case PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED:
+ updateBatterySavingStats();
+ break;
}
}
};
@@ -126,6 +148,7 @@
mBatterySaverPolicy = policy;
mBatterySaverPolicy.addListener(this);
mFileUpdater = new FileUpdater(context);
+ mBatterySavingStats = BatterySavingStats.getInstance();
// Initialize plugins.
final ArrayList<Plugin> plugins = new ArrayList<>();
@@ -149,6 +172,9 @@
public void systemReady() {
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
mContext.registerReceiver(mReceiver, filter);
mFileUpdater.systemReady(LocalServices.getService(ActivityManagerInternal.class)
@@ -280,7 +306,6 @@
enabled = mEnabled;
mIsInteractive = isInteractive;
-
if (enabled) {
fileValues = mBatterySaverPolicy.getFileValues(isInteractive);
} else {
@@ -293,6 +318,8 @@
pmi.powerHint(PowerHint.LOW_POWER, enabled ? 1 : 0);
}
+ updateBatterySavingStats();
+
if (ArrayUtils.isEmpty(fileValues)) {
mFileUpdater.restoreDefault();
} else {
@@ -332,7 +359,6 @@
mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
Manifest.permission.DEVICE_POWER);
-
for (LowPowerModeListener listener : listeners) {
final PowerSaveState result =
mBatterySaverPolicy.getBatterySaverPolicy(
@@ -388,4 +414,28 @@
foregroundUser);
}
}
+
+ private void updateBatterySavingStats() {
+ final PowerManager pm = getPowerManager();
+ if (pm == null) {
+ Slog.wtf(TAG, "PowerManager not initialized");
+ return;
+ }
+ final boolean isInteractive = pm.isInteractive();
+ final int dozeMode =
+ pm.isDeviceIdleMode() ? DozeState.DEEP
+ : pm.isLightDeviceIdleMode() ? DozeState.LIGHT
+ : DozeState.NOT_DOZING;
+
+ synchronized (mLock) {
+ if (mIsPluggedIn) {
+ mBatterySavingStats.startCharging();
+ return;
+ }
+ mBatterySavingStats.transitionState(
+ mEnabled ? BatterySaverState.ON : BatterySaverState.OFF,
+ isInteractive ? InteractiveState.INTERACTIVE : InteractiveState.NON_INTERACTIVE,
+ dozeMode);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
new file mode 100644
index 0000000..9466350
--- /dev/null
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
@@ -0,0 +1,414 @@
+/*
+ * 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.server.power.batterysaver;
+
+import android.os.BatteryManagerInternal;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
+import com.android.server.power.BatterySaverPolicy;
+
+import java.io.PrintWriter;
+
+/**
+ * This class keeps track of battery drain rate.
+ *
+ * Test:
+ atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java
+ */
+public class BatterySavingStats {
+
+ private static final String TAG = "BatterySavingStats";
+
+ private static final boolean DEBUG = BatterySaverPolicy.DEBUG;
+
+ private final Object mLock = new Object();
+
+ /** Whether battery saver is on or off. */
+ interface BatterySaverState {
+ int OFF = 0;
+ int ON = 1;
+
+ int SHIFT = 0;
+ int BITS = 1;
+ int MASK = (1 << BITS) - 1;
+
+ static int fromIndex(int index) {
+ return (index >> SHIFT) & MASK;
+ }
+ }
+
+ /** Whether the device is interactive (i.e. screen on) or not. */
+ interface InteractiveState {
+ int NON_INTERACTIVE = 0;
+ int INTERACTIVE = 1;
+
+ int SHIFT = BatterySaverState.SHIFT + BatterySaverState.BITS;
+ int BITS = 1;
+ int MASK = (1 << BITS) - 1;
+
+ static int fromIndex(int index) {
+ return (index >> SHIFT) & MASK;
+ }
+ }
+
+ /** Doze mode. */
+ interface DozeState {
+ int NOT_DOZING = 0;
+ int LIGHT = 1;
+ int DEEP = 2;
+
+ int SHIFT = InteractiveState.SHIFT + InteractiveState.BITS;
+ int BITS = 2;
+ int MASK = (1 << BITS) - 1;
+
+ static int fromIndex(int index) {
+ return (index >> SHIFT) & MASK;
+ }
+ }
+
+ /**
+ * Various stats in each state.
+ */
+ static class Stat {
+ public long startTime;
+ public long endTime;
+
+ public int startBatteryLevel;
+ public int endBatteryLevel;
+
+ public long totalTimeMillis;
+ public int totalBatteryDrain;
+
+ public long totalMinutes() {
+ return totalTimeMillis / 60_000;
+ }
+
+ public double drainPerHour() {
+ if (totalTimeMillis == 0) {
+ return 0;
+ }
+ return (double) totalBatteryDrain / (totalTimeMillis / (60.0 * 60 * 1000));
+ }
+
+ @VisibleForTesting
+ String toStringForTest() {
+ return "{" + totalMinutes() + "m," + totalBatteryDrain + ","
+ + String.format("%.2f", drainPerHour()) + "}";
+ }
+ }
+
+ @VisibleForTesting
+ static final String COUNTER_POWER_MILLIAMPS_PREFIX = "battery_saver_stats_milliamps_";
+
+ @VisibleForTesting
+ static final String COUNTER_TIME_SECONDS_PREFIX = "battery_saver_stats_seconds_";
+
+ private static BatterySavingStats sInstance;
+
+ private BatteryManagerInternal mBatteryManagerInternal;
+ private final MetricsLogger mMetricsLogger;
+
+ private static final int STATE_NOT_INITIALIZED = -1;
+ private static final int STATE_CHARGING = -2;
+
+ /**
+ * Current state, one of STATE_* or values returned by {@link #statesToIndex}.
+ */
+ @GuardedBy("mLock")
+ private int mCurrentState = STATE_NOT_INITIALIZED;
+
+ /**
+ * Stats in each state.
+ */
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ final ArrayMap<Integer, Stat> mStats = new ArrayMap<>();
+
+ private final MetricsLoggerHelper mMetricsLoggerHelper = new MetricsLoggerHelper();
+
+ /**
+ * Don't call it directly -- use {@link #getInstance()}. Not private for testing.
+ * @param metricsLogger
+ */
+ @VisibleForTesting
+ BatterySavingStats(MetricsLogger metricsLogger) {
+ mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class);
+ mMetricsLogger = metricsLogger;
+ }
+
+ public static synchronized BatterySavingStats getInstance() {
+ if (sInstance == null) {
+ sInstance = new BatterySavingStats(new MetricsLogger());
+ }
+ return sInstance;
+ }
+
+ private BatteryManagerInternal getBatteryManagerInternal() {
+ if (mBatteryManagerInternal == null) {
+ mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class);
+ }
+ return mBatteryManagerInternal;
+ }
+
+ /**
+ * Takes a state triplet and generates a state index.
+ */
+ @VisibleForTesting
+ static int statesToIndex(
+ int batterySaverState, int interactiveState, int dozeState) {
+ int ret = batterySaverState & BatterySaverState.MASK;
+ ret |= (interactiveState & InteractiveState.MASK) << InteractiveState.SHIFT;
+ ret |= (dozeState & DozeState.MASK) << DozeState.SHIFT;
+ return ret;
+ }
+
+ /**
+ * Takes a state index and returns a string for logging.
+ */
+ @VisibleForTesting
+ static String stateToString(int state) {
+ switch (state) {
+ case STATE_NOT_INITIALIZED:
+ return "NotInitialized";
+ case STATE_CHARGING:
+ return "Charging";
+ }
+ return "BS=" + BatterySaverState.fromIndex(state)
+ + ",I=" + InteractiveState.fromIndex(state)
+ + ",D=" + DozeState.fromIndex(state);
+ }
+
+ /**
+ * @return {@link Stat} fo a given state.
+ */
+ @VisibleForTesting
+ Stat getStat(int stateIndex) {
+ synchronized (mLock) {
+ Stat stat = mStats.get(stateIndex);
+ if (stat == null) {
+ stat = new Stat();
+ mStats.put(stateIndex, stat);
+ }
+ return stat;
+ }
+ }
+
+ /**
+ * @return {@link Stat} fo a given state triplet.
+ */
+ private Stat getStat(int batterySaverState, int interactiveState, int dozeState) {
+ return getStat(statesToIndex(batterySaverState, interactiveState, dozeState));
+ }
+
+ @VisibleForTesting
+ long injectCurrentTime() {
+ return SystemClock.elapsedRealtime();
+ }
+
+ @VisibleForTesting
+ int injectBatteryLevel() {
+ final BatteryManagerInternal bmi = getBatteryManagerInternal();
+ if (bmi == null) {
+ Slog.wtf(TAG, "BatteryManagerInternal not initialized");
+ return 0;
+ }
+ return bmi.getBatteryChargeCounter();
+ }
+
+ /**
+ * Called from the outside whenever any of the states changes, when the device is not plugged
+ * in.
+ */
+ public void transitionState(int batterySaverState, int interactiveState, int dozeState) {
+ synchronized (mLock) {
+ final int newState = statesToIndex(
+ batterySaverState, interactiveState, dozeState);
+ transitionStateLocked(newState);
+ }
+ }
+
+ /**
+ * Called from the outside when the device is plugged in.
+ */
+ public void startCharging() {
+ synchronized (mLock) {
+ transitionStateLocked(STATE_CHARGING);
+ }
+ }
+
+ private void transitionStateLocked(int newState) {
+ if (mCurrentState == newState) {
+ return;
+ }
+ final long now = injectCurrentTime();
+ final int batteryLevel = injectBatteryLevel();
+
+ endLastStateLocked(now, batteryLevel);
+ startNewStateLocked(newState, now, batteryLevel);
+ mMetricsLoggerHelper.transitionState(newState, now, batteryLevel);
+ }
+
+ private void endLastStateLocked(long now, int batteryLevel) {
+ if (mCurrentState < 0) {
+ return;
+ }
+ final Stat stat = getStat(mCurrentState);
+
+ stat.endBatteryLevel = batteryLevel;
+ stat.endTime = now;
+
+ final long deltaTime = stat.endTime - stat.startTime;
+ final int deltaDrain = stat.startBatteryLevel - stat.endBatteryLevel;
+
+ stat.totalTimeMillis += deltaTime;
+ stat.totalBatteryDrain += deltaDrain;
+
+ if (DEBUG) {
+ Slog.d(TAG, "State summary: " + stateToString(mCurrentState)
+ + ": " + (deltaTime / 1_000) + "s "
+ + "Start level: " + stat.startBatteryLevel + "uA "
+ + "End level: " + stat.endBatteryLevel + "uA "
+ + deltaDrain + "uA");
+ }
+ EventLogTags.writeBatterySavingStats(
+ BatterySaverState.fromIndex(mCurrentState),
+ InteractiveState.fromIndex(mCurrentState),
+ DozeState.fromIndex(mCurrentState),
+ deltaTime,
+ deltaDrain,
+ stat.totalTimeMillis,
+ stat.totalBatteryDrain);
+
+ }
+
+ private void startNewStateLocked(int newState, long now, int batteryLevel) {
+ if (DEBUG) {
+ Slog.d(TAG, "New state: " + stateToString(newState));
+ }
+ mCurrentState = newState;
+
+ if (mCurrentState < 0) {
+ return;
+ }
+
+ final Stat stat = getStat(mCurrentState);
+ stat.startBatteryLevel = batteryLevel;
+ stat.startTime = now;
+ stat.endTime = 0;
+ }
+
+ public void dump(PrintWriter pw, String indent) {
+ synchronized (mLock) {
+ pw.print(indent);
+ pw.println("Battery Saving Stats:");
+
+ indent = indent + " ";
+
+ pw.print(indent);
+ pw.println("Battery Saver: Off On");
+ dumpLineLocked(pw, indent, InteractiveState.NON_INTERACTIVE, "NonIntr",
+ DozeState.NOT_DOZING, "NonDoze");
+ dumpLineLocked(pw, indent, InteractiveState.INTERACTIVE, " Intr",
+ DozeState.NOT_DOZING, " ");
+
+ dumpLineLocked(pw, indent, InteractiveState.NON_INTERACTIVE, "NonIntr",
+ DozeState.DEEP, "Deep ");
+ dumpLineLocked(pw, indent, InteractiveState.INTERACTIVE, " Intr",
+ DozeState.DEEP, " ");
+
+ dumpLineLocked(pw, indent, InteractiveState.NON_INTERACTIVE, "NonIntr",
+ DozeState.LIGHT, "Light ");
+ dumpLineLocked(pw, indent, InteractiveState.INTERACTIVE, " Intr",
+ DozeState.LIGHT, " ");
+
+ pw.println();
+ }
+ }
+
+ private void dumpLineLocked(PrintWriter pw, String indent,
+ int interactiveState, String interactiveLabel,
+ int dozeState, String dozeLabel) {
+ pw.print(indent);
+ pw.print(dozeLabel);
+ pw.print(" ");
+ pw.print(interactiveLabel);
+ pw.print(": ");
+
+ final Stat offStat = getStat(BatterySaverState.OFF, interactiveState, dozeState);
+ final Stat onStat = getStat(BatterySaverState.ON, interactiveState, dozeState);
+
+ pw.println(String.format("%6dm %6dmA %8.1fmA/h %6dm %6dmA %8.1fmA/h",
+ offStat.totalMinutes(),
+ offStat.totalBatteryDrain / 1000,
+ offStat.drainPerHour() / 1000.0,
+ onStat.totalMinutes(),
+ onStat.totalBatteryDrain / 1000,
+ onStat.drainPerHour() / 1000.0));
+ }
+
+ @VisibleForTesting
+ class MetricsLoggerHelper {
+ private int mLastState = STATE_NOT_INITIALIZED;
+ private long mStartTime;
+ private int mStartBatteryLevel;
+
+ private static final int STATE_CHANGE_DETECT_MASK =
+ (BatterySaverState.MASK << BatterySaverState.SHIFT) |
+ (InteractiveState.MASK << InteractiveState.SHIFT);
+
+ public void transitionState(int newState, long now, int batteryLevel) {
+ final boolean stateChanging =
+ ((mLastState >= 0) ^ (newState >= 0)) ||
+ (((mLastState ^ newState) & STATE_CHANGE_DETECT_MASK) != 0);
+ if (stateChanging) {
+ if (mLastState >= 0) {
+ final long deltaTime = now - mStartTime;
+ final int deltaBattery = mStartBatteryLevel - batteryLevel;
+
+ report(mLastState, deltaTime, deltaBattery);
+ }
+ mStartTime = now;
+ mStartBatteryLevel = batteryLevel;
+ }
+ mLastState = newState;
+ }
+
+ String getCounterSuffix(int state) {
+ final boolean batterySaver =
+ BatterySaverState.fromIndex(state) != BatterySaverState.OFF;
+ final boolean interactive =
+ InteractiveState.fromIndex(state) != InteractiveState.NON_INTERACTIVE;
+ if (batterySaver) {
+ return interactive ? "11" : "10";
+ } else {
+ return interactive ? "01" : "00";
+ }
+ }
+
+ void report(int state, long deltaTimeMs, int deltaBatteryUa) {
+ final String suffix = getCounterSuffix(state);
+ mMetricsLogger.count(COUNTER_POWER_MILLIAMPS_PREFIX + suffix, deltaBatteryUa / 1000);
+ mMetricsLogger.count(COUNTER_TIME_SECONDS_PREFIX + suffix, (int) (deltaTimeMs / 1000));
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/slice/PinnedSliceState.java b/services/core/java/com/android/server/slice/PinnedSliceState.java
index 5811714..8da16d7 100644
--- a/services/core/java/com/android/server/slice/PinnedSliceState.java
+++ b/services/core/java/com/android/server/slice/PinnedSliceState.java
@@ -14,12 +14,15 @@
package com.android.server.slice;
+import static android.app.slice.SliceManager.PERMISSION_GRANTED;
+
import android.app.slice.ISliceListener;
import android.app.slice.Slice;
import android.app.slice.SliceProvider;
import android.app.slice.SliceSpec;
import android.content.ContentProviderClient;
import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
@@ -51,18 +54,16 @@
@GuardedBy("mLock")
private final ArraySet<String> mPinnedPkgs = new ArraySet<>();
@GuardedBy("mLock")
- private final ArrayMap<IBinder, ISliceListener> mListeners = new ArrayMap<>();
+ private final ArrayMap<IBinder, ListenerInfo> mListeners = new ArrayMap<>();
@GuardedBy("mLock")
private SliceSpec[] mSupportedSpecs = null;
- @GuardedBy("mLock")
- private final ArrayMap<IBinder, String> mPkgMap = new ArrayMap<>();
private final DeathRecipient mDeathRecipient = this::handleRecheckListeners;
+ private boolean mSlicePinned;
public PinnedSliceState(SliceManagerService service, Uri uri) {
mService = service;
mUri = uri;
- mService.getHandler().post(this::handleSendPinned);
mLock = mService.getLock();
}
@@ -102,14 +103,27 @@
}
public void destroy() {
- mService.getHandler().post(this::handleSendUnpinned);
+ setSlicePinned(false);
}
public void onChange() {
mService.getHandler().post(this::handleBind);
}
- public void addSliceListener(ISliceListener listener, String pkg, SliceSpec[] specs) {
+ private void setSlicePinned(boolean pinned) {
+ synchronized (mLock) {
+ if (mSlicePinned == pinned) return;
+ mSlicePinned = pinned;
+ if (pinned) {
+ mService.getHandler().post(this::handleSendPinned);
+ } else {
+ mService.getHandler().post(this::handleSendUnpinned);
+ }
+ }
+ }
+
+ public void addSliceListener(ISliceListener listener, String pkg, SliceSpec[] specs,
+ boolean hasPermission) {
synchronized (mLock) {
if (mListeners.size() == 0) {
mService.listen(mUri);
@@ -118,26 +132,27 @@
listener.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
}
- mListeners.put(listener.asBinder(), listener);
- mPkgMap.put(listener.asBinder(), pkg);
+ mListeners.put(listener.asBinder(), new ListenerInfo(listener, pkg, hasPermission,
+ Binder.getCallingUid(), Binder.getCallingPid()));
mergeSpecs(specs);
+ setSlicePinned(hasPermission);
}
}
public boolean removeSliceListener(ISliceListener listener) {
synchronized (mLock) {
listener.asBinder().unlinkToDeath(mDeathRecipient, 0);
- mPkgMap.remove(listener.asBinder());
if (mListeners.containsKey(listener.asBinder()) && mListeners.size() == 1) {
mService.unlisten(mUri);
}
mListeners.remove(listener.asBinder());
}
- return !isPinned();
+ return !hasPinOrListener();
}
public void pin(String pkg, SliceSpec[] specs) {
synchronized (mLock) {
+ setSlicePinned(true);
mPinnedPkgs.add(pkg);
mergeSpecs(specs);
}
@@ -147,7 +162,7 @@
synchronized (mLock) {
mPinnedPkgs.remove(pkg);
}
- return !isPinned();
+ return !hasPinOrListener();
}
public boolean isListening() {
@@ -156,8 +171,32 @@
}
}
+ public void recheckPackage(String pkg) {
+ synchronized (mLock) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ ListenerInfo info = mListeners.valueAt(i);
+ if (!info.hasPermission && Objects.equals(info.pkg, pkg)) {
+ mService.getHandler().post(() -> {
+ // This bind lets the app itself participate in the permission grant.
+ Slice s = doBind(info);
+ if (mService.checkAccess(info.pkg, mUri, info.callingUid, info.callingPid)
+ == PERMISSION_GRANTED) {
+ info.hasPermission = true;
+ setSlicePinned(true);
+ try {
+ info.listener.onSliceUpdated(s);
+ } catch (RemoteException e) {
+ checkSelfRemove();
+ }
+ }
+ });
+ }
+ }
+ }
+ }
+
@VisibleForTesting
- public boolean isPinned() {
+ public boolean hasPinOrListener() {
synchronized (mLock) {
return !mPinnedPkgs.isEmpty() || !mListeners.isEmpty();
}
@@ -166,62 +205,71 @@
ContentProviderClient getClient() {
ContentProviderClient client =
mService.getContext().getContentResolver().acquireContentProviderClient(mUri);
+ if (client == null) return null;
client.setDetectNotResponding(SLICE_TIMEOUT);
return client;
}
+ private void checkSelfRemove() {
+ if (!hasPinOrListener()) {
+ // All the listeners died, remove from pinned state.
+ mService.unlisten(mUri);
+ mService.removePinnedSlice(mUri);
+ }
+ }
+
private void handleRecheckListeners() {
- if (!isPinned()) return;
+ if (!hasPinOrListener()) return;
synchronized (mLock) {
for (int i = mListeners.size() - 1; i >= 0; i--) {
- ISliceListener l = mListeners.valueAt(i);
- if (!l.asBinder().isBinderAlive()) {
+ ListenerInfo l = mListeners.valueAt(i);
+ if (!l.listener.asBinder().isBinderAlive()) {
mListeners.removeAt(i);
}
}
- if (!isPinned()) {
- // All the listeners died, remove from pinned state.
- mService.removePinnedSlice(mUri);
- }
+ checkSelfRemove();
}
}
private void handleBind() {
Slice cachedSlice = doBind(null);
synchronized (mLock) {
- if (!isPinned()) return;
+ if (!hasPinOrListener()) return;
for (int i = mListeners.size() - 1; i >= 0; i--) {
- ISliceListener l = mListeners.valueAt(i);
+ ListenerInfo info = mListeners.valueAt(i);
Slice s = cachedSlice;
- if (s == null || s.hasHint(Slice.HINT_CALLER_NEEDED)) {
- s = doBind(mPkgMap.get(l));
+ if (s == null || s.hasHint(Slice.HINT_CALLER_NEEDED)
+ || !info.hasPermission) {
+ s = doBind(info);
}
if (s == null) {
mListeners.removeAt(i);
continue;
}
try {
- l.onSliceUpdated(s);
+ info.listener.onSliceUpdated(s);
} catch (RemoteException e) {
Log.e(TAG, "Unable to notify slice " + mUri, e);
mListeners.removeAt(i);
continue;
}
}
- if (!isPinned()) {
- // All the listeners died, remove from pinned state.
- mService.removePinnedSlice(mUri);
- }
+ checkSelfRemove();
}
}
- private Slice doBind(String overridePkg) {
+ private Slice doBind(ListenerInfo info) {
try (ContentProviderClient client = getClient()) {
+ if (client == null) return null;
Bundle extras = new Bundle();
extras.putParcelable(SliceProvider.EXTRA_BIND_URI, mUri);
extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS,
new ArrayList<>(Arrays.asList(mSupportedSpecs)));
- extras.putString(SliceProvider.EXTRA_OVERRIDE_PKG, overridePkg);
+ if (info != null) {
+ extras.putString(SliceProvider.EXTRA_OVERRIDE_PKG, info.pkg);
+ extras.putInt(SliceProvider.EXTRA_OVERRIDE_UID, info.callingUid);
+ extras.putInt(SliceProvider.EXTRA_OVERRIDE_PID, info.callingPid);
+ }
final Bundle res;
try {
res = client.call(SliceProvider.METHOD_SLICE, null, extras);
@@ -232,11 +280,16 @@
if (res == null) return null;
Bundle.setDefusable(res, true);
return res.getParcelable(SliceProvider.EXTRA_SLICE);
+ } catch (Throwable t) {
+ // Calling out of the system process, make sure they don't throw anything at us.
+ Log.e(TAG, "Caught throwable while binding " + mUri, t);
+ return null;
}
}
private void handleSendPinned() {
try (ContentProviderClient client = getClient()) {
+ if (client == null) return;
Bundle b = new Bundle();
b.putParcelable(SliceProvider.EXTRA_BIND_URI, mUri);
try {
@@ -249,6 +302,7 @@
private void handleSendUnpinned() {
try (ContentProviderClient client = getClient()) {
+ if (client == null) return;
Bundle b = new Bundle();
b.putParcelable(SliceProvider.EXTRA_BIND_URI, mUri);
try {
@@ -258,4 +312,22 @@
}
}
}
+
+ private class ListenerInfo {
+
+ private ISliceListener listener;
+ private String pkg;
+ private boolean hasPermission;
+ private int callingUid;
+ private int callingPid;
+
+ public ListenerInfo(ISliceListener listener, String pkg, boolean hasPermission,
+ int callingUid, int callingPid) {
+ this.listener = listener;
+ this.pkg = pkg;
+ this.hasPermission = hasPermission;
+ this.callingUid = callingUid;
+ this.callingPid = callingPid;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/slice/SliceFullAccessList.java b/services/core/java/com/android/server/slice/SliceFullAccessList.java
new file mode 100644
index 0000000..591e809
--- /dev/null
+++ b/services/core/java/com/android/server/slice/SliceFullAccessList.java
@@ -0,0 +1,131 @@
+/*
+ * 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.server.slice;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.List;
+
+public class SliceFullAccessList {
+
+ static final int DB_VERSION = 1;
+ private static final String TAG = "SliceFullAccessList";
+
+ private static final String TAG_LIST = "slice-access-list";
+ private static final String TAG_PKG = "pkg";
+ private static final String TAG_USER = "user";
+
+ private final String ATT_USER_ID = "user";
+ private final String ATT_VERSION = "version";
+
+ private final SparseArray<ArraySet<String>> mFullAccessPkgs = new SparseArray<>();
+ private final Context mContext;
+
+ public SliceFullAccessList(Context context) {
+ mContext = context;
+ }
+
+ public boolean hasFullAccess(String pkg, int userId) {
+ ArraySet<String> pkgs = mFullAccessPkgs.get(userId, null);
+ return pkgs != null && pkgs.contains(pkg);
+ }
+
+ public void grantFullAccess(String pkg, int userId) {
+ ArraySet<String> pkgs = mFullAccessPkgs.get(userId, null);
+ if (pkgs == null) {
+ pkgs = new ArraySet<>();
+ mFullAccessPkgs.put(userId, pkgs);
+ }
+ pkgs.add(pkg);
+ }
+
+ public void writeXml(XmlSerializer out) throws IOException {
+ out.startTag(null, TAG_LIST);
+ out.attribute(null, ATT_VERSION, String.valueOf(DB_VERSION));
+
+ final int N = mFullAccessPkgs.size();
+ for (int i = 0 ; i < N; i++) {
+ final int userId = mFullAccessPkgs.keyAt(i);
+ final ArraySet<String> pkgs = mFullAccessPkgs.valueAt(i);
+ out.startTag(null, TAG_USER);
+ out.attribute(null, ATT_USER_ID, Integer.toString(userId));
+ if (pkgs != null) {
+ final int M = pkgs.size();
+ for (int j = 0; j < M; j++) {
+ out.startTag(null, TAG_PKG);
+ out.text(pkgs.valueAt(j));
+ out.endTag(null, TAG_PKG);
+
+ }
+ }
+ out.endTag(null, TAG_USER);
+ }
+ out.endTag(null, TAG_LIST);
+ }
+
+ public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException {
+ // upgrade xml
+ int xmlVersion = XmlUtils.readIntAttribute(parser, ATT_VERSION, 0);
+ final List<UserInfo> activeUsers = UserManager.get(mContext).getUsers(true);
+ for (UserInfo userInfo : activeUsers) {
+ upgradeXml(xmlVersion, userInfo.getUserHandle().getIdentifier());
+ }
+
+ mFullAccessPkgs.clear();
+ // read grants
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ String tag = parser.getName();
+ if (type == XmlPullParser.END_TAG
+ && TAG_LIST.equals(tag)) {
+ break;
+ }
+ if (type == XmlPullParser.START_TAG) {
+ if (TAG_USER.equals(tag)) {
+ final int userId = XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0);
+ ArraySet<String> pkgs = new ArraySet<>();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ String userTag = parser.getName();
+ if (type == XmlPullParser.END_TAG
+ && TAG_USER.equals(userTag)) {
+ break;
+ }
+ if (type == XmlPullParser.START_TAG) {
+ if (TAG_PKG.equals(userTag)) {
+ final String pkg = parser.nextText();
+ pkgs.add(pkg);
+ }
+ }
+ }
+ mFullAccessPkgs.put(userId, pkgs);
+ }
+ }
+ }
+ }
+
+ protected void upgradeXml(final int xmlVersion, final int userId) {}
+}
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index c191580..5db0fc0 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -19,6 +19,8 @@
import static android.content.ContentProvider.getUriWithoutUserId;
import static android.content.ContentProvider.getUserIdFromUri;
import static android.content.ContentProvider.maybeAddUserId;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.Manifest.permission;
import android.app.ActivityManager;
@@ -32,20 +34,24 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
+import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.AtomicFile;
import android.util.Log;
+import android.util.Slog;
+import android.util.Xml.Encoding;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -55,6 +61,16 @@
import com.android.server.ServiceThread;
import com.android.server.SystemService;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -75,6 +91,8 @@
private final ArraySet<SliceGrant> mUserGrants = new ArraySet<>();
private final Handler mHandler;
private final ContentObserver mObserver;
+ private final AtomicFile mSliceAccessFile;
+ private final SliceFullAccessList mAccessList;
public SliceManagerService(Context context) {
this(context, createHandler().getLooper());
@@ -99,6 +117,21 @@
}
}
};
+ final File systemDir = new File(Environment.getDataDirectory(), "system");
+ mSliceAccessFile = new AtomicFile(new File(systemDir, "slice_access.xml"));
+ mAccessList = new SliceFullAccessList(mContext);
+
+ synchronized (mSliceAccessFile) {
+ if (!mSliceAccessFile.exists()) return;
+ try {
+ InputStream input = mSliceAccessFile.openRead();
+ XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+ parser.setInput(input, Encoding.UTF_8.name());
+ mAccessList.readXml(parser);
+ } catch (IOException | XmlPullParserException e) {
+ Slog.d(TAG, "Can't read slice access file", e);
+ }
+ }
}
/// ----- Lifecycle stuff -----
@@ -120,8 +153,10 @@
throws RemoteException {
verifyCaller(pkg);
uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier());
- enforceAccess(pkg, uri);
- getOrCreatePinnedSlice(uri).addSliceListener(listener, pkg, specs);
+ enforceCrossUser(pkg, uri);
+ getOrCreatePinnedSlice(uri).addSliceListener(listener, pkg, specs,
+ checkAccess(pkg, uri, Binder.getCallingUid(), Binder.getCallingUid())
+ == PERMISSION_GRANTED);
}
@Override
@@ -129,7 +164,6 @@
throws RemoteException {
verifyCaller(pkg);
uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier());
- enforceAccess(pkg, uri);
if (getPinnedSlice(uri).removeSliceListener(listener)) {
removePinnedSlice(uri);
}
@@ -169,14 +203,14 @@
@Override
public int checkSlicePermission(Uri uri, String pkg, int pid, int uid) throws RemoteException {
if (mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
- == PackageManager.PERMISSION_GRANTED) {
+ == PERMISSION_GRANTED) {
return SliceManager.PERMISSION_GRANTED;
}
- if (hasFullSliceAccess(pkg, uid)) {
+ if (hasFullSliceAccess(pkg, UserHandle.getUserId(uid))) {
return SliceManager.PERMISSION_GRANTED;
}
synchronized (mLock) {
- if (mUserGrants.contains(new SliceGrant(uri, pkg))) {
+ if (mUserGrants.contains(new SliceGrant(uri, pkg, UserHandle.getUserId(uid)))) {
return SliceManager.PERMISSION_USER_GRANTED;
}
}
@@ -189,16 +223,23 @@
getContext().enforceCallingOrSelfPermission(permission.MANAGE_SLICE_PERMISSIONS,
"Slice granting requires MANAGE_SLICE_PERMISSIONS");
if (allSlices) {
- // TODO: Manage full access grants.
+ mAccessList.grantFullAccess(pkg, Binder.getCallingUserHandle().getIdentifier());
+ mHandler.post(mSaveAccessList);
} else {
synchronized (mLock) {
- mUserGrants.add(new SliceGrant(uri, pkg));
+ mUserGrants.add(new SliceGrant(uri, pkg,
+ Binder.getCallingUserHandle().getIdentifier()));
}
- long ident = Binder.clearCallingIdentity();
- try {
- mContext.getContentResolver().notifyChange(uri, null);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ }
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mContext.getContentResolver().notifyChange(uri, null);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ synchronized (mLock) {
+ for (PinnedSliceState p : mPinnedSlicesByUri.values()) {
+ p.recheckPackage(pkg);
}
}
}
@@ -249,17 +290,13 @@
return mHandler;
}
- private void enforceAccess(String pkg, Uri uri) throws RemoteException {
- int user = Binder.getCallingUserHandle().getIdentifier();
+ protected int checkAccess(String pkg, Uri uri, int uid, int pid) {
+ int user = UserHandle.getUserId(uid);
// Check for default launcher/assistant.
- if (!hasFullSliceAccess(pkg, Binder.getCallingUid())) {
- try {
- // Also allow things with uri access.
- getContext().enforceUriPermission(uri, Binder.getCallingPid(),
- Binder.getCallingUid(),
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
- "Slice binding requires permission to the Uri");
- } catch (SecurityException e) {
+ if (!hasFullSliceAccess(pkg, user)) {
+ // Also allow things with uri access.
+ if (getContext().checkUriPermission(uri, pid, uid,
+ Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != PERMISSION_GRANTED) {
// Last fallback (if the calling app owns the authority, then it can have access).
long ident = Binder.clearCallingIdentity();
try {
@@ -268,17 +305,21 @@
ContentProviderHolder holder = null;
String providerName = getUriWithoutUserId(uri).getAuthority();
try {
- holder = activityManager.getContentProviderExternal(
- providerName, getUserIdFromUri(uri, user), token);
- if (holder == null || holder.info == null
- || !Objects.equals(holder.info.packageName, pkg)) {
- // No more fallbacks, no access.
- throw e;
+ try {
+ holder = activityManager.getContentProviderExternal(
+ providerName, getUserIdFromUri(uri, user), token);
+ if (holder == null || holder.info == null
+ || !Objects.equals(holder.info.packageName, pkg)) {
+ return PERMISSION_DENIED;
+ }
+ } finally {
+ if (holder != null && holder.provider != null) {
+ activityManager.removeContentProviderExternal(providerName, token);
+ }
}
- } finally {
- if (holder != null && holder.provider != null) {
- activityManager.removeContentProviderExternal(providerName, token);
- }
+ } catch (RemoteException e) {
+ // Can't happen.
+ e.rethrowAsRuntimeException();
}
} finally {
// I know, the double finally seems ugly, but seems safest for the identity.
@@ -286,23 +327,31 @@
}
}
}
- // Lastly check for any multi-userness. Any return statements above here will break this
- // important check.
+ return PERMISSION_GRANTED;
+ }
+
+ private void enforceCrossUser(String pkg, Uri uri) {
+ int user = Binder.getCallingUserHandle().getIdentifier();
if (getUserIdFromUri(uri, user) != user) {
getContext().enforceCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL,
"Slice interaction across users requires INTERACT_ACROSS_USERS_FULL");
}
}
+ private void enforceAccess(String pkg, Uri uri) throws RemoteException {
+ if (checkAccess(pkg, uri, Binder.getCallingUid(), Binder.getCallingPid())
+ != PERMISSION_GRANTED) {
+ throw new SecurityException("Access to slice " + uri + " is required");
+ }
+ enforceCrossUser(pkg, uri);
+ }
+
private void enforceFullAccess(String pkg, String name, Uri uri) {
int user = Binder.getCallingUserHandle().getIdentifier();
if (!hasFullSliceAccess(pkg, user)) {
throw new SecurityException(String.format("Call %s requires full slice access", name));
}
- if (getUserIdFromUri(uri, user) != user) {
- getContext().enforceCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL,
- "Slice interaction across users requires INTERACT_ACROSS_USERS_FULL");
- }
+ enforceCrossUser(pkg, uri);
}
private void verifyCaller(String pkg) {
@@ -395,8 +444,7 @@
}
private boolean isGrantedFullAccess(String pkg, int userId) {
- // TODO: This will be user granted access, if we allow this through a prompt.
- return false;
+ return mAccessList.hasFullAccess(pkg, userId);
}
private static ServiceThread createHandler() {
@@ -406,6 +454,32 @@
return handlerThread;
}
+ private final Runnable mSaveAccessList = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mSliceAccessFile) {
+ final FileOutputStream stream;
+ try {
+ stream = mSliceAccessFile.startWrite();
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to save access file", e);
+ return;
+ }
+
+ try {
+ XmlSerializer out = XmlPullParserFactory.newInstance().newSerializer();
+ out.setOutput(stream, Encoding.UTF_8.name());
+ mAccessList.writeXml(out);
+ out.flush();
+ mSliceAccessFile.finishWrite(stream);
+ } catch (IOException | XmlPullParserException e) {
+ Slog.w(TAG, "Failed to save access file, restoring backup", e);
+ mSliceAccessFile.failWrite(stream);
+ }
+ }
+ }
+ };
+
public static class Lifecycle extends SystemService {
private SliceManagerService mService;
@@ -440,10 +514,12 @@
private class SliceGrant {
private final Uri mUri;
private final String mPkg;
+ private final int mUserId;
- public SliceGrant(Uri uri, String pkg) {
+ public SliceGrant(Uri uri, String pkg, int userId) {
mUri = uri;
mPkg = pkg;
+ mUserId = userId;
}
@Override
@@ -455,7 +531,8 @@
public boolean equals(Object obj) {
if (!(obj instanceof SliceGrant)) return false;
SliceGrant other = (SliceGrant) obj;
- return Objects.equals(other.mUri, mUri) && Objects.equals(other.mPkg, mPkg);
+ return Objects.equals(other.mUri, mUri) && Objects.equals(other.mPkg, mPkg)
+ && (other.mUserId == mUserId);
}
}
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index faafb39..f498cdd 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -19,6 +19,9 @@
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.StatsManager;
+import android.bluetooth.BluetoothActivityEnergyInfo;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.UidTraffic;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -30,7 +33,6 @@
import android.net.NetworkStats;
import android.net.wifi.IWifiManager;
import android.net.wifi.WifiActivityEnergyInfo;
-import android.os.StatsDimensionsValue;
import android.os.BatteryStatsInternal;
import android.os.Binder;
import android.os.Bundle;
@@ -43,6 +45,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
+import android.os.StatsDimensionsValue;
import android.os.StatsLogEventWrapper;
import android.os.SynchronousResultReceiver;
import android.os.SystemClock;
@@ -110,6 +113,7 @@
new StatFs(Environment.getRootDirectory().getAbsolutePath());
private final StatFs mStatFsTemp =
new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
+ private final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
public StatsCompanionService(Context context) {
super();
@@ -157,7 +161,8 @@
@Override
public void sendBroadcast(String pkg, String cls) {
- // TODO: Use a pending intent, and enfoceCallingPermission.
+ // TODO: Use a pending intent.
+ enforceCallingPermission();
mContext.sendBroadcastAsUser(new Intent(ACTION_TRIGGER_COLLECTION).setClassName(pkg, cls),
UserHandle.SYSTEM);
}
@@ -235,7 +240,7 @@
}
}
- public final static class AppUpdateReceiver extends BroadcastReceiver {
+ private final static class AppUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
/**
@@ -280,7 +285,7 @@
}
}
- public final static class AnomalyAlarmReceiver extends BroadcastReceiver {
+ private final static class AnomalyAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Slog.i(TAG, "StatsCompanionService believes an anomaly has occurred.");
@@ -300,7 +305,7 @@
}
}
- public final static class PullingAlarmReceiver extends BroadcastReceiver {
+ private final static class PullingAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG)
@@ -321,16 +326,18 @@
}
}
- public final static class ShutdownEventReceiver extends BroadcastReceiver {
+ private final static class ShutdownEventReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
/**
* Skip immediately if intent is not relevant to device shutdown.
*/
if (!intent.getAction().equals(Intent.ACTION_REBOOT)
- && !intent.getAction().equals(Intent.ACTION_SHUTDOWN)) {
- return;
+ && !(intent.getAction().equals(Intent.ACTION_SHUTDOWN)
+ && (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0)) {
+ return;
}
+
Slog.i(TAG, "StatsCompanionService noticed a shutdown.");
synchronized (sStatsdLock) {
if (sStatsd == null) {
@@ -402,24 +409,23 @@
}
}
- private StatsLogEventWrapper[] addNetworkStats(int tag, NetworkStats stats, boolean withFGBG) {
- List<StatsLogEventWrapper> ret = new ArrayList<>();
- int size = stats.size();
- NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling
- for (int j = 0; j < size; j++) {
- stats.getValues(j, entry);
- StatsLogEventWrapper e = new StatsLogEventWrapper(tag, withFGBG ? 6 : 5);
- e.writeInt(entry.uid);
- if (withFGBG) {
- e.writeInt(entry.set);
- }
- e.writeLong(entry.rxBytes);
- e.writeLong(entry.rxPackets);
- e.writeLong(entry.txBytes);
- e.writeLong(entry.txPackets);
- ret.add(e);
+ private void addNetworkStats(
+ int tag, List<StatsLogEventWrapper> ret, NetworkStats stats, boolean withFGBG) {
+ int size = stats.size();
+ NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling
+ for (int j = 0; j < size; j++) {
+ stats.getValues(j, entry);
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tag, withFGBG ? 6 : 5);
+ e.writeInt(entry.uid);
+ if (withFGBG) {
+ e.writeInt(entry.set);
}
- return ret.toArray(new StatsLogEventWrapper[ret.size()]);
+ e.writeLong(entry.rxBytes);
+ e.writeLong(entry.rxPackets);
+ e.writeLong(entry.txBytes);
+ e.writeLong(entry.txPackets);
+ ret.add(e);
+ }
}
/**
@@ -485,220 +491,289 @@
return null;
}
+ private void pullKernelWakelock(int tagId, List<StatsLogEventWrapper> pulledData) {
+ final KernelWakelockStats wakelockStats =
+ mKernelWakelockReader.readKernelWakelockStats(mTmpWakelockStats);
+ for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
+ String name = ent.getKey();
+ KernelWakelockStats.Entry kws = ent.getValue();
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 4);
+ e.writeString(name);
+ e.writeInt(kws.mCount);
+ e.writeInt(kws.mVersion);
+ e.writeLong(kws.mTotalTime);
+ pulledData.add(e);
+ }
+ }
+
+ private void pullWifiBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ // TODO: Consider caching the following call to get BatteryStatsInternal.
+ BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+ String[] ifaces = bs.getWifiIfaces();
+ if (ifaces.length == 0) {
+ return;
+ }
+ NetworkStatsFactory nsf = new NetworkStatsFactory();
+ // Combine all the metrics per Uid into one record.
+ NetworkStats stats =
+ nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null)
+ .groupedByUid();
+ addNetworkStats(tagId, pulledData, stats, false);
+ } catch (java.io.IOException e) {
+ Slog.e(TAG, "Pulling netstats for wifi bytes has error", e);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void pullWifiBytesTransferByFgBg(int tagId, List<StatsLogEventWrapper> pulledData) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+ String[] ifaces = bs.getWifiIfaces();
+ if (ifaces.length == 0) {
+ return;
+ }
+ NetworkStatsFactory nsf = new NetworkStatsFactory();
+ NetworkStats stats = rollupNetworkStatsByFGBG(
+ nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null));
+ addNetworkStats(tagId, pulledData, stats, true);
+ } catch (java.io.IOException e) {
+ Slog.e(TAG, "Pulling netstats for wifi bytes w/ fg/bg has error", e);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void pullMobileBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+ String[] ifaces = bs.getMobileIfaces();
+ if (ifaces.length == 0) {
+ return;
+ }
+ NetworkStatsFactory nsf = new NetworkStatsFactory();
+ // Combine all the metrics per Uid into one record.
+ NetworkStats stats =
+ nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null)
+ .groupedByUid();
+ addNetworkStats(tagId, pulledData, stats, false);
+ } catch (java.io.IOException e) {
+ Slog.e(TAG, "Pulling netstats for mobile bytes has error", e);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void pullBluetoothBytesTransfer(int tagId, List<StatsLogEventWrapper> pulledData) {
+ BluetoothActivityEnergyInfo info = pullBluetoothData();
+ for (UidTraffic traffic : info.getUidTraffic()) {
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
+ e.writeInt(traffic.getUid());
+ e.writeLong(traffic.getRxBytes());
+ e.writeLong(traffic.getTxBytes());
+ pulledData.add(e);
+ }
+ }
+
+ private void pullMobileBytesTransferByFgBg(int tagId, List<StatsLogEventWrapper> pulledData) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+ String[] ifaces = bs.getMobileIfaces();
+ if (ifaces.length == 0) {
+ return;
+ }
+ NetworkStatsFactory nsf = new NetworkStatsFactory();
+ NetworkStats stats = rollupNetworkStatsByFGBG(
+ nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces, NetworkStats.TAG_NONE, null));
+ addNetworkStats(tagId, pulledData, stats, true);
+ } catch (java.io.IOException e) {
+ Slog.e(TAG, "Pulling netstats for mobile bytes w/ fg/bg has error", e);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void pullCpuTimePerFreq(int tagId, List<StatsLogEventWrapper> pulledData) {
+ for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
+ long[] clusterTimeMs = mKernelCpuSpeedReaders[cluster].readAbsolute();
+ if (clusterTimeMs != null) {
+ for (int speed = clusterTimeMs.length - 1; speed >= 0; --speed) {
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
+ e.writeInt(cluster);
+ e.writeInt(speed);
+ e.writeLong(clusterTimeMs[speed]);
+ pulledData.add(e);
+ }
+ }
+ }
+ }
+
+ private void pullWifiActivityEnergyInfo(int tagId, List<StatsLogEventWrapper> pulledData) {
+ long token = Binder.clearCallingIdentity();
+ if (mWifiManager == null) {
+ mWifiManager =
+ IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
+ }
+ if (mWifiManager != null) {
+ try {
+ SynchronousResultReceiver wifiReceiver = new SynchronousResultReceiver("wifi");
+ mWifiManager.requestActivityInfo(wifiReceiver);
+ final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
+ e.writeLong(wifiInfo.getTimeStamp());
+ e.writeInt(wifiInfo.getStackState());
+ e.writeLong(wifiInfo.getControllerTxTimeMillis());
+ e.writeLong(wifiInfo.getControllerRxTimeMillis());
+ e.writeLong(wifiInfo.getControllerIdleTimeMillis());
+ e.writeLong(wifiInfo.getControllerEnergyUsed());
+ pulledData.add(e);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Pulling wifiManager for wifi controller activity energy info has error", e);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ private void pullModemActivityInfo(int tagId, List<StatsLogEventWrapper> pulledData) {
+ long token = Binder.clearCallingIdentity();
+ if (mTelephony == null) {
+ mTelephony = TelephonyManager.from(mContext);
+ }
+ if (mTelephony != null) {
+ SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
+ mTelephony.requestModemActivityInfo(modemReceiver);
+ final ModemActivityInfo modemInfo = awaitControllerInfo(modemReceiver);
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
+ e.writeLong(modemInfo.getTimestamp());
+ e.writeLong(modemInfo.getSleepTimeMillis());
+ e.writeLong(modemInfo.getIdleTimeMillis());
+ e.writeLong(modemInfo.getTxTimeMillis()[0]);
+ e.writeLong(modemInfo.getTxTimeMillis()[1]);
+ e.writeLong(modemInfo.getTxTimeMillis()[2]);
+ e.writeLong(modemInfo.getTxTimeMillis()[3]);
+ e.writeLong(modemInfo.getTxTimeMillis()[4]);
+ e.writeLong(modemInfo.getRxTimeMillis());
+ e.writeLong(modemInfo.getEnergyUsed());
+ pulledData.add(e);
+ }
+ }
+
+ private void pullBluetoothActivityInfo(int tagId, List<StatsLogEventWrapper> pulledData) {
+ BluetoothActivityEnergyInfo info = pullBluetoothData();
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
+ e.writeLong(info.getTimeStamp());
+ e.writeInt(info.getBluetoothStackState());
+ e.writeLong(info.getControllerTxTimeMillis());
+ e.writeLong(info.getControllerRxTimeMillis());
+ e.writeLong(info.getControllerIdleTimeMillis());
+ e.writeLong(info.getControllerEnergyUsed());
+ pulledData.add(e);
+ }
+
+ private synchronized BluetoothActivityEnergyInfo pullBluetoothData() {
+ if (adapter != null) {
+ SynchronousResultReceiver bluetoothReceiver = null;
+ bluetoothReceiver = new SynchronousResultReceiver("bluetooth");
+ adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
+ return awaitControllerInfo(bluetoothReceiver);
+ } else {
+ return null;
+ }
+ }
+
+ private void pullSystemElapsedRealtime(int tagId, List<StatsLogEventWrapper> pulledData) {
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 1);
+ e.writeLong(SystemClock.elapsedRealtime());
+ pulledData.add(e);
+ }
+
+ private void pullDiskSpace(int tagId, List<StatsLogEventWrapper> pulledData) {
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
+ e.writeLong(mStatFsData.getAvailableBytes());
+ e.writeLong(mStatFsSystem.getAvailableBytes());
+ e.writeLong(mStatFsTemp.getAvailableBytes());
+ pulledData.add(e);
+ }
+
+ private void pullSystemUpTime(int tagId, List<StatsLogEventWrapper> pulledData) {
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 1);
+ e.writeLong(SystemClock.uptimeMillis());
+ pulledData.add(e);
+ }
+
/**
- *
- * Pulls wifi controller activity energy info from WiFiManager
+ * Pulls various data.
*/
@Override // Binder call
public StatsLogEventWrapper[] pullData(int tagId) {
enforceCallingPermission();
if (DEBUG)
Slog.d(TAG, "Pulling " + tagId);
-
+ List<StatsLogEventWrapper> ret = new ArrayList();
switch (tagId) {
case StatsLog.WIFI_BYTES_TRANSFER: {
- long token = Binder.clearCallingIdentity();
- try {
- // TODO: Consider caching the following call to get BatteryStatsInternal.
- BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
- String[] ifaces = bs.getWifiIfaces();
- if (ifaces.length == 0) {
- return null;
- }
- NetworkStatsFactory nsf = new NetworkStatsFactory();
- // Combine all the metrics per Uid into one record.
- NetworkStats stats = nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
- NetworkStats.TAG_NONE, null).groupedByUid();
- return addNetworkStats(tagId, stats, false);
- } catch (java.io.IOException e) {
- Slog.e(TAG, "Pulling netstats for wifi bytes has error", e);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- break;
+ pullWifiBytesTransfer(tagId, ret);
+ break;
}
case StatsLog.MOBILE_BYTES_TRANSFER: {
- long token = Binder.clearCallingIdentity();
- try {
- BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
- String[] ifaces = bs.getMobileIfaces();
- if (ifaces.length == 0) {
- return null;
- }
- NetworkStatsFactory nsf = new NetworkStatsFactory();
- // Combine all the metrics per Uid into one record.
- NetworkStats stats = nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
- NetworkStats.TAG_NONE, null).groupedByUid();
- return addNetworkStats(tagId, stats, false);
- } catch (java.io.IOException e) {
- Slog.e(TAG, "Pulling netstats for mobile bytes has error", e);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- break;
+ pullMobileBytesTransfer(tagId, ret);
+ break;
}
case StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: {
- long token = Binder.clearCallingIdentity();
- try {
- BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
- String[] ifaces = bs.getWifiIfaces();
- if (ifaces.length == 0) {
- return null;
- }
- NetworkStatsFactory nsf = new NetworkStatsFactory();
- NetworkStats stats = rollupNetworkStatsByFGBG(
- nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
- NetworkStats.TAG_NONE, null));
- return addNetworkStats(tagId, stats, true);
- } catch (java.io.IOException e) {
- Slog.e(TAG, "Pulling netstats for wifi bytes w/ fg/bg has error", e);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- break;
+ pullWifiBytesTransferByFgBg(tagId, ret);
+ break;
}
case StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: {
- long token = Binder.clearCallingIdentity();
- try {
- BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
- String[] ifaces = bs.getMobileIfaces();
- if (ifaces.length == 0) {
- return null;
- }
- NetworkStatsFactory nsf = new NetworkStatsFactory();
- NetworkStats stats = rollupNetworkStatsByFGBG(
- nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
- NetworkStats.TAG_NONE, null));
- return addNetworkStats(tagId, stats, true);
- } catch (java.io.IOException e) {
- Slog.e(TAG, "Pulling netstats for mobile bytes w/ fg/bg has error", e);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- break;
+ pullMobileBytesTransferByFgBg(tagId, ret);
+ break;
+ }
+ case StatsLog.BLUETOOTH_BYTES_TRANSFER: {
+ pullBluetoothBytesTransfer(tagId, ret);
+ break;
}
case StatsLog.KERNEL_WAKELOCK: {
- final KernelWakelockStats wakelockStats =
- mKernelWakelockReader.readKernelWakelockStats(mTmpWakelockStats);
- List<StatsLogEventWrapper> ret = new ArrayList();
- for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
- String name = ent.getKey();
- KernelWakelockStats.Entry kws = ent.getValue();
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 4);
- e.writeString(name);
- e.writeInt(kws.mCount);
- e.writeInt(kws.mVersion);
- e.writeLong(kws.mTotalTime);
- ret.add(e);
- }
- return ret.toArray(new StatsLogEventWrapper[ret.size()]);
+ pullKernelWakelock(tagId, ret);
+ break;
}
case StatsLog.CPU_TIME_PER_FREQ: {
- List<StatsLogEventWrapper> ret = new ArrayList();
- for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
- long[] clusterTimeMs = mKernelCpuSpeedReaders[cluster].readAbsolute();
- if (clusterTimeMs != null) {
- for (int speed = clusterTimeMs.length - 1; speed >= 0; --speed) {
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
- e.writeInt(cluster);
- e.writeInt(speed);
- e.writeLong(clusterTimeMs[speed]);
- ret.add(e);
- }
- }
- }
- return ret.toArray(new StatsLogEventWrapper[ret.size()]);
+ pullCpuTimePerFreq(tagId, ret);
+ break;
}
case StatsLog.WIFI_ACTIVITY_ENERGY_INFO: {
- List<StatsLogEventWrapper> ret = new ArrayList();
- long token = Binder.clearCallingIdentity();
- if (mWifiManager == null) {
- mWifiManager = IWifiManager.Stub.asInterface(ServiceManager.getService(
- Context.WIFI_SERVICE));
- }
- if (mWifiManager != null) {
- try {
- SynchronousResultReceiver wifiReceiver = new SynchronousResultReceiver("wifi");
- mWifiManager.requestActivityInfo(wifiReceiver);
- final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
- e.writeLong(wifiInfo.getTimeStamp());
- e.writeInt(wifiInfo.getStackState());
- e.writeLong(wifiInfo.getControllerTxTimeMillis());
- e.writeLong(wifiInfo.getControllerRxTimeMillis());
- e.writeLong(wifiInfo.getControllerIdleTimeMillis());
- e.writeLong(wifiInfo.getControllerEnergyUsed());
- ret.add(e);
- return ret.toArray(new StatsLogEventWrapper[ret.size()]);
- } catch (RemoteException e) {
- Slog.e(TAG, "Pulling wifiManager for wifi controller activity energy info has error", e);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- break;
+ pullWifiActivityEnergyInfo(tagId, ret);
+ break;
}
case StatsLog.MODEM_ACTIVITY_INFO: {
- List<StatsLogEventWrapper> ret = new ArrayList();
- long token = Binder.clearCallingIdentity();
- if (mTelephony == null) {
- mTelephony = TelephonyManager.from(mContext);
- }
- if (mTelephony != null) {
- SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
- mTelephony.requestModemActivityInfo(modemReceiver);
- final ModemActivityInfo modemInfo = awaitControllerInfo(modemReceiver);
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 6);
- e.writeLong(modemInfo.getTimestamp());
- e.writeLong(modemInfo.getSleepTimeMillis());
- e.writeLong(modemInfo.getIdleTimeMillis());
- e.writeLong(modemInfo.getTxTimeMillis()[0]);
- e.writeLong(modemInfo.getTxTimeMillis()[1]);
- e.writeLong(modemInfo.getTxTimeMillis()[2]);
- e.writeLong(modemInfo.getTxTimeMillis()[3]);
- e.writeLong(modemInfo.getTxTimeMillis()[4]);
- e.writeLong(modemInfo.getRxTimeMillis());
- e.writeLong(modemInfo.getEnergyUsed());
- ret.add(e);
- return ret.toArray(new StatsLogEventWrapper[ret.size()]);
- }
- break;
+ pullModemActivityInfo(tagId, ret);
+ break;
}
- case StatsLog.CPU_SUSPEND_TIME: {
- List<StatsLogEventWrapper> ret = new ArrayList();
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 1);
- e.writeLong(SystemClock.elapsedRealtime());
- ret.add(e);
- return ret.toArray(new StatsLogEventWrapper[ret.size()]);
- }
- case StatsLog.CPU_IDLE_TIME: {
- List<StatsLogEventWrapper> ret = new ArrayList();
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 1);
- e.writeLong(SystemClock.uptimeMillis());
- ret.add(e);
- return ret.toArray(new StatsLogEventWrapper[ret.size()]);
- }
- case StatsLog.DISK_SPACE: {
- List<StatsLogEventWrapper> ret = new ArrayList();
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 3);
- e.writeLong(mStatFsData.getAvailableBytes());
- e.writeLong(mStatFsSystem.getAvailableBytes());
- e.writeLong(mStatFsTemp.getAvailableBytes());
- ret.add(e);
- return ret.toArray(new StatsLogEventWrapper[ret.size()]);
+ case StatsLog.BLUETOOTH_ACTIVITY_INFO: {
+ pullBluetoothActivityInfo(tagId, ret);
+ break;
}
case StatsLog.SYSTEM_UPTIME: {
- List<StatsLogEventWrapper> ret = new ArrayList();
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 1);
- e.writeLong(SystemClock.uptimeMillis());
- ret.add(e);
- return ret.toArray(new StatsLogEventWrapper[ret.size()]);
+ pullSystemUpTime(tagId, ret);
+ break;
+ }
+ case StatsLog.SYSTEM_ELAPSED_REALTIME: {
+ pullSystemElapsedRealtime(tagId, ret);
+ break;
+ }
+ case StatsLog.DISK_SPACE: {
+ pullDiskSpace(tagId, ret);
+ break;
}
default:
Slog.w(TAG, "No such tagId data as " + tagId);
return null;
}
- return null;
+ return ret.toArray(new StatsLogEventWrapper[ret.size()]);
}
@Override // Binder call
@@ -706,7 +781,8 @@
enforceCallingPermission();
if (DEBUG) Slog.d(TAG, "learned that statsdReady");
sayHiToStatsd(); // tell statsd that we're ready too and link to it
- mContext.sendBroadcast(new Intent(StatsManager.ACTION_STATSD_STARTED),
+ mContext.sendBroadcastAsUser(new Intent(StatsManager.ACTION_STATSD_STARTED),
+ UserHandle.SYSTEM,
android.Manifest.permission.DUMP);
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index adb368b..7c170ae 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -56,7 +56,6 @@
import java.util.ArrayList;
import java.util.List;
-
/**
* A note on locking: We rely on the fact that calls onto mBar are oneway or
* if they are local, that they just enqueue messages to not deadlock.
@@ -525,6 +524,26 @@
}
@Override
+ public void showPinningEnterExitToast(boolean entering) throws RemoteException {
+ if (mBar != null) {
+ try {
+ mBar.showPinningEnterExitToast(entering);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
+ @Override
+ public void showPinningEscapeToast() throws RemoteException {
+ if (mBar != null) {
+ try {
+ mBar.showPinningEscapeToast();
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
+ @Override
public void showFingerprintDialog(Bundle bundle, IFingerprintDialogReceiver receiver) {
if (mBar != null) {
try {
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
new file mode 100644
index 0000000..853c7eb
--- /dev/null
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -0,0 +1,395 @@
+/*
+ * 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.server.textclassifier;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.service.textclassifier.ITextClassifierService;
+import android.service.textclassifier.ITextClassificationCallback;
+import android.service.textclassifier.ITextLinksCallback;
+import android.service.textclassifier.ITextSelectionCallback;
+import android.service.textclassifier.TextClassifierService;
+import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextLinks;
+import android.view.textclassifier.TextSelection;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
+import com.android.server.SystemService;
+
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A manager for TextClassifier services.
+ * Apps bind to the TextClassificationManagerService for text classification. This service
+ * reroutes calls to it to a {@link TextClassifierService} that it manages.
+ */
+public final class TextClassificationManagerService extends ITextClassifierService.Stub {
+
+ private static final String LOG_TAG = "TextClassificationManagerService";
+
+ // How long after the last interaction with the service we would unbind
+ private static final long TIMEOUT_IDLE_BIND_MILLIS = TimeUnit.MINUTES.toMillis(1);
+
+ public static final class Lifecycle extends SystemService {
+
+ private final TextClassificationManagerService mManagerService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ mManagerService = new TextClassificationManagerService(context);
+ }
+
+ @Override
+ public void onStart() {
+ try {
+ publishBinderService(Context.TEXT_CLASSIFICATION_SERVICE, mManagerService);
+ } catch (Throwable t) {
+ // Starting this service is not critical to the running of this device and should
+ // therefore not crash the device. If it fails, log the error and continue.
+ Slog.e(LOG_TAG, "Could not start the TextClassificationManagerService.", t);
+ }
+ }
+ }
+
+ private final Context mContext;
+ private final Handler mHandler;
+ private final Intent mServiceIntent;
+ private final ServiceConnection mConnection;
+ private final Runnable mUnbind;
+ private final Object mLock;
+ @GuardedBy("mLock")
+ private final Queue<PendingRequest> mPendingRequests;
+
+ @GuardedBy("mLock")
+ private ITextClassifierService mService;
+ @GuardedBy("mLock")
+ private boolean mBinding;
+
+ private TextClassificationManagerService(Context context) {
+ mContext = Preconditions.checkNotNull(context);
+ mHandler = new Handler();
+ mServiceIntent = new Intent(TextClassifierService.SERVICE_INTERFACE)
+ .setComponent(TextClassifierService.getServiceComponentName(mContext));
+ mConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ synchronized (mLock) {
+ mService = ITextClassifierService.Stub.asInterface(service);
+ setBindingLocked(false);
+ handlePendingRequestsLocked();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ cleanupService();
+ }
+
+ @Override
+ public void onBindingDied(ComponentName name) {
+ cleanupService();
+ }
+
+ @Override
+ public void onNullBinding(ComponentName name) {
+ cleanupService();
+ }
+
+ private void cleanupService() {
+ synchronized (mLock) {
+ mService = null;
+ setBindingLocked(false);
+ handlePendingRequestsLocked();
+ }
+ }
+ };
+ mPendingRequests = new LinkedList<>();
+ mUnbind = this::unbind;
+ mLock = new Object();
+ }
+
+ @Override
+ public void onSuggestSelection(
+ CharSequence text, int selectionStartIndex, int selectionEndIndex,
+ TextSelection.Options options, ITextSelectionCallback callback)
+ throws RemoteException {
+ // TODO(b/72481438): All remote calls need to take userId.
+ validateInput(text, selectionStartIndex, selectionEndIndex, callback);
+
+ if (!bind()) {
+ callback.onFailure();
+ return;
+ }
+
+ synchronized (mLock) {
+ if (isBoundLocked()) {
+ mService.onSuggestSelection(
+ text, selectionStartIndex, selectionEndIndex, options, callback);
+ scheduleUnbindLocked();
+ } else {
+ final Callable<Void> request = () -> {
+ onSuggestSelection(
+ text, selectionStartIndex, selectionEndIndex,
+ options, callback);
+ return null;
+ };
+ final Callable<Void> onServiceFailure = () -> {
+ callback.onFailure();
+ return null;
+ };
+ enqueueRequestLocked(request, onServiceFailure, callback.asBinder());
+ }
+ }
+ }
+
+ @Override
+ public void onClassifyText(
+ CharSequence text, int startIndex, int endIndex,
+ TextClassification.Options options, ITextClassificationCallback callback)
+ throws RemoteException {
+ validateInput(text, startIndex, endIndex, callback);
+
+ if (!bind()) {
+ callback.onFailure();
+ return;
+ }
+
+ synchronized (mLock) {
+ if (isBoundLocked()) {
+ mService.onClassifyText(text, startIndex, endIndex, options, callback);
+ scheduleUnbindLocked();
+ } else {
+ final Callable<Void> request = () -> {
+ onClassifyText(text, startIndex, endIndex, options, callback);
+ return null;
+ };
+ final Callable<Void> onServiceFailure = () -> {
+ callback.onFailure();
+ return null;
+ };
+ enqueueRequestLocked(request, onServiceFailure, callback.asBinder());
+ }
+ }
+ }
+
+ @Override
+ public void onGenerateLinks(
+ CharSequence text, TextLinks.Options options, ITextLinksCallback callback)
+ throws RemoteException {
+ validateInput(text, callback);
+
+ if (!bind()) {
+ callback.onFailure();
+ return;
+ }
+
+ synchronized (mLock) {
+ if (isBoundLocked()) {
+ mService.onGenerateLinks(text, options, callback);
+ scheduleUnbindLocked();
+ } else {
+ final Callable<Void> request = () -> {
+ onGenerateLinks(text, options, callback);
+ return null;
+ };
+ final Callable<Void> onServiceFailure = () -> {
+ callback.onFailure();
+ return null;
+ };
+ enqueueRequestLocked(request, onServiceFailure, callback.asBinder());
+ }
+ }
+ }
+
+ /**
+ * @return true if the service is bound or in the process of being bound.
+ * Returns false otherwise.
+ */
+ private boolean bind() {
+ synchronized (mLock) {
+ if (isBoundLocked() || isBindingLocked()) {
+ return true;
+ }
+
+ // TODO: Handle bind timeout.
+ final boolean willBind;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Slog.d(LOG_TAG, "Binding to " + mServiceIntent.getComponent());
+ willBind = mContext.bindServiceAsUser(
+ mServiceIntent, mConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ Binder.getCallingUserHandle());
+ setBindingLocked(willBind);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return willBind;
+ }
+ }
+
+ @GuardedBy("mLock")
+ private boolean isBoundLocked() {
+ return mService != null;
+ }
+
+ @GuardedBy("mLock")
+ private boolean isBindingLocked() {
+ return mBinding;
+ }
+
+ @GuardedBy("mLock")
+ private void setBindingLocked(boolean binding) {
+ mBinding = binding;
+ }
+
+ private void unbind() {
+ synchronized (mLock) {
+ if (!isBoundLocked()) {
+ return;
+ }
+
+ Slog.d(LOG_TAG, "Unbinding from " + mServiceIntent.getComponent());
+ mContext.unbindService(mConnection);
+
+ synchronized (mLock) {
+ mService = null;
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void scheduleUnbindLocked() {
+ mHandler.removeCallbacks(mUnbind);
+ mHandler.postDelayed(mUnbind, TIMEOUT_IDLE_BIND_MILLIS);
+ }
+
+ @GuardedBy("mLock")
+ private void enqueueRequestLocked(
+ Callable<Void> request, Callable<Void> onServiceFailure, IBinder binder) {
+ mPendingRequests.add(new PendingRequest(request, onServiceFailure, binder));
+ }
+
+ @GuardedBy("mLock")
+ private void handlePendingRequestsLocked() {
+ // TODO(b/72481146): Implement PendingRequest similar to that in RemoteFillService.
+ final PendingRequest[] pendingRequests =
+ mPendingRequests.toArray(new PendingRequest[mPendingRequests.size()]);
+ for (PendingRequest pendingRequest : pendingRequests) {
+ if (isBoundLocked()) {
+ pendingRequest.executeLocked();
+ } else {
+ pendingRequest.notifyServiceFailureLocked();
+ }
+ }
+ }
+
+ private final class PendingRequest implements IBinder.DeathRecipient {
+
+ private final Callable<Void> mRequest;
+ private final Callable<Void> mOnServiceFailure;
+ private final IBinder mBinder;
+
+ /**
+ * Initializes a new pending request.
+ *
+ * @param request action to perform when the service is bound
+ * @param onServiceFailure action to perform when the service dies or disconnects
+ * @param binder binder to the process that made this pending request
+ */
+ PendingRequest(
+ @NonNull Callable<Void> request, @NonNull Callable<Void> onServiceFailure,
+ @NonNull IBinder binder) {
+ mRequest = Preconditions.checkNotNull(request);
+ mOnServiceFailure = Preconditions.checkNotNull(onServiceFailure);
+ mBinder = Preconditions.checkNotNull(binder);
+ try {
+ mBinder.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @GuardedBy("mLock")
+ void executeLocked() {
+ removeLocked();
+ try {
+ mRequest.call();
+ } catch (Exception e) {
+ Slog.d(LOG_TAG, "Error handling pending request: " + e.getMessage());
+ }
+ }
+
+ @GuardedBy("mLock")
+ void notifyServiceFailureLocked() {
+ removeLocked();
+ try {
+ mOnServiceFailure.call();
+ } catch (Exception e) {
+ Slog.d(LOG_TAG, "Error notifying callback of service failure: "
+ + e.getMessage());
+ }
+ }
+
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ // No need to handle this pending request anymore. Remove.
+ removeLocked();
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void removeLocked() {
+ mPendingRequests.remove(this);
+ mBinder.unlinkToDeath(this, 0);
+ }
+ }
+
+ private static void validateInput(
+ CharSequence text, int startIndex, int endIndex, Object callback)
+ throws RemoteException {
+ try {
+ TextClassifier.Utils.validate(text, startIndex, endIndex, true /* allowInMainThread */);
+ Preconditions.checkNotNull(callback);
+ } catch (IllegalArgumentException | NullPointerException e) {
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
+ private static void validateInput(CharSequence text, Object callback) throws RemoteException {
+ try {
+ TextClassifier.Utils.validate(text, true /* allowInMainThread */);
+ Preconditions.checkNotNull(callback);
+ } catch (IllegalArgumentException | NullPointerException e) {
+ throw new RemoteException(e.getMessage());
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/timezone/PackageStatusStorage.java b/services/core/java/com/android/server/timezone/PackageStatusStorage.java
index 251a277..04f0871 100644
--- a/services/core/java/com/android/server/timezone/PackageStatusStorage.java
+++ b/services/core/java/com/android/server/timezone/PackageStatusStorage.java
@@ -81,7 +81,7 @@
private final AtomicFile mPackageStatusFile;
PackageStatusStorage(File storageDir) {
- mPackageStatusFile = new AtomicFile(new File(storageDir, "package-status.xml"));
+ mPackageStatusFile = new AtomicFile(new File(storageDir, "package-status.xml"), "timezone-status");
}
/**
diff --git a/services/core/java/com/android/server/tv/PersistentDataStore.java b/services/core/java/com/android/server/tv/PersistentDataStore.java
index 85a8829..8f2194c 100644
--- a/services/core/java/com/android/server/tv/PersistentDataStore.java
+++ b/services/core/java/com/android/server/tv/PersistentDataStore.java
@@ -91,7 +91,7 @@
throw new IllegalStateException("User dir cannot be created: " + userDir);
}
}
- mAtomicFile = new AtomicFile(new File(userDir, "tv-input-manager-state.xml"));
+ mAtomicFile = new AtomicFile(new File(userDir, "tv-input-manager-state.xml"), "tv-input-state");
}
public boolean isParentalControlsEnabled() {
diff --git a/services/core/java/com/android/server/updates/SmartSelectionInstallReceiver.java b/services/core/java/com/android/server/updates/SmartSelectionInstallReceiver.java
index 1457366..eff9a9a 100644
--- a/services/core/java/com/android/server/updates/SmartSelectionInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/SmartSelectionInstallReceiver.java
@@ -21,8 +21,8 @@
public SmartSelectionInstallReceiver() {
super(
"/data/misc/textclassifier/",
- "textclassifier.smartselection.model",
- "metadata/smartselection",
+ "textclassifier.model",
+ "metadata/classification",
"version");
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index fc7ad09..2bdaa1a 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -38,6 +38,7 @@
import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
+
import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
@@ -1647,10 +1648,7 @@
+ " transit=" + appTransitionToString(transit) + " isEntrance=" + enter
+ " Callers=" + Debug.getCallers(3));
}
- } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS
- && (transit == TRANSIT_ACTIVITY_OPEN
- || transit == TRANSIT_TASK_OPEN
- || transit == TRANSIT_TASK_TO_FRONT)) {
+ } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS && enter) {
a = loadAnimationRes("android", enter
? com.android.internal.R.anim.task_open_enter_cross_profile_apps
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index d340923..2c2389b 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -219,6 +219,14 @@
}
/**
+ * Returns {@code true} if the {@link WindowConfiguration} in the override
+ * {@link Configuration} specifies bounds.
+ */
+ public boolean hasOverrideBounds() {
+ return !getOverrideBounds().isEmpty();
+ }
+
+ /**
* Sets the passed in {@link Rect} to the current bounds.
* @see {@link #getOverrideBounds()}.
*/
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 9fe16ae..b435605 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -17,34 +17,115 @@
package com.android.server.wm;
import android.util.ArrayMap;
-import android.util.Slog;
import android.view.SurfaceControl;
import android.graphics.Rect;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Utility class for use by a WindowContainer implementation to add "DimLayer" support, that is
* black layers of varying opacity at various Z-levels which create the effect of a Dim.
*/
class Dimmer {
private static final String TAG = "WindowManager";
+ private static final int DEFAULT_DIM_ANIM_DURATION = 200;
- private class DimState {
- SurfaceControl mSurfaceControl;
+ private class DimAnimatable implements SurfaceAnimator.Animatable {
+ private final SurfaceControl mDimLayer;
+
+ private DimAnimatable(SurfaceControl dimLayer) {
+ mDimLayer = dimLayer;
+ }
+
+ @Override
+ public SurfaceControl.Transaction getPendingTransaction() {
+ return mHost.getPendingTransaction();
+ }
+
+ @Override
+ public void commitPendingTransaction() {
+ mHost.commitPendingTransaction();
+ }
+
+ @Override
+ public void onAnimationLeashCreated(SurfaceControl.Transaction t, SurfaceControl leash) {
+ }
+
+ @Override
+ public void onAnimationLeashDestroyed(SurfaceControl.Transaction t) {
+ }
+
+ @Override
+ public void destroyAfterPendingTransaction(SurfaceControl surface) {
+ mHost.destroyAfterPendingTransaction(surface);
+ }
+
+ @Override
+ public SurfaceControl.Builder makeAnimationLeash() {
+ return mHost.makeAnimationLeash();
+ }
+
+ @Override
+ public SurfaceControl getAnimationLeashParent() {
+ return mHost.getSurfaceControl();
+ }
+
+ @Override
+ public SurfaceControl getSurfaceControl() {
+ return mDimLayer;
+ }
+
+ @Override
+ public SurfaceControl getParentSurfaceControl() {
+ return mHost.getSurfaceControl();
+ }
+
+ @Override
+ public int getSurfaceWidth() {
+ // This will determine the size of the leash created. This should be the size of the
+ // host and not the dim layer since the dim layer may get bigger during animation. If
+ // that occurs, the leash size cannot change so we need to ensure the leash is big
+ // enough that the dim layer can grow.
+ // This works because the mHost will be a Task which has the display bounds.
+ return mHost.getSurfaceWidth();
+ }
+
+ @Override
+ public int getSurfaceHeight() {
+ // See getSurfaceWidth() above for explanation.
+ return mHost.getSurfaceHeight();
+ }
+ }
+
+ @VisibleForTesting
+ class DimState {
+ /**
+ * The layer where property changes should be invoked on.
+ */
+ SurfaceControl mDimLayer;
boolean mDimming;
+ boolean isVisible;
+ SurfaceAnimator mSurfaceAnimator;
/**
- * Used for Dims not assosciated with a WindowContainer. See {@link Dimmer#dimAbove} for
+ * Used for Dims not associated with a WindowContainer. See {@link Dimmer#dimAbove} for
* details on Dim lifecycle.
*/
boolean mDontReset;
- DimState(SurfaceControl ctl) {
- mSurfaceControl = ctl;
+ DimState(SurfaceControl dimLayer) {
+ mDimLayer = dimLayer;
mDimming = true;
+ mSurfaceAnimator = new SurfaceAnimator(new DimAnimatable(dimLayer), () -> {
+ if (!mDimming) {
+ mDimLayer.destroy();
+ }
+ }, mHost.mService.mAnimator::addAfterPrepareSurfacesRunnable, mHost.mService);
}
- };
+ }
- private ArrayMap<WindowContainer, DimState> mDimLayerUsers = new ArrayMap<>();
+ @VisibleForTesting
+ ArrayMap<WindowContainer, DimState> mDimLayerUsers = new ArrayMap<>();
/**
* The {@link WindowContainer} that our Dim's are bounded to. We may be dimming on behalf of the
@@ -56,19 +137,18 @@
mHost = host;
}
- SurfaceControl makeDimLayer() {
- final SurfaceControl control = mHost.makeChildSurface(null)
+ private SurfaceControl makeDimLayer() {
+ return mHost.makeChildSurface(null)
.setParent(mHost.getSurfaceControl())
.setColorLayer(true)
.setName("Dim Layer for - " + mHost.getName())
.build();
- return control;
}
/**
* Retreive the DimState for a given child of the host.
*/
- DimState getDimState(WindowContainer container) {
+ private DimState getDimState(WindowContainer container) {
DimState state = mDimLayerUsers.get(container);
if (state == null) {
final SurfaceControl ctl = makeDimLayer();
@@ -88,14 +168,12 @@
private void dim(SurfaceControl.Transaction t, WindowContainer container, int relativeLayer,
float alpha) {
final DimState d = getDimState(container);
- t.show(d.mSurfaceControl);
if (container != null) {
- t.setRelativeLayer(d.mSurfaceControl,
- container.getSurfaceControl(), relativeLayer);
+ t.setRelativeLayer(d.mDimLayer, container.getSurfaceControl(), relativeLayer);
} else {
- t.setLayer(d.mSurfaceControl, Integer.MAX_VALUE);
+ t.setLayer(d.mDimLayer, Integer.MAX_VALUE);
}
- t.setAlpha(d.mSurfaceControl, alpha);
+ t.setAlpha(d.mDimLayer, alpha);
d.mDimming = true;
}
@@ -107,16 +185,18 @@
*/
void stopDim(SurfaceControl.Transaction t) {
DimState d = getDimState(null);
- t.hide(d.mSurfaceControl);
+ t.hide(d.mDimLayer);
+ d.isVisible = false;
d.mDontReset = false;
}
+
/**
* Place a Dim above the entire host container. The caller is responsible for calling stopDim to
* remove this effect. If the Dim can be assosciated with a particular child of the host
* consider using the other variant of dimAbove which ties the Dim lifetime to the child
* lifetime more explicitly.
*
- * @param t A transaction in which to apply the Dim.
+ * @param t A transaction in which to apply the Dim.
* @param alpha The alpha at which to Dim.
*/
void dimAbove(SurfaceControl.Transaction t, float alpha) {
@@ -128,9 +208,9 @@
* for each call to {@link WindowContainer#prepareSurfaces} the Dim state will be reset
* and the child should call dimAbove again to request the Dim to continue.
*
- * @param t A transaction in which to apply the Dim.
+ * @param t A transaction in which to apply the Dim.
* @param container The container which to dim above. Should be a child of our host.
- * @param alpha The alpha at which to Dim.
+ * @param alpha The alpha at which to Dim.
*/
void dimAbove(SurfaceControl.Transaction t, WindowContainer container, float alpha) {
dim(t, container, 1, alpha);
@@ -139,9 +219,9 @@
/**
* Like {@link #dimAbove} but places the dim below the given container.
*
- * @param t A transaction in which to apply the Dim.
+ * @param t A transaction in which to apply the Dim.
* @param container The container which to dim below. Should be a child of our host.
- * @param alpha The alpha at which to Dim.
+ * @param alpha The alpha at which to Dim.
*/
void dimBelow(SurfaceControl.Transaction t, WindowContainer container, float alpha) {
@@ -159,7 +239,7 @@
void resetDimStates() {
for (int i = mDimLayerUsers.size() - 1; i >= 0; i--) {
final DimState state = mDimLayerUsers.valueAt(i);
- if (state.mDontReset == false) {
+ if (!state.mDontReset) {
state.mDimming = false;
}
}
@@ -169,7 +249,7 @@
* Call after invoking {@link WindowContainer#prepareSurfaces} on children as
* described in {@link #resetDimStates}.
*
- * @param t A transaction in which to update the dims.
+ * @param t A transaction in which to update the dims.
* @param bounds The bounds at which to dim.
* @return true if any Dims were updated.
*/
@@ -177,19 +257,80 @@
boolean didSomething = false;
for (int i = mDimLayerUsers.size() - 1; i >= 0; i--) {
DimState state = mDimLayerUsers.valueAt(i);
+ WindowContainer container = mDimLayerUsers.keyAt(i);
+
// TODO: We want to animate the addition and removal of Dim's instead of immediately
// acting. When we do this we need to take care to account for the "Replacing Windows"
// case (and seamless dim transfer).
- if (state.mDimming == false) {
+ if (!state.mDimming) {
mDimLayerUsers.removeAt(i);
- state.mSurfaceControl.destroy();
+ startDimExit(container, state.mSurfaceAnimator, t);
} else {
didSomething = true;
// TODO: Once we use geometry from hierarchy this falls away.
- t.setSize(state.mSurfaceControl, bounds.width(), bounds.height());
- t.setPosition(state.mSurfaceControl, bounds.left, bounds.top);
+ t.setSize(state.mDimLayer, bounds.width(), bounds.height());
+ t.setPosition(state.mDimLayer, bounds.left, bounds.top);
+ if (!state.isVisible) {
+ state.isVisible = true;
+ t.show(state.mDimLayer);
+ startDimEnter(container, state.mSurfaceAnimator, t);
+ }
}
}
return didSomething;
}
+
+ private void startDimEnter(WindowContainer container, SurfaceAnimator animator,
+ SurfaceControl.Transaction t) {
+ startAnim(container, animator, t, 0 /* startAlpha */, 1 /* endAlpha */);
+ }
+
+ private void startDimExit(WindowContainer container, SurfaceAnimator animator,
+ SurfaceControl.Transaction t) {
+ startAnim(container, animator, t, 1 /* startAlpha */, 0 /* endAlpha */);
+ }
+
+ private void startAnim(WindowContainer container, SurfaceAnimator animator,
+ SurfaceControl.Transaction t, float startAlpha, float endAlpha) {
+ animator.startAnimation(t, new LocalAnimationAdapter(
+ new AlphaAnimationSpec(startAlpha, endAlpha, getDimDuration(container)),
+ mHost.mService.mSurfaceAnimationRunner), false /* hidden */);
+ }
+
+ private long getDimDuration(WindowContainer container) {
+ // If there's no container, then there isn't an animation occurring while dimming. Set the
+ // duration to 0 so it immediately dims to the set alpha.
+ if (container == null) {
+ return 0;
+ }
+
+ // Otherwise use the same duration as the animation on the WindowContainer
+ AnimationAdapter animationAdapter = container.mSurfaceAnimator.getAnimation();
+ return animationAdapter == null ? DEFAULT_DIM_ANIM_DURATION
+ : animationAdapter.getDurationHint();
+ }
+
+ private static class AlphaAnimationSpec implements LocalAnimationAdapter.AnimationSpec {
+ private final long mDuration;
+ private final float mFromAlpha;
+ private final float mToAlpha;
+
+ AlphaAnimationSpec(float fromAlpha, float toAlpha, long duration) {
+ mFromAlpha = fromAlpha;
+ mToAlpha = toAlpha;
+ mDuration = duration;
+ }
+
+ @Override
+ public long getDuration() {
+ return mDuration;
+ }
+
+ @Override
+ public void apply(SurfaceControl.Transaction t, SurfaceControl sc, long currentPlayTime) {
+ float alpha = ((float) currentPlayTime / getDuration()) * (mToAlpha - mFromAlpha)
+ + mFromAlpha;
+ t.setAlpha(sc, alpha);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6dc384a..7674b5e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1508,6 +1508,10 @@
return mTaskStackContainers.getTopStack();
}
+ ArrayList<Task> getVisibleTasks() {
+ return mTaskStackContainers.getVisibleTasks();
+ }
+
void onStackWindowingModeChanged(TaskStack stack) {
mTaskStackContainers.onStackWindowingModeChanged(stack);
}
@@ -1802,6 +1806,11 @@
getParent().positionChildAt(position, this, includingParents);
}
+ void positionStackAt(int position, TaskStack child) {
+ mTaskStackContainers.positionChildAt(position, child, false /* includingParents */);
+ layoutAndAssignWindowLayersIfNeeded();
+ }
+
int taskIdFromPoint(int x, int y) {
for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
@@ -3255,6 +3264,16 @@
return mSplitScreenPrimaryStack;
}
+ ArrayList<Task> getVisibleTasks() {
+ final ArrayList<Task> visibleTasks = new ArrayList<>();
+ forAllTasks(task -> {
+ if (task.isVisible()) {
+ visibleTasks.add(task);
+ }
+ });
+ return visibleTasks;
+ }
+
/**
* Adds the stack to this container.
* @see DisplayContent#createStack(int, boolean, StackWindowController)
@@ -3580,6 +3599,8 @@
}
private final class AboveAppWindowContainers extends NonAppWindowContainers {
+ private final Dimmer mDimmer = new Dimmer(this);
+ private final Rect mTmpDimBoundsRect = new Rect();
AboveAppWindowContainers(String name, WindowManagerService service) {
super(name, service);
}
@@ -3611,6 +3632,22 @@
imeContainer.assignRelativeLayer(t, getSurfaceControl(), Integer.MAX_VALUE);
}
}
+
+ @Override
+ Dimmer getDimmer() {
+ return mDimmer;
+ }
+
+ @Override
+ void prepareSurfaces() {
+ mDimmer.resetDimStates();
+ super.prepareSurfaces();
+ getBounds(mTmpDimBoundsRect);
+
+ if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
+ scheduleAnimation();
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java
index 7f79686..97b64dc 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplaySettings.java
@@ -64,7 +64,7 @@
public DisplaySettings() {
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
- mFile = new AtomicFile(new File(systemDir, "display_settings.xml"));
+ mFile = new AtomicFile(new File(systemDir, "display_settings.xml"), "wm-displays");
}
public void getOverscanLocked(String name, String uniqueId, Rect outRect) {
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
new file mode 100644
index 0000000..ad4957e
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -0,0 +1,85 @@
+/*
+ * 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.server.wm;
+
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.content.res.Configuration;
+import android.util.Slog;
+
+/**
+ * Controller for the display container. This is created by activity manager to link activity
+ * displays to the display content they use in window manager.
+ */
+public class DisplayWindowController
+ extends WindowContainerController<DisplayContent, WindowContainerListener> {
+
+ private final int mDisplayId;
+
+ public DisplayWindowController(int displayId, WindowContainerListener listener) {
+ super(listener, WindowManagerService.getInstance());
+ mDisplayId = displayId;
+
+ synchronized (mWindowMap) {
+ // TODO: Convert to setContainer() from DisplayContent once everything is hooked up.
+ // Currently we are not setup to register for config changes.
+ mContainer = mRoot.getDisplayContentOrCreate(displayId);
+ if (mContainer == null) {
+ throw new IllegalArgumentException("Trying to add displayId=" + displayId);
+ }
+ }
+ }
+
+ @Override
+ public void removeContainer() {
+ // TODO: Pipe through from ActivityDisplay to remove the display
+ throw new UnsupportedOperationException("To be implemented");
+ }
+
+ @Override
+ public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ // TODO: Pipe through from ActivityDisplay to update the configuration for the display
+ throw new UnsupportedOperationException("To be implemented");
+ }
+
+ /**
+ * Positions the task stack at the given position in the task stack container.
+ */
+ public void positionChildAt(StackWindowController child, int position) {
+ synchronized (mWindowMap) {
+ if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskStackAt: positioning stack=" + child
+ + " at " + position);
+ if (mContainer == null) {
+ if (DEBUG_STACK) Slog.i(TAG_WM,
+ "positionTaskStackAt: could not find display=" + mContainer);
+ return;
+ }
+ if (child.mContainer == null) {
+ if (DEBUG_STACK) Slog.i(TAG_WM,
+ "positionTaskStackAt: could not find stack=" + this);
+ return;
+ }
+ mContainer.positionStackAt(position, child.mContainer);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "{DisplayWindowController displayId=" + mDisplayId + "}";
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 7ae1f24..80798bf 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -568,6 +568,14 @@
: null;
final TaskStack dockedStack = mDisplayContent.getSplitScreenPrimaryStack();
boolean visibleAndValid = visible && stack != null && dockedStack != null;
+
+ // Ensure an old dim that was shown for the docked stack divider is removed so we don't end
+ // up with dim layers that can no longer be removed.
+ if (mDimmedStack != null && mDimmedStack != stack) {
+ mDimmedStack.stopDimming();
+ mDimmedStack = null;
+ }
+
if (visibleAndValid) {
mDimmedStack = stack;
stack.dim(alpha);
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 88b7a11..281e0a8 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -19,6 +19,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
+import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
@@ -86,6 +87,7 @@
private boolean mAddInputConsumerHandle;
private boolean mAddPipInputConsumerHandle;
private boolean mAddWallpaperInputConsumerHandle;
+ private boolean mAddRecentsAnimationInputConsumerHandle;
private boolean mDisableWallpaperTouchEvents;
private final Rect mTmpRect = new Rect();
private final UpdateInputForAllWindowsConsumer mUpdateInputForAllWindowsConsumer =
@@ -612,7 +614,7 @@
InputConsumerImpl navInputConsumer;
InputConsumerImpl pipInputConsumer;
InputConsumerImpl wallpaperInputConsumer;
- Rect pipTouchableBounds;
+ InputConsumerImpl recentsAnimationInputConsumer;
boolean inDrag;
WallpaperController wallpaperController;
@@ -622,11 +624,13 @@
navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY);
pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY);
wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY);
+ recentsAnimationInputConsumer = getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION,
+ DEFAULT_DISPLAY);
mAddInputConsumerHandle = navInputConsumer != null;
mAddPipInputConsumerHandle = pipInputConsumer != null;
mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
+ mAddRecentsAnimationInputConsumerHandle = recentsAnimationInputConsumer != null;
mTmpRect.setEmpty();
- pipTouchableBounds = mAddPipInputConsumerHandle ? mTmpRect : null;
mDisableWallpaperTouchEvents = false;
this.inDrag = inDrag;
wallpaperController = mService.mRoot.mWallpaperController;
@@ -659,12 +663,28 @@
final boolean hasFocus = w == mInputFocus;
final boolean isVisible = w.isVisibleLw();
+ if (mAddRecentsAnimationInputConsumerHandle) {
+ final RecentsAnimationController recentsAnimationController =
+ mService.getRecentsAnimationController();
+ if (recentsAnimationController != null
+ && recentsAnimationController.hasInputConsumerForApp(w.mAppToken)) {
+ if (recentsAnimationController.updateInputConsumerForApp(
+ recentsAnimationInputConsumer, hasFocus)) {
+ addInputWindowHandle(recentsAnimationInputConsumer.mWindowHandle);
+ mAddRecentsAnimationInputConsumerHandle = false;
+ }
+ // Skip adding the window below regardless of whether there is an input consumer
+ // to handle it
+ return;
+ }
+ }
+
if (w.inPinnedWindowingMode()) {
if (mAddPipInputConsumerHandle
&& (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) {
// Update the bounds of the Pip input consumer to match the window bounds.
- w.getBounds(pipTouchableBounds);
- pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
+ w.getBounds(mTmpRect);
+ pipInputConsumer.mWindowHandle.touchableRegion.set(mTmpRect);
addInputWindowHandle(pipInputConsumer.mWindowHandle);
mAddPipInputConsumerHandle = false;
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
new file mode 100644
index 0000000..fe5b65c
--- /dev/null
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.TaskSnapshot;
+import android.app.WindowConfiguration;
+import android.graphics.GraphicBuffer;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.Slog;
+import android.view.IRecentsAnimationController;
+import android.view.IRecentsAnimationRunner;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Controls a single instance of the remote driven recents animation. In particular, this allows
+ * the calling SystemUI to animate the visible task windows as a part of the transition. The remote
+ * runner is provided an animation controller which allows it to take screenshots and to notify
+ * window manager when the animation is completed. In addition, window manager may also notify the
+ * app if it requires the animation to be canceled at any time (ie. due to timeout, etc.)
+ */
+public class RecentsAnimationController {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "RecentsAnimationController" : TAG_WM;
+ private static final boolean DEBUG = false;
+
+ private final WindowManagerService mService;
+ private final IRecentsAnimationRunner mRunner;
+ private final RecentsAnimationCallbacks mCallbacks;
+ private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>();
+
+ // The recents component app token that is shown behind the visibile tasks
+ private AppWindowToken mHomeAppToken;
+
+ // We start the RecentsAnimationController in a pending-start state since we need to wait for
+ // the wallpaper/activity to draw before we can give control to the handler to start animating
+ // the visible task surfaces
+ private boolean mPendingStart = true;
+
+ // Set when the animation has been canceled
+ private boolean mCanceled = false;
+
+ // Whether or not the input consumer is enabled. The input consumer must be both registered and
+ // enabled for it to start intercepting touch events.
+ private boolean mInputConsumerEnabled;
+
+ private Rect mTmpRect = new Rect();
+
+ public interface RecentsAnimationCallbacks {
+ void onAnimationFinished(boolean moveHomeToTop);
+ }
+
+ private final IRecentsAnimationController mController =
+ new IRecentsAnimationController.Stub() {
+
+ @Override
+ public TaskSnapshot screenshotTask(int taskId) {
+ if (DEBUG) Log.d(TAG, "screenshotTask(" + taskId + "): mCanceled=" + mCanceled);
+ long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mService.getWindowManagerLock()) {
+ if (mCanceled) {
+ return null;
+ }
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
+ final Task task = adapter.mTask;
+ if (task.mTaskId == taskId) {
+ // TODO: Save this screenshot as the task snapshot?
+ final Rect taskFrame = new Rect();
+ task.getBounds(taskFrame);
+ final GraphicBuffer buffer = SurfaceControl.captureLayers(
+ task.getSurfaceControl().getHandle(), taskFrame, 1f);
+ final AppWindowToken topChild = task.getTopChild();
+ final WindowState mainWindow = topChild.findMainWindow();
+ return new TaskSnapshot(buffer, topChild.getConfiguration().orientation,
+ mainWindow.mStableInsets,
+ ActivityManager.isLowRamDeviceStatic() /* reduced */,
+ 1.0f /* scale */);
+ }
+ }
+ return null;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void finish(boolean moveHomeToTop) {
+ if (DEBUG) Log.d(TAG, "finish(" + moveHomeToTop + "): mCanceled=" + mCanceled);
+ long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mService.getWindowManagerLock()) {
+ if (mCanceled) {
+ return;
+ }
+ }
+
+ // Note, the callback will handle its own synchronization, do not lock on WM lock
+ // prior to calling the callback
+ mCallbacks.onAnimationFinished(moveHomeToTop);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void setInputConsumerEnabled(boolean enabled) {
+ if (DEBUG) Log.d(TAG, "setInputConsumerEnabled(" + enabled + "): mCanceled="
+ + mCanceled);
+ long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mService.getWindowManagerLock()) {
+ if (mCanceled) {
+ return;
+ }
+
+ mInputConsumerEnabled = enabled;
+ mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ mService.scheduleAnimationLocked();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+
+ /**
+ * Initializes a new RecentsAnimationController.
+ *
+ * @param remoteAnimationRunner The remote runner which should be notified when the animation is
+ * ready to start or has been canceled
+ * @param callbacks Callbacks to be made when the animation finishes
+ * @param restoreHomeBehindStackId The stack id to restore the home stack behind once the
+ * animation is complete. Will be passed to the callback.
+ */
+ RecentsAnimationController(WindowManagerService service,
+ IRecentsAnimationRunner remoteAnimationRunner, RecentsAnimationCallbacks callbacks,
+ int displayId) {
+ mService = service;
+ mRunner = remoteAnimationRunner;
+ mCallbacks = callbacks;
+
+ final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
+ final ArrayList<Task> visibleTasks = dc.getVisibleTasks();
+ if (visibleTasks.isEmpty()) {
+ cancelAnimation();
+ return;
+ }
+
+ // Make leashes for each of the visible tasks and add it to the recents animation to be
+ // started
+ final int taskCount = visibleTasks.size();
+ for (int i = 0; i < taskCount; i++) {
+ final Task task = visibleTasks.get(i);
+ final WindowConfiguration config = task.getWindowConfiguration();
+ if (config.tasksAreFloating()
+ || config.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || config.getActivityType() == ACTIVITY_TYPE_HOME) {
+ continue;
+ }
+ addAnimation(task);
+ }
+
+ // Adjust the wallpaper visibility for the showing home activity
+ final AppWindowToken recentsComponentAppToken =
+ dc.getHomeStack().getTopChild().getTopFullscreenAppToken();
+ if (recentsComponentAppToken != null) {
+ if (DEBUG) Log.d(TAG, "setHomeApp(" + recentsComponentAppToken.getName() + ")");
+ mHomeAppToken = recentsComponentAppToken;
+ final WallpaperController wc = dc.mWallpaperController;
+ if (recentsComponentAppToken.windowsCanBeWallpaperTarget()) {
+ dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ dc.setLayoutNeeded();
+ }
+ }
+
+ mService.mWindowPlacerLocked.performSurfacePlacement();
+ }
+
+ private void addAnimation(Task task) {
+ if (DEBUG) Log.d(TAG, "addAnimation(" + task.getName() + ")");
+ final SurfaceAnimator anim = new SurfaceAnimator(task, null /* animationFinishedCallback */,
+ mService.mAnimator::addAfterPrepareSurfacesRunnable, mService);
+ final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task);
+ anim.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */);
+ task.commitPendingTransaction();
+ mPendingAnimations.add(taskAdapter);
+ }
+
+ void startAnimation() {
+ if (DEBUG) Log.d(TAG, "startAnimation(): mPendingStart=" + mPendingStart);
+ if (!mPendingStart) {
+ return;
+ }
+ try {
+ final RemoteAnimationTarget[] appAnimations =
+ new RemoteAnimationTarget[mPendingAnimations.size()];
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ appAnimations[i] = mPendingAnimations.get(i).createRemoteAnimationApp();
+ }
+ mPendingStart = false;
+ mRunner.onAnimationStart(mController, appAnimations);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to start recents animation", e);
+ }
+ }
+
+ void cancelAnimation() {
+ if (DEBUG) Log.d(TAG, "cancelAnimation()");
+ if (mCanceled) {
+ // We've already canceled the animation
+ return;
+ }
+ mCanceled = true;
+ try {
+ mRunner.onAnimationCanceled();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to cancel recents animation", e);
+ }
+
+ // Clean up and return to the previous app
+ mCallbacks.onAnimationFinished(false /* moveHomeToTop */);
+ }
+
+ void cleanupAnimation() {
+ if (DEBUG) Log.d(TAG, "cleanupAnimation(): mPendingAnimations="
+ + mPendingAnimations.size());
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
+ adapter.mCapturedFinishCallback.onAnimationFinished(adapter);
+ }
+ mPendingAnimations.clear();
+
+ mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ mService.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
+ }
+
+ void checkAnimationReady(WallpaperController wallpaperController) {
+ if (mPendingStart) {
+ final boolean wallpaperReady = !isHomeAppOverWallpaper()
+ || (wallpaperController.getWallpaperTarget() != null
+ && wallpaperController.wallpaperTransitionReady());
+ if (wallpaperReady) {
+ mService.getRecentsAnimationController().startAnimation();
+ }
+ }
+ }
+
+ boolean isWallpaperVisible(WindowState w) {
+ return w != null && w.mAppToken != null && mHomeAppToken == w.mAppToken
+ && isHomeAppOverWallpaper();
+ }
+
+ boolean hasInputConsumerForApp(AppWindowToken appToken) {
+ return mInputConsumerEnabled && isAnimatingApp(appToken);
+ }
+
+ boolean updateInputConsumerForApp(InputConsumerImpl recentsAnimationInputConsumer,
+ boolean hasFocus) {
+ // Update the input consumer touchable region to match the home app main window
+ final WindowState homeAppMainWindow = mHomeAppToken != null
+ ? mHomeAppToken.findMainWindow()
+ : null;
+ if (homeAppMainWindow != null) {
+ homeAppMainWindow.getBounds(mTmpRect);
+ recentsAnimationInputConsumer.mWindowHandle.hasFocus = hasFocus;
+ recentsAnimationInputConsumer.mWindowHandle.touchableRegion.set(mTmpRect);
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isHomeAppOverWallpaper() {
+ if (mHomeAppToken == null) {
+ return false;
+ }
+ return mHomeAppToken.windowsCanBeWallpaperTarget();
+ }
+
+ private boolean isAnimatingApp(AppWindowToken appToken) {
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ final Task task = mPendingAnimations.get(i).mTask;
+ for (int j = task.getChildCount() - 1; j >= 0; j--) {
+ final AppWindowToken app = task.getChildAt(j);
+ if (app == appToken) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private class TaskAnimationAdapter implements AnimationAdapter {
+
+ private Task mTask;
+ private SurfaceControl mCapturedLeash;
+ private OnAnimationFinishedCallback mCapturedFinishCallback;
+
+ TaskAnimationAdapter(Task task) {
+ mTask = task;
+ }
+
+ RemoteAnimationTarget createRemoteAnimationApp() {
+ // TODO: Do we need position and stack bounds?
+ return new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
+ !mTask.fillsParent(),
+ mTask.getTopVisibleAppMainWindow().mWinAnimator.mLastClipRect,
+ mTask.getPrefixOrderIndex(), new Point(), new Rect(),
+ mTask.getWindowConfiguration());
+ }
+
+ @Override
+ public boolean getDetachWallpaper() {
+ return false;
+ }
+
+ @Override
+ public int getBackgroundColor() {
+ return 0;
+ }
+
+ @Override
+ public void startAnimation(SurfaceControl animationLeash, Transaction t,
+ OnAnimationFinishedCallback finishCallback) {
+ mCapturedLeash = animationLeash;
+ mCapturedFinishCallback = finishCallback;
+ }
+
+ @Override
+ public void onAnimationCancelled(SurfaceControl animationLeash) {
+ cancelAnimation();
+ }
+
+ @Override
+ public long getDurationHint() {
+ return 0;
+ }
+
+ @Override
+ public long getStatusBarTransitionsStartTime() {
+ return SystemClock.uptimeMillis();
+ }
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ pw.print(prefix); pw.println(RecentsAnimationController.class.getSimpleName() + ":");
+ pw.print(innerPrefix); pw.println("mPendingStart=" + mPendingStart);
+ pw.print(innerPrefix); pw.println("mHomeAppToken=" + mHomeAppToken);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 8515dcb..8269a3b 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -88,6 +88,10 @@
* Called when the transition is ready to be started, and all leashes have been set up.
*/
void goodToGo() {
+ if (mPendingAnimations.isEmpty()) {
+ onAnimationFinished();
+ return;
+ }
mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MS);
try {
mRemoteAnimationAdapter.getRunner().onAnimationStart(createAnimations(),
@@ -160,7 +164,8 @@
return new RemoteAnimationTarget(task.mTaskId, getMode(),
mCapturedLeash, !mAppWindowToken.fillsParent(),
mainWindow.mWinAnimator.mLastClipRect,
- mAppWindowToken.getPrefixOrderIndex(), mPosition, mStackBounds);
+ mAppWindowToken.getPrefixOrderIndex(), mPosition, mStackBounds,
+ task.getWindowConfiguration());
}
private int getMode() {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 2cc96c9..68c8995 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -623,6 +623,13 @@
defaultDisplay.pendingLayoutChanges);
}
+ // Defer starting the recents animation until the wallpaper has drawn
+ final RecentsAnimationController recentsAnimationController =
+ mService.getRecentsAnimationController();
+ if (recentsAnimationController != null) {
+ recentsAnimationController.checkAnimationReady(mWallpaperController);
+ }
+
if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
&& !mService.mAppTransition.isReady()) {
// At this point, there was a window with a wallpaper that was force hiding other
@@ -896,10 +903,26 @@
boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {
final WindowManager.LayoutParams attrs = w.mAttrs;
final int attrFlags = attrs.flags;
+ final boolean onScreen = w.isOnScreen();
final boolean canBeSeen = w.isDisplayedLw();
final int privateflags = attrs.privateFlags;
boolean displayHasContent = false;
+ if (DEBUG_KEEP_SCREEN_ON) {
+ Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked w: " + w
+ + ", w.mHasSurface: " + w.mHasSurface
+ + ", w.isOnScreen(): " + onScreen
+ + ", w.isDisplayedLw(): " + w.isDisplayedLw()
+ + ", w.mAttrs.userActivityTimeout: " + w.mAttrs.userActivityTimeout);
+ }
+ if (w.mHasSurface && onScreen) {
+ if (!syswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
+ mUserActivityTimeout = w.mAttrs.userActivityTimeout;
+ if (DEBUG_KEEP_SCREEN_ON) {
+ Slog.d(TAG, "mUserActivityTimeout set to " + mUserActivityTimeout);
+ }
+ }
+ }
if (w.mHasSurface && canBeSeen) {
if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
mHoldScreen = w.mSession;
@@ -912,9 +935,6 @@
if (!syswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
mScreenBrightness = w.mAttrs.screenBrightness;
}
- if (!syswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
- mUserActivityTimeout = w.mAttrs.userActivityTimeout;
- }
final int type = attrs.type;
// This function assumes that the contents of the default display are processed first
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 10f1c3a..0512a08 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -62,7 +62,7 @@
* @param addAfterPrepareSurfaces Consumer that takes a runnable and executes it after preparing
* surfaces in WM. Can be implemented differently during testing.
*/
- SurfaceAnimator(Animatable animatable, Runnable animationFinishedCallback,
+ SurfaceAnimator(Animatable animatable, @Nullable Runnable animationFinishedCallback,
Consumer<Runnable> addAfterPrepareSurfaces, WindowManagerService service) {
mAnimatable = animatable;
mService = service;
@@ -71,7 +71,8 @@
addAfterPrepareSurfaces);
}
- private OnAnimationFinishedCallback getFinishedCallback(Runnable animationFinishedCallback,
+ private OnAnimationFinishedCallback getFinishedCallback(
+ @Nullable Runnable animationFinishedCallback,
Consumer<Runnable> addAfterPrepareSurfaces) {
return anim -> {
synchronized (mService.mWindowMap) {
@@ -97,7 +98,9 @@
SurfaceControl.openTransaction();
try {
reset(t, true /* destroyLeash */);
- animationFinishedCallback.run();
+ if (animationFinishedCallback != null) {
+ animationFinishedCallback.run();
+ }
} finally {
SurfaceControl.mergeToGlobalTransaction(t);
SurfaceControl.closeTransaction();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0628436..7d970d9 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -462,8 +462,8 @@
} else {
mStack.getBounds(mTmpRect);
mTmpRect.intersect(getBounds());
+ out.set(mTmpRect);
}
- out.set(mTmpRect);
} else {
out.set(getBounds());
}
@@ -640,6 +640,7 @@
mPreserveNonFloatingState = false;
}
+ @Override
Dimmer getDimmer() {
return mDimmer;
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index bc0f9ad..a0d1480 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -21,6 +21,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
@@ -53,6 +54,7 @@
import android.graphics.Rect;
import android.graphics.Region;
import android.os.RemoteException;
+import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
@@ -736,13 +738,22 @@
}
private void updateSurfaceBounds() {
- updateSurfaceBounds(getPendingTransaction());
+ updateSurfaceSize(getPendingTransaction());
+ updateSurfacePosition();
scheduleAnimation();
}
- void updateSurfaceBounds(SurfaceControl.Transaction transaction) {
- updateSurfaceSize(transaction);
- updateSurfacePosition(transaction);
+ /**
+ * Calculate an amount by which to expand the stack bounds in each direction.
+ * Used to make room for shadows in the pinned windowing mode.
+ */
+ int getStackOutset() {
+ if (inPinnedWindowingMode()) {
+ final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
+ return mService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP,
+ displayMetrics);
+ }
+ return 0;
}
private void updateSurfaceSize(SurfaceControl.Transaction transaction) {
@@ -751,8 +762,13 @@
}
final Rect stackBounds = getBounds();
- final int width = stackBounds.width();
- final int height = stackBounds.height();
+ int width = stackBounds.width();
+ int height = stackBounds.height();
+
+ final int outset = getStackOutset();
+ width += 2*outset;
+ height += 2*outset;
+
if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
return;
}
@@ -1722,6 +1738,7 @@
|| activityType == ACTIVITY_TYPE_ASSISTANT;
}
+ @Override
Dimmer getDimmer() {
return mDimmer;
}
@@ -1752,4 +1769,12 @@
mDimmer.stopDim(getPendingTransaction());
scheduleAnimation();
}
+
+ @Override
+ void getRelativePosition(Point outPos) {
+ super.getRelativePosition(outPos);
+ final int outset = getStackOutset();
+ outPos.x -= outset;
+ outPos.y -= outset;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 1218d3b..f2ad6fb 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -149,8 +149,17 @@
mFindResults.setUseTopWallpaperAsTarget(true);
}
+ final RecentsAnimationController recentsAnimationController =
+ mService.getRecentsAnimationController();
final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
- if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
+ final boolean isRecentsTransitionTarget = (recentsAnimationController != null
+ && recentsAnimationController.isWallpaperVisible(w));
+ if (isRecentsTransitionTarget) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Found recents animation wallpaper target: " + w);
+ mFindResults.setWallpaperTarget(w);
+ return true;
+ } else if (hasWallpaper && w.isOnScreen()
+ && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: " + w);
mFindResults.setWallpaperTarget(w);
if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
@@ -199,15 +208,22 @@
}
}
- private boolean isWallpaperVisible(WindowState wallpaperTarget) {
+ private final boolean isWallpaperVisible(WindowState wallpaperTarget) {
+ final RecentsAnimationController recentsAnimationController =
+ mService.getRecentsAnimationController();
+ boolean isAnimatingWithRecentsComponent = recentsAnimationController != null
+ && recentsAnimationController.isWallpaperVisible(wallpaperTarget);
if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
+ (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
+ " animating=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
? wallpaperTarget.mAppToken.isSelfAnimating() : null)
- + " prev=" + mPrevWallpaperTarget);
+ + " prev=" + mPrevWallpaperTarget
+ + " recentsAnimationWallpaperVisible=" + isAnimatingWithRecentsComponent);
return (wallpaperTarget != null
- && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
- && wallpaperTarget.mAppToken.isSelfAnimating())))
+ && (!wallpaperTarget.mObscured
+ || isAnimatingWithRecentsComponent
+ || (wallpaperTarget.mAppToken != null
+ && wallpaperTarget.mAppToken.isSelfAnimating())))
|| mPrevWallpaperTarget != null;
}
@@ -587,6 +603,11 @@
mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
"*** WALLPAPER DRAW TIMEOUT");
+
+ // If there was a recents animation in progress, cancel that animation
+ if (mService.getRecentsAnimationController() != null) {
+ mService.getRecentsAnimationController().cancelAnimation();
+ }
return true;
}
return false;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 8a500b5..6bd7f22 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -131,7 +131,7 @@
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
super.onConfigurationChanged(newParentConfig);
- updateSurfacePosition(getPendingTransaction());
+ updateSurfacePosition();
scheduleAnimation();
}
@@ -343,9 +343,9 @@
}
/** Returns true if this window container has the input child. */
- boolean hasChild(WindowContainer child) {
+ boolean hasChild(E child) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowContainer current = mChildren.get(i);
+ final E current = mChildren.get(i);
if (current == child || current.hasChild(child)) {
return true;
}
@@ -467,10 +467,22 @@
void onResize() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer wc = mChildren.get(i);
- wc.onResize();
+ wc.onParentResize();
}
}
+ void onParentResize() {
+ // In the case this container has specified its own bounds, a parent resize will not
+ // affect its bounds. Any relevant changes will be propagated through changes to the
+ // Configuration override.
+ if (hasOverrideBounds()) {
+ return;
+ }
+
+ // Default implementation is to treat as resize on self.
+ onResize();
+ }
+
void onMovedByResize() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer wc = mChildren.get(i);
@@ -1192,7 +1204,7 @@
}
}
- void updateSurfacePosition(SurfaceControl.Transaction transaction) {
+ void updateSurfacePosition() {
if (mSurfaceControl == null) {
return;
}
@@ -1202,12 +1214,8 @@
return;
}
- transaction.setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
+ getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
-
- for (int i = mChildren.size() - 1; i >= 0; i--) {
- mChildren.get(i).updateSurfacePosition(transaction);
- }
}
void getRelativePosition(Point outPos) {
@@ -1219,4 +1227,11 @@
outPos.offset(-parentBounds.left, -parentBounds.top);
}
}
+
+ Dimmer getDimmer() {
+ if (mParent == null) {
+ return null;
+ }
+ return mParent.getDimmer();
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index de1e7ec..066e4e6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -24,6 +24,8 @@
import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.StatusBarManager.DISABLE_MASK;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.EXTRA_USER_HANDLE;
@@ -123,6 +125,7 @@
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.IAssistDataReceiver;
+import android.app.WindowConfiguration;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -196,6 +199,7 @@
import android.view.IInputFilter;
import android.view.IOnKeyguardExitResult;
import android.view.IPinnedStackListener;
+import android.view.IRecentsAnimationRunner;
import android.view.IRotationWatcher;
import android.view.IWallpaperVisibilityListener;
import android.view.IWindow;
@@ -528,6 +532,7 @@
IInputMethodManager mInputMethodManager;
AccessibilityController mAccessibilityController;
+ private RecentsAnimationController mRecentsAnimationController;
Watermark mWatermark;
StrictModeFlash mStrictModeFlash;
@@ -902,9 +907,16 @@
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
WindowManagerPolicy policy) {
+ return main(context, im, haveInputMethods, showBootMsgs, onlyCore, policy,
+ new SurfaceAnimationRunner());
+ }
+
+ public static WindowManagerService main(final Context context, final InputManagerService im,
+ final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
+ WindowManagerPolicy policy, SurfaceAnimationRunner surfaceAnimationRunner) {
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
- onlyCore, policy), 0);
+ onlyCore, policy, surfaceAnimationRunner), 0);
return sInstance;
}
@@ -927,7 +939,7 @@
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
- WindowManagerPolicy policy) {
+ WindowManagerPolicy policy, SurfaceAnimationRunner surfaceAnimationRunner) {
installLock(this, INDEX_WINDOW);
mContext = context;
mHaveInputMethods = haveInputMethods;
@@ -1054,7 +1066,7 @@
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
mHoldingScreenWakeLock.setReferenceCounted(false);
- mSurfaceAnimationRunner = new SurfaceAnimationRunner();
+ mSurfaceAnimationRunner = surfaceAnimationRunner;
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
@@ -2670,6 +2682,39 @@
}
}
+ public void initializeRecentsAnimation(
+ IRecentsAnimationRunner recentsAnimationRunner,
+ RecentsAnimationController.RecentsAnimationCallbacks callbacks, int displayId) {
+ synchronized (mWindowMap) {
+ cancelRecentsAnimation();
+ mRecentsAnimationController = new RecentsAnimationController(this,
+ recentsAnimationRunner, callbacks, displayId);
+ }
+ }
+
+ public RecentsAnimationController getRecentsAnimationController() {
+ return mRecentsAnimationController;
+ }
+
+ public void cancelRecentsAnimation() {
+ synchronized (mWindowMap) {
+ if (mRecentsAnimationController != null) {
+ // This call will call through to cleanupAnimation() below after the animation is
+ // canceled
+ mRecentsAnimationController.cancelAnimation();
+ }
+ }
+ }
+
+ public void cleanupRecentsAnimation() {
+ synchronized (mWindowMap) {
+ if (mRecentsAnimationController != null) {
+ mRecentsAnimationController.cleanupAnimation();
+ mRecentsAnimationController = null;
+ }
+ }
+ }
+
public void setAppFullscreen(IBinder token, boolean toOpaque) {
synchronized (mWindowMap) {
final AppWindowToken atoken = mRoot.getAppWindowToken(token);
@@ -6327,6 +6372,10 @@
pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
pw.println(" mLayoutToAnim:");
mAppTransition.dump(pw, " ");
+ if (mRecentsAnimationController != null) {
+ pw.print(" mRecentsAnimationController="); pw.println(mRecentsAnimationController);
+ mRecentsAnimationController.dump(pw, " ");
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 477dd2b..36e3612 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2138,18 +2138,6 @@
mInputWindowHandle.inputChannel = null;
}
- private Dimmer getDimmer() {
- Task task = getTask();
- if (task != null) {
- return task.getDimmer();
- }
- TaskStack taskStack = getStack();
- if (taskStack != null) {
- return taskStack.getDimmer();
- }
- return null;
- }
-
/** Returns true if the replacement window was removed. */
boolean removeReplacedWindowIfNeeded(WindowState replacement) {
if (mWillReplaceWindow && mReplacementWindow == replacement && replacement.hasDrawnLw()) {
@@ -4516,11 +4504,11 @@
private void applyDims(Dimmer dimmer) {
if (!mAnimatingExit && mAppDied) {
mIsDimming = true;
- getDimmer().dimAbove(getPendingTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
+ dimmer.dimAbove(getPendingTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
} else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0
- && !mAnimatingExit && isVisible()) {
+ && !mAnimatingExit && isVisible() && !mWinAnimator.mLastHidden) {
mIsDimming = true;
- getDimmer().dimBelow(getPendingTransaction(), this, mAttrs.dimAmount);
+ dimmer.dimBelow(getPendingTransaction(), this, mAttrs.dimAmount);
}
}
@@ -4531,8 +4519,7 @@
if (dimmer != null) {
applyDims(dimmer);
}
-
- updateSurfacePosition(mPendingTransaction);
+ updateSurfacePosition();
mWinAnimator.prepareSurfaceLocked(true);
super.prepareSurfaces();
@@ -4554,7 +4541,11 @@
}
@Override
- void updateSurfacePosition(Transaction t) {
+ void updateSurfacePosition() {
+ updateSurfacePosition(getPendingTransaction());
+ }
+
+ private void updateSurfacePosition(Transaction t) {
if (mSurfaceControl == null) {
return;
}
@@ -4585,6 +4576,17 @@
outPoint.offset(-parentBounds.left, -parentBounds.top);
}
+ TaskStack stack = getStack();
+
+ // If we have stack outsets, that means the top-left
+ // will be outset, and we need to inset ourselves
+ // to account for it. If we actually have shadows we will
+ // then un-inset ourselves by the surfaceInsets.
+ if (stack != null) {
+ final int outset = stack.getStackOutset();
+ outPoint.offset(outset, outset);
+ }
+
// Expand for surface insets. See WindowState.expandForSurfaceInsets.
outPoint.offset(-mAttrs.surfaceInsets.left, -mAttrs.surfaceInsets.top);
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 1cfa956..5c9cfbb 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -99,7 +99,6 @@
// Unchanging local convenience fields.
final WindowManagerService mService;
final WindowState mWin;
- private final WindowStateAnimator mParentWinAnimator;
final WindowAnimator mAnimator;
final Session mSession;
final WindowManagerPolicy mPolicy;
@@ -135,8 +134,6 @@
float mAlpha = 0;
float mLastAlpha = 0;
- boolean mHasClipRect;
- Rect mClipRect = new Rect();
Rect mTmpClipRect = new Rect();
Rect mTmpFinalClipRect = new Rect();
Rect mLastClipRect = new Rect();
@@ -150,7 +147,6 @@
* system decorations.
*/
private final Rect mSystemDecorRect = new Rect();
- private final Rect mLastSystemDecorRect = new Rect();
float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
private float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
@@ -224,7 +220,6 @@
mContext = service.mContext;
mWin = win;
- mParentWinAnimator = !win.isChildWindow() ? null : win.getParentWindow().mWinAnimator;
mSession = win.mSession;
mAttrType = win.mAttrs.type;
mIsWallpaper = win.mIsWallpaper;
@@ -455,9 +450,6 @@
}
// We may abort, so initialize to defaults.
- mLastSystemDecorRect.set(0, 0, 0, 0);
- mHasClipRect = false;
- mClipRect.set(0, 0, 0, 0);
mLastClipRect.set(0, 0, 0, 0);
// Set up surface control with initial size.
@@ -649,14 +641,12 @@
}
void computeShownFrameLocked() {
-
final int displayId = mWin.getDisplayId();
final ScreenRotationAnimation screenRotationAnimation =
mAnimator.getScreenRotationAnimationLocked(displayId);
final boolean screenAnimation =
screenRotationAnimation != null && screenRotationAnimation.isAnimating();
- mHasClipRect = false;
if (screenAnimation) {
// cache often used attributes locally
final Rect frame = mWin.mFrame;
@@ -796,9 +786,9 @@
// We use the clip rect as provided by the tranformation for non-fullscreen windows to
// avoid premature clipping with the system decor rect.
- clipRect.set((mHasClipRect && !fullscreen) ? mClipRect : mSystemDecorRect);
+ clipRect.set(mSystemDecorRect);
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect
- + " mHasClipRect=" + mHasClipRect + " fullscreen=" + fullscreen);
+ + " fullscreen=" + fullscreen);
if (isFreeformResizing && !w.isChildWindow()) {
// For freeform resizing non child windows, we are using the big surface positioned
@@ -808,12 +798,6 @@
w.expandForSurfaceInsets(clipRect);
- if (mHasClipRect && fullscreen) {
- // We intersect the clip rect specified by the transformation with the expanded system
- // decor rect to prevent artifacts from drawing during animation if the transformation
- // clip rect extends outside the system decor rect.
- clipRect.intersect(mClipRect);
- }
// The clip rect was generated assuming (0,0) as the window origin,
// so we need to translate to match the actual surface coordinates.
clipRect.offset(w.mAttrs.surfaceInsets.left, w.mAttrs.surfaceInsets.top);
@@ -1378,8 +1362,6 @@
pw.print(prefix); pw.print("mDrawState="); pw.print(drawStateToString());
pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden);
pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw);
- pw.print(" last="); mLastSystemDecorRect.printShortString(pw);
- pw.print(" mHasClipRect="); pw.print(mHasClipRect);
pw.print(" mLastClipRect="); mLastClipRect.printShortString(pw);
if (!mLastFinalClipRect.isEmpty()) {
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 67bad0f..8fd5be2 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -358,6 +358,7 @@
Return<void> gnssAcquireWakelockCb() override;
Return<void> gnssReleaseWakelockCb() override;
Return<void> gnssRequestTimeCb() override;
+ Return<void> gnssRequestLocationCb(const bool independentFromGnss) override;
Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;
// New in 1.1
@@ -472,6 +473,11 @@
return Void();
}
+Return<void> GnssCallback::gnssRequestLocationCb(const bool independentFromGnss) {
+ // TODO(b/72405645): call into java implementation
+ return Void();
+}
+
Return<void> GnssCallback::gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) {
ALOGD("%s: yearOfHw=%d\n", __func__, info.yearOfHw);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index a8e8237..9fcf3ee 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -19,12 +19,10 @@
import android.app.admin.IDevicePolicyManager;
import android.content.ComponentName;
import android.os.PersistableBundle;
-import android.os.UserHandle;
import android.security.keymaster.KeymasterCertificateChain;
import android.security.keystore.ParcelableKeyGenParameterSpec;
import android.telephony.data.ApnSetting;
-import com.android.internal.R;
import com.android.server.SystemService;
import java.util.ArrayList;
@@ -107,11 +105,6 @@
}
@Override
- public boolean startUserInBackground(ComponentName who, UserHandle userHandle) {
- return false;
- }
-
- @Override
public void setStartUserSessionMessage(
ComponentName admin, CharSequence startUserSessionMessage) {}
@@ -175,4 +168,13 @@
public boolean isOverrideApnEnabled(ComponentName admin) {
return false;
}
+
+ public void clearSystemUpdatePolicyFreezePeriodRecord() {
+ }
+
+ @Override
+ public boolean isMeteredDataDisabledForUser(ComponentName admin,
+ String packageName, int userId) {
+ return false;
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 99712a5..4c57f7f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -19,7 +19,6 @@
import static android.Manifest.permission.BIND_DEVICE_ADMIN;
import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityManager.USER_OP_SUCCESS;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY;
@@ -68,9 +67,6 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker
.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
-import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
-
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER;
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;
@@ -238,6 +234,7 @@
import java.lang.reflect.Constructor;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
+import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -248,7 +245,6 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -311,6 +307,8 @@
private static final String TAG_PRINTING_ENABLED = "printing-enabled";
+ private static final String TAG_TRANSFER_OWNERSHIP_BUNDLE = "transfer-ownership-bundle";
+
private static final int REQUEST_EXPIRE_PASSWORD = 5571;
private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1);
@@ -725,7 +723,14 @@
handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle);
} else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)) {
clearWipeProfileNotification();
+ } else if (Intent.ACTION_DATE_CHANGED.equals(action)
+ || Intent.ACTION_TIME_CHANGED.equals(action)) {
+ // Update freeze period record when clock naturally progresses to the next day
+ // (ACTION_DATE_CHANGED), or when manual clock adjustment is made
+ // (ACTION_TIME_CHANGED)
+ updateSystemUpdateFreezePeriodsRecord(/* saveIfChanged */ true);
}
+
}
private void sendDeviceOwnerUserCommand(String action, int userHandle) {
@@ -734,7 +739,8 @@
if (deviceOwner != null) {
Bundle extras = new Bundle();
extras.putParcelable(Intent.EXTRA_USER, UserHandle.of(userHandle));
- sendAdminCommandLocked(deviceOwner, action, extras, null);
+ sendAdminCommandLocked(deviceOwner, action, extras, /* result */ null,
+ /* inForeground */ true);
}
}
}
@@ -2113,6 +2119,8 @@
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
+ filter.addAction(Intent.ACTION_DATE_CHANGED);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
LocalServices.addService(DevicePolicyManagerInternal.class, mLocalService);
@@ -3301,6 +3309,7 @@
cleanUpOldUsers();
maybeSetDefaultProfileOwnerUserRestrictions();
handleStartUser(UserHandle.USER_SYSTEM);
+ maybeLogStart();
// Register an observer for watching for user setup complete and settings changes.
mSetupContentObserver.register();
@@ -3353,6 +3362,17 @@
deleteTransferOwnershipMetadataFileLocked();
deleteTransferOwnershipBundleLocked(metadata.userId);
}
+ updateSystemUpdateFreezePeriodsRecord(/* saveIfChanged */ true);
+ }
+
+ private void maybeLogStart() {
+ if (!SecurityLog.isLoggingEnabled()) {
+ return;
+ }
+ final String verifiedBootState =
+ mInjector.systemPropertiesGet("ro.boot.verifiedbootstate");
+ final String verityMode = mInjector.systemPropertiesGet("ro.boot.veritymode");
+ SecurityLog.writeEvent(SecurityLog.TAG_OS_STARTUP, verifiedBootState, verityMode);
}
private void ensureDeviceOwnerUserStarted() {
@@ -3861,14 +3881,17 @@
Preconditions.checkNotNull(who, "ComponentName is null");
validateQualityConstant(quality);
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
- if (ap.minimumPasswordMetrics.quality != quality) {
- ap.minimumPasswordMetrics.quality = quality;
- updatePasswordValidityCheckpointLocked(mInjector.userHandleGetCallingUserId());
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ final PasswordMetrics metrics = ap.minimumPasswordMetrics;
+ if (metrics.quality != quality) {
+ metrics.quality = quality;
+ updatePasswordValidityCheckpointLocked(userId);
+ saveSettingsLocked(userId);
}
+ maybeLogPasswordComplexitySet(who, userId, parent, metrics);
}
}
@@ -3961,14 +3984,17 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
- if (ap.minimumPasswordMetrics.length != length) {
- ap.minimumPasswordMetrics.length = length;
- updatePasswordValidityCheckpointLocked(mInjector.userHandleGetCallingUserId());
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ final PasswordMetrics metrics = ap.minimumPasswordMetrics;
+ if (metrics.length != length) {
+ metrics.length = length;
+ updatePasswordValidityCheckpointLocked(userId);
+ saveSettingsLocked(userId);
}
+ maybeLogPasswordComplexitySet(who, userId, parent, metrics);
}
}
@@ -3984,15 +4010,21 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
if (ap.passwordHistoryLength != length) {
ap.passwordHistoryLength = length;
- updatePasswordValidityCheckpointLocked(mInjector.userHandleGetCallingUserId());
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ updatePasswordValidityCheckpointLocked(userId);
+ saveSettingsLocked(userId);
}
}
+ if (SecurityLog.isLoggingEnabled()) {
+ final int affectedUserId = parent ? getProfileParentId(userId) : userId;
+ SecurityLog.writeEvent(SecurityLog.TAG_PASSWORD_HISTORY_LENGTH_SET,
+ who.getPackageName(), userId, affectedUserId, length);
+ }
}
@Override
@@ -4026,6 +4058,11 @@
// in case this is the first one, set the alarm on the appropriate user.
setExpirationAlarmCheckLocked(mContext, userHandle, parent);
}
+ if (SecurityLog.isLoggingEnabled()) {
+ final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
+ SecurityLog.writeEvent(SecurityLog.TAG_PASSWORD_EXPIRATION_SET, who.getPackageName(),
+ userHandle, affectedUserId, timeout);
+ }
}
/**
@@ -4174,14 +4211,17 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
- ActiveAdmin ap = getActiveAdminForCallerLocked(
+ final ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
- if (ap.minimumPasswordMetrics.upperCase != length) {
- ap.minimumPasswordMetrics.upperCase = length;
- updatePasswordValidityCheckpointLocked(mInjector.userHandleGetCallingUserId());
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ final PasswordMetrics metrics = ap.minimumPasswordMetrics;
+ if (metrics.upperCase != length) {
+ metrics.upperCase = length;
+ updatePasswordValidityCheckpointLocked(userId);
+ saveSettingsLocked(userId);
}
+ maybeLogPasswordComplexitySet(who, userId, parent, metrics);
}
}
@@ -4194,14 +4234,17 @@
@Override
public void setPasswordMinimumLowerCase(ComponentName who, int length, boolean parent) {
Preconditions.checkNotNull(who, "ComponentName is null");
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
- if (ap.minimumPasswordMetrics.lowerCase != length) {
- ap.minimumPasswordMetrics.lowerCase = length;
- updatePasswordValidityCheckpointLocked(mInjector.userHandleGetCallingUserId());
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ final PasswordMetrics metrics = ap.minimumPasswordMetrics;
+ if (metrics.lowerCase != length) {
+ metrics.lowerCase = length;
+ updatePasswordValidityCheckpointLocked(userId);
+ saveSettingsLocked(userId);
}
+ maybeLogPasswordComplexitySet(who, userId, parent, metrics);
}
}
@@ -4217,14 +4260,17 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
- if (ap.minimumPasswordMetrics.letters != length) {
- ap.minimumPasswordMetrics.letters = length;
- updatePasswordValidityCheckpointLocked(mInjector.userHandleGetCallingUserId());
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ final PasswordMetrics metrics = ap.minimumPasswordMetrics;
+ if (metrics.letters != length) {
+ metrics.letters = length;
+ updatePasswordValidityCheckpointLocked(userId);
+ saveSettingsLocked(userId);
}
+ maybeLogPasswordComplexitySet(who, userId, parent, metrics);
}
}
@@ -4240,14 +4286,17 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
- if (ap.minimumPasswordMetrics.numeric != length) {
- ap.minimumPasswordMetrics.numeric = length;
- updatePasswordValidityCheckpointLocked(mInjector.userHandleGetCallingUserId());
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ final PasswordMetrics metrics = ap.minimumPasswordMetrics;
+ if (metrics.numeric != length) {
+ metrics.numeric = length;
+ updatePasswordValidityCheckpointLocked(userId);
+ saveSettingsLocked(userId);
}
+ maybeLogPasswordComplexitySet(who, userId, parent, metrics);
}
}
@@ -4255,7 +4304,7 @@
public int getPasswordMinimumNumeric(ComponentName who, int userHandle, boolean parent) {
return getStrictestPasswordRequirement(who, userHandle, parent,
admin -> admin.minimumPasswordMetrics.numeric, PASSWORD_QUALITY_COMPLEX);
- }
+ }
@Override
public void setPasswordMinimumSymbols(ComponentName who, int length, boolean parent) {
@@ -4263,14 +4312,17 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
- if (ap.minimumPasswordMetrics.symbols != length) {
+ final PasswordMetrics metrics = ap.minimumPasswordMetrics;
+ if (metrics.symbols != length) {
ap.minimumPasswordMetrics.symbols = length;
- updatePasswordValidityCheckpointLocked(mInjector.userHandleGetCallingUserId());
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ updatePasswordValidityCheckpointLocked(userId);
+ saveSettingsLocked(userId);
}
+ maybeLogPasswordComplexitySet(who, userId, parent, metrics);
}
}
@@ -4286,14 +4338,17 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
- if (ap.minimumPasswordMetrics.nonLetter != length) {
+ final PasswordMetrics metrics = ap.minimumPasswordMetrics;
+ if (metrics.nonLetter != length) {
ap.minimumPasswordMetrics.nonLetter = length;
- updatePasswordValidityCheckpointLocked(mInjector.userHandleGetCallingUserId());
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ updatePasswordValidityCheckpointLocked(userId);
+ saveSettingsLocked(userId);
}
+ maybeLogPasswordComplexitySet(who, userId, parent, metrics);
}
}
@@ -4580,6 +4635,7 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
@@ -4589,9 +4645,14 @@
who, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent);
if (ap.maximumFailedPasswordsForWipe != num) {
ap.maximumFailedPasswordsForWipe = num;
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ saveSettingsLocked(userId);
}
}
+ if (SecurityLog.isLoggingEnabled()) {
+ final int affectedUserId = parent ? getProfileParentId(userId) : userId;
+ SecurityLog.writeEvent(SecurityLog.TAG_MAX_PASSWORD_ATTEMPTS_SET, who.getPackageName(),
+ userId, affectedUserId, num);
+ }
}
@Override
@@ -4689,7 +4750,6 @@
return false;
}
}
-
@Override
public boolean resetPassword(String passwordOrNull, int flags) throws RemoteException {
final int callingUid = mInjector.binderGetCallingUid();
@@ -4945,6 +5005,11 @@
updateMaximumTimeToLockLocked(userHandle);
}
}
+ if (SecurityLog.isLoggingEnabled()) {
+ final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
+ SecurityLog.writeEvent(SecurityLog.TAG_MAX_SCREEN_LOCK_TIMEOUT_SET,
+ who.getPackageName(), userHandle, affectedUserId, timeMs);
+ }
}
private void updateMaximumTimeToLockLocked(@UserIdInt int userId) {
@@ -5114,11 +5179,12 @@
final long ident = mInjector.binderClearCallingIdentity();
try {
+ final ComponentName adminComponent = admin.info.getComponent();
// Evict key
if ((flags & DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY) != 0) {
enforceManagedProfile(
callingUserId, "set FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY");
- if (!isProfileOwner(admin.info.getComponent(), callingUserId)) {
+ if (!isProfileOwner(adminComponent, callingUserId)) {
throw new SecurityException("Only profile owner admins can set "
+ "FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY");
}
@@ -5148,6 +5214,13 @@
} else {
mInjector.getTrustManager().setDeviceLockedForUser(userToLock, true);
}
+
+ if (SecurityLog.isLoggingEnabled()) {
+ final int affectedUserId =
+ parent ? getProfileParentId(callingUserId) : callingUserId;
+ SecurityLog.writeEvent(SecurityLog.TAG_REMOTE_LOCK,
+ adminComponent.getPackageName(), callingUserId, affectedUserId);
+ }
} catch (RemoteException e) {
} finally {
mInjector.binderRestoreCallingIdentity(ident);
@@ -6178,8 +6251,7 @@
if (mInjector.securityLogIsLoggingEnabled()) {
SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT,
- /*result*/ 0,
- /*method strength*/ 1);
+ /*result*/ 0, /*method strength*/ 1);
}
}
@@ -7026,6 +7098,11 @@
saveSettingsLocked(userHandle);
}
}
+ if (SecurityLog.isLoggingEnabled()) {
+ final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
+ SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISABLED_FEATURES_SET,
+ who.getPackageName(), userHandle, affectedUserId, which);
+ }
}
/**
@@ -8948,7 +9025,7 @@
}
@Override
- public boolean startUserInBackground(ComponentName who, UserHandle userHandle) {
+ public int startUserInBackground(ComponentName who, UserHandle userHandle) {
Preconditions.checkNotNull(who, "ComponentName is null");
Preconditions.checkNotNull(userHandle, "UserHandle is null");
@@ -8959,27 +9036,31 @@
final int userId = userHandle.getIdentifier();
if (isManagedProfile(userId)) {
Log.w(LOG_TAG, "Managed profile cannot be started in background");
- return false;
+ return DevicePolicyManager.USER_OPERATION_ERROR_MANAGED_PROFILE;
}
final long id = mInjector.binderClearCallingIdentity();
try {
if (!mInjector.getActivityManagerInternal().canStartMoreUsers()) {
Log.w(LOG_TAG, "Cannot start more users in background");
- return false;
+ return DevicePolicyManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS;
}
- return mInjector.getIActivityManager().startUserInBackground(userId);
+ if (mInjector.getIActivityManager().startUserInBackground(userId)) {
+ return DevicePolicyManager.USER_OPERATION_SUCCESS;
+ } else {
+ return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
+ }
} catch (RemoteException e) {
// Same process, should not happen.
- return false;
+ return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
}
@Override
- public boolean stopUser(ComponentName who, UserHandle userHandle) {
+ public int stopUser(ComponentName who, UserHandle userHandle) {
Preconditions.checkNotNull(who, "ComponentName is null");
Preconditions.checkNotNull(userHandle, "UserHandle is null");
@@ -8990,23 +9071,14 @@
final int userId = userHandle.getIdentifier();
if (isManagedProfile(userId)) {
Log.w(LOG_TAG, "Managed profile cannot be stopped");
- return false;
+ return DevicePolicyManager.USER_OPERATION_ERROR_MANAGED_PROFILE;
}
- final long id = mInjector.binderClearCallingIdentity();
- try {
- return mInjector.getIActivityManager().stopUser(userId, true /*force*/, null)
- == USER_OP_SUCCESS;
- } catch (RemoteException e) {
- // Same process, should not happen.
- return false;
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
+ return stopUserUnchecked(userId);
}
@Override
- public boolean logoutUser(ComponentName who) {
+ public int logoutUser(ComponentName who) {
Preconditions.checkNotNull(who, "ComponentName is null");
final int callingUserId = mInjector.userHandleGetCallingUserId();
@@ -9020,20 +9092,40 @@
if (isManagedProfile(callingUserId)) {
Log.w(LOG_TAG, "Managed profile cannot be logout");
- return false;
+ return DevicePolicyManager.USER_OPERATION_ERROR_MANAGED_PROFILE;
}
final long id = mInjector.binderClearCallingIdentity();
try {
if (!mInjector.getIActivityManager().switchUser(UserHandle.USER_SYSTEM)) {
Log.w(LOG_TAG, "Failed to switch to primary user");
- return false;
+ // This should never happen as target user is UserHandle.USER_SYSTEM
+ return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
}
- return mInjector.getIActivityManager().stopUser(callingUserId, true /*force*/, null)
- == USER_OP_SUCCESS;
} catch (RemoteException e) {
// Same process, should not happen.
- return false;
+ return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
+ } finally {
+ mInjector.binderRestoreCallingIdentity(id);
+ }
+
+ return stopUserUnchecked(callingUserId);
+ }
+
+ private int stopUserUnchecked(int userId) {
+ final long id = mInjector.binderClearCallingIdentity();
+ try {
+ switch (mInjector.getIActivityManager().stopUser(userId, true /*force*/, null)) {
+ case ActivityManager.USER_OP_SUCCESS:
+ return DevicePolicyManager.USER_OPERATION_SUCCESS;
+ case ActivityManager.USER_OP_IS_CURRENT:
+ return DevicePolicyManager.USER_OPERATION_ERROR_CURRENT_USER;
+ default:
+ return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
+ }
+ } catch (RemoteException e) {
+ // Same process, should not happen.
+ return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
@@ -9173,6 +9265,12 @@
}
saveUserRestrictionsLocked(userHandle);
}
+ if (SecurityLog.isLoggingEnabled()) {
+ final int eventTag = enabledFromThisOwner
+ ? SecurityLog.TAG_USER_RESTRICTION_ADDED
+ : SecurityLog.TAG_USER_RESTRICTION_REMOVED;
+ SecurityLog.writeEvent(eventTag, who.getPackageName(), userHandle, key);
+ }
}
private void saveUserRestrictionsLocked(int userId) {
@@ -10422,8 +10520,15 @@
@Override
public void setSystemUpdatePolicy(ComponentName who, SystemUpdatePolicy policy) {
- if (policy != null && !policy.isValid()) {
- throw new IllegalArgumentException("Invalid system update policy.");
+ if (policy != null) {
+ // throws exception if policy type is invalid
+ policy.validateType();
+ // throws exception if freeze period is invalid
+ policy.validateFreezePeriods();
+ Pair<LocalDate, LocalDate> record = mOwners.getSystemUpdateFreezePeriodRecord();
+ // throws exception if freeze period is incompatible with previous freeze period record
+ policy.validateAgainstPreviousFreezePeriod(record.first, record.second,
+ LocalDate.now());
}
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -10431,6 +10536,7 @@
mOwners.clearSystemUpdatePolicy();
} else {
mOwners.setSystemUpdatePolicy(policy);
+ updateSystemUpdateFreezePeriodsRecord(/* saveIfChanged */ false);
}
mOwners.writeDeviceOwner();
}
@@ -10451,6 +10557,83 @@
}
}
+ private static boolean withinRange(Pair<LocalDate, LocalDate> range, LocalDate date) {
+ return (!date.isBefore(range.first) && !date.isAfter(range.second));
+ }
+
+ /**
+ * keeps track of the last continuous period when the system is under OTA freeze.
+ *
+ * DPMS keeps track of the previous dates during which OTA was freezed as a result of an
+ * system update policy with freeze periods in effect. This is needed to make robust
+ * validation on new system update polices, for example to prevent the OTA from being
+ * frozen for more than 90 days if the DPC keeps resetting a new 24-hour freeze period
+ * on midnight everyday, or having freeze periods closer than 60 days apart by DPC resetting
+ * a new freeze period after a few days.
+ *
+ * @param saveIfChanged whether to persist the result on disk if freeze period record is
+ * updated. This should only be set to {@code false} if there is a guaranteed
+ * mOwners.writeDeviceOwner() later in the control flow to reduce the number of
+ * disk writes. Otherwise you risk inconsistent on-disk state.
+ *
+ * @see SystemUpdatePolicy#validateAgainstPreviousFreezePeriod
+ */
+ private void updateSystemUpdateFreezePeriodsRecord(boolean saveIfChanged) {
+ Slog.d(LOG_TAG, "updateSystemUpdateFreezePeriodsRecord");
+ synchronized (this) {
+ final SystemUpdatePolicy policy = mOwners.getSystemUpdatePolicy();
+ if (policy == null) {
+ return;
+ }
+ final LocalDate now = LocalDate.now();
+ final Pair<LocalDate, LocalDate> currentPeriod = policy.getCurrentFreezePeriod(now);
+ if (currentPeriod == null) {
+ return;
+ }
+ final Pair<LocalDate, LocalDate> record = mOwners.getSystemUpdateFreezePeriodRecord();
+ final LocalDate start = record.first;
+ final LocalDate end = record.second;
+ final boolean changed;
+ if (end == null || start == null) {
+ // Start a new period if there is none at the moment
+ changed = mOwners.setSystemUpdateFreezePeriodRecord(now, now);
+ } else if (now.equals(end.plusDays(1))) {
+ // Extend the existing period
+ changed = mOwners.setSystemUpdateFreezePeriodRecord(start, now);
+ } else if (now.isAfter(end.plusDays(1))) {
+ if (withinRange(currentPeriod, start) && withinRange(currentPeriod, end)) {
+ // The device might be off for some period. If the past freeze record
+ // is within range of the current freeze period, assume the device was off
+ // during the period [end, now] and extend the freeze record to [start, now].
+ changed = mOwners.setSystemUpdateFreezePeriodRecord(start, now);
+ } else {
+ changed = mOwners.setSystemUpdateFreezePeriodRecord(now, now);
+ }
+ } else if (now.isBefore(start)) {
+ // Systm clock was adjusted backwards, restart record
+ changed = mOwners.setSystemUpdateFreezePeriodRecord(now, now);
+ } else /* start <= now <= end */ {
+ changed = false;
+ }
+ if (changed && saveIfChanged) {
+ mOwners.writeDeviceOwner();
+ }
+ }
+ }
+
+ @Override
+ public void clearSystemUpdatePolicyFreezePeriodRecord() {
+ enforceShell("clearSystemUpdatePolicyFreezePeriodRecord");
+ synchronized (this) {
+ // Print out current record to help diagnosed CTS failures
+ Slog.i(LOG_TAG, "Clear freeze period record: "
+ + mOwners.getSystemUpdateFreezePeriodRecordAsString());
+ if (mOwners.setSystemUpdateFreezePeriodRecord(null, null)) {
+ mOwners.writeDeviceOwner();
+ }
+ }
+ }
+
/**
* Checks if the caller of the method is the device owner app.
*
@@ -11237,22 +11420,38 @@
}
}
+ @Override
+ public boolean isMeteredDataDisabledForUser(ComponentName who,
+ String packageName, int userId) {
+ Preconditions.checkNotNull(who);
+
+ if (!mHasFeature) {
+ return false;
+ }
+ if (!isCallerWithSystemUid()) {
+ throw new SecurityException(
+ "Only the system can query restricted pkgs for a specific user");
+ }
+ synchronized (this) {
+ final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId);
+ if (admin != null && admin.meteredDisabledPackages != null) {
+ return admin.meteredDisabledPackages.contains(packageName);
+ }
+ }
+ return false;
+ }
+
private void pushMeteredDisabledPackagesLocked(int userId) {
mInjector.getNetworkPolicyManagerInternal().setMeteredRestrictedPackages(
getMeteredDisabledPackagesLocked(userId), userId);
}
private Set<String> getMeteredDisabledPackagesLocked(int userId) {
- final DevicePolicyData policy = getUserData(userId);
+ final ComponentName who = getOwnerComponent(userId);
final Set<String> restrictedPkgs = new ArraySet<>();
- for (int i = policy.mAdminList.size() - 1; i >= 0; --i) {
- final ActiveAdmin admin = policy.mAdminList.get(i);
- if (!isActiveAdminWithPolicyForUserLocked(admin,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, userId)) {
- // Not a profile or device owner, ignore
- continue;
- }
- if (admin.meteredDisabledPackages != null) {
+ if (who != null) {
+ final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId);
+ if (admin != null && admin.meteredDisabledPackages != null) {
restrictedPkgs.addAll(admin.meteredDisabledPackages);
}
}
@@ -12301,9 +12500,11 @@
}
@Override
- public boolean clearApplicationUserData(ComponentName admin, String packageName,
+ public void clearApplicationUserData(ComponentName admin, String packageName,
IPackageDataObserver callback) {
Preconditions.checkNotNull(admin, "ComponentName is null");
+ Preconditions.checkNotNull(packageName, "packageName is null");
+ Preconditions.checkNotNull(callback, "callback is null");
synchronized (this) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
}
@@ -12311,29 +12512,24 @@
long ident = mInjector.binderClearCallingIdentity();
try {
- return ActivityManager.getService().clearApplicationUserData(packageName, false,
- callback, userId);
+ ActivityManager.getService().clearApplicationUserData(packageName, false, callback,
+ userId);
} catch(RemoteException re) {
// Same process, should not happen.
} catch (SecurityException se) {
// This can happen e.g. for device admin packages, do not throw out the exception,
// because callers have no means to know beforehand for which packages this might
- // happen.
+ // happen. If so, we send back that removal failed.
Slog.w(LOG_TAG, "Not allowed to clear application user data for package " + packageName,
se);
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
-
- if (callback != null) {
try {
- // If there was a throw above, we send back that removal failed
callback.onRemoveCompleted(packageName, false);
} catch (RemoteException re) {
// Caller is no longer available, ignore
}
+ } finally {
+ mInjector.binderRestoreCallingIdentity(ident);
}
- return false;
}
@Override
@@ -12624,6 +12820,7 @@
try (FileInputStream stream = new FileInputStream(bundleFile)) {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(stream, null);
+ parser.next();
return PersistableBundle.restoreFromXml(parser);
} catch (IOException | XmlPullParserException | IllegalArgumentException e) {
Slog.e(LOG_TAG, "Caught exception while trying to load the "
@@ -12845,7 +13042,10 @@
final XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(stream, StandardCharsets.UTF_8.name());
serializer.startDocument(null, true);
+ serializer.startTag(null, TAG_TRANSFER_OWNERSHIP_BUNDLE);
bundle.saveToXml(serializer);
+ serializer.endTag(null, TAG_TRANSFER_OWNERSHIP_BUNDLE);
+ serializer.endDocument();
atomicFile.finishWrite(stream);
} catch (IOException | XmlPullParserException e) {
Slog.e(LOG_TAG, "Caught exception while trying to save the "
@@ -12860,4 +13060,15 @@
TRANSFER_OWNERSHIP_PARAMETERS_XML);
parametersFile.delete();
}
+
+ private void maybeLogPasswordComplexitySet(ComponentName who, int userId, boolean parent,
+ PasswordMetrics metrics) {
+ if (SecurityLog.isLoggingEnabled()) {
+ final int affectedUserId = parent ? getProfileParentId(userId) : userId;
+ SecurityLog.writeEvent(SecurityLog.TAG_PASSWORD_COMPLEXITY_SET, who.getPackageName(),
+ userId, affectedUserId, metrics.length, metrics.quality, metrics.letters,
+ metrics.nonLetter, metrics.numeric, metrics.upperCase, metrics.lowerCase,
+ metrics.symbols);
+ }
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index d2151ed..0268519 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -47,6 +47,7 @@
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
+import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -78,6 +79,7 @@
private static final String TAG_DEVICE_OWNER = "device-owner";
private static final String TAG_DEVICE_INITIALIZER = "device-initializer";
private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy";
+ private static final String TAG_FREEZE_PERIOD_RECORD = "freeze-record";
private static final String TAG_PENDING_OTA_INFO = "pending-ota-info";
private static final String TAG_PROFILE_OWNER = "profile-owner";
// Holds "context" for device-owner, this must not be show up before device-owner.
@@ -90,6 +92,8 @@
private static final String ATTR_REMOTE_BUGREPORT_HASH = "remoteBugreportHash";
private static final String ATTR_USERID = "userId";
private static final String ATTR_USER_RESTRICTIONS_MIGRATED = "userRestrictionsMigrated";
+ private static final String ATTR_FREEZE_RECORD_START = "start";
+ private static final String ATTR_FREEZE_RECORD_END = "end";
private final UserManager mUserManager;
private final UserManagerInternal mUserManagerInternal;
@@ -105,6 +109,8 @@
// Local system update policy controllable by device owner.
private SystemUpdatePolicy mSystemUpdatePolicy;
+ private LocalDate mSystemUpdateFreezeStart;
+ private LocalDate mSystemUpdateFreezeEnd;
// Pending OTA info if there is one.
@Nullable
@@ -355,6 +361,47 @@
}
}
+ Pair<LocalDate, LocalDate> getSystemUpdateFreezePeriodRecord() {
+ synchronized (mLock) {
+ return new Pair<>(mSystemUpdateFreezeStart, mSystemUpdateFreezeEnd);
+ }
+ }
+
+ String getSystemUpdateFreezePeriodRecordAsString() {
+ StringBuilder freezePeriodRecord = new StringBuilder();
+ freezePeriodRecord.append("start: ");
+ if (mSystemUpdateFreezeStart != null) {
+ freezePeriodRecord.append(mSystemUpdateFreezeStart.toString());
+ } else {
+ freezePeriodRecord.append("null");
+ }
+ freezePeriodRecord.append("; end: ");
+ if (mSystemUpdateFreezeEnd != null) {
+ freezePeriodRecord.append(mSystemUpdateFreezeEnd.toString());
+ } else {
+ freezePeriodRecord.append("null");
+ }
+ return freezePeriodRecord.toString();
+ }
+
+ /**
+ * Returns {@code true} if the freeze period record is changed, {@code false} otherwise.
+ */
+ boolean setSystemUpdateFreezePeriodRecord(LocalDate start, LocalDate end) {
+ boolean changed = false;
+ synchronized (mLock) {
+ if (!Objects.equals(mSystemUpdateFreezeStart, start)) {
+ mSystemUpdateFreezeStart = start;
+ changed = true;
+ }
+ if (!Objects.equals(mSystemUpdateFreezeEnd, end)) {
+ mSystemUpdateFreezeEnd = end;
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
boolean hasDeviceOwner() {
synchronized (mLock) {
return mDeviceOwner != null;
@@ -676,9 +723,16 @@
mSystemUpdatePolicy.saveToXml(out);
out.endTag(null, TAG_SYSTEM_UPDATE_POLICY);
}
-
- if (mSystemUpdateInfo != null) {
- mSystemUpdateInfo.writeToXml(out, TAG_PENDING_OTA_INFO);
+ if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) {
+ out.startTag(null, TAG_FREEZE_PERIOD_RECORD);
+ if (mSystemUpdateFreezeStart != null) {
+ out.attribute(null, ATTR_FREEZE_RECORD_START,
+ mSystemUpdateFreezeStart.toString());
+ }
+ if (mSystemUpdateFreezeEnd != null) {
+ out.attribute(null, ATTR_FREEZE_RECORD_END, mSystemUpdateFreezeEnd.toString());
+ }
+ out.endTag(null, TAG_FREEZE_PERIOD_RECORD);
}
}
@@ -711,6 +765,19 @@
case TAG_PENDING_OTA_INFO:
mSystemUpdateInfo = SystemUpdateInfo.readFromXml(parser);
break;
+ case TAG_FREEZE_PERIOD_RECORD:
+ String startDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_START);
+ String endDate = parser.getAttributeValue(null, ATTR_FREEZE_RECORD_END);
+ if (startDate != null && endDate != null) {
+ mSystemUpdateFreezeStart = LocalDate.parse(startDate);
+ mSystemUpdateFreezeEnd = LocalDate.parse(endDate);
+ if (mSystemUpdateFreezeStart.isAfter(mSystemUpdateFreezeEnd)) {
+ Slog.e(TAG, "Invalid system update freeze record loaded");
+ mSystemUpdateFreezeStart = null;
+ mSystemUpdateFreezeEnd = null;
+ }
+ }
+ break;
default:
Slog.e(TAG, "Unexpected tag: " + tag);
return false;
@@ -879,6 +946,14 @@
pw.println(prefix + "Pending System Update: " + mSystemUpdateInfo);
needBlank = true;
}
+ if (mSystemUpdateFreezeStart != null || mSystemUpdateFreezeEnd != null) {
+ if (needBlank) {
+ pw.println();
+ }
+ pw.println(prefix + "System update freeze record: "
+ + getSystemUpdateFreezePeriodRecordAsString());
+ needBlank = true;
+ }
}
@VisibleForTesting
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java b/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java
index 6a9b53a..a17a107 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java
@@ -47,7 +47,7 @@
* This is a lightweight operation to prepare variables but not perform any IO.
*/
public PasswordBlacklist(File file) {
- mFile = new AtomicFile(file);
+ mFile = new AtomicFile(file, "device-policy");
}
/**
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index a9fd8e5..3277adf 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -71,6 +71,10 @@
*/
private static final int BUFFER_ENTRIES_MAXIMUM_LEVEL = BUFFER_ENTRIES_NOTIFICATION_LEVEL * 10;
/**
+ * Critical log buffer level, 90% of capacity.
+ */
+ private static final int BUFFER_ENTRIES_CRITICAL_LEVEL = BUFFER_ENTRIES_MAXIMUM_LEVEL * 9 / 10;
+ /**
* How often should Device Owner be notified under normal circumstances.
*/
private static final long RATE_LIMIT_INTERVAL_MILLISECONDS = TimeUnit.HOURS.toMillis(2);
@@ -97,6 +101,10 @@
@GuardedBy("mLock")
private boolean mAllowedToRetrieve = false;
+ // Whether we have already logged the fact that log buffer reached 90%, to avoid dupes.
+ @GuardedBy("mLock")
+ private boolean mCriticalLevelLogged = false;
+
/**
* Last events fetched from log to check for overlap between batches. We can leave it empty if
* we are sure there will be no overlap anymore, e.g. when we get empty batch.
@@ -116,10 +124,12 @@
void start() {
Slog.i(TAG, "Starting security logging.");
+ SecurityLog.writeEvent(SecurityLog.TAG_LOGGING_STARTED);
mLock.lock();
try {
if (mMonitorThread == null) {
mPendingLogs = new ArrayList<>();
+ mCriticalLevelLogged = false;
mId = 0;
mAllowedToRetrieve = false;
mNextAllowedRetrievalTimeMillis = -1;
@@ -135,6 +145,7 @@
void stop() {
Slog.i(TAG, "Stopping security logging.");
+ SecurityLog.writeEvent(SecurityLog.TAG_LOGGING_STOPPED);
mLock.lock();
try {
if (mMonitorThread != null) {
@@ -205,6 +216,7 @@
mLock.lock();
mAllowedToRetrieve = false;
mPendingLogs = new ArrayList<>();
+ mCriticalLevelLogged = false;
mLock.unlock();
Slog.i(TAG, "Discarded all logs.");
}
@@ -222,6 +234,7 @@
+ RATE_LIMIT_INTERVAL_MILLISECONDS;
List<SecurityEvent> result = mPendingLogs;
mPendingLogs = new ArrayList<>();
+ mCriticalLevelLogged = false;
return result;
} else {
return null;
@@ -344,11 +357,14 @@
// Save the rest of the new batch.
mPendingLogs.addAll(idLogs);
+ checkCriticalLevel();
+
if (mPendingLogs.size() > BUFFER_ENTRIES_MAXIMUM_LEVEL) {
// Truncate buffer down to half of BUFFER_ENTRIES_MAXIMUM_LEVEL.
mPendingLogs = new ArrayList<>(mPendingLogs.subList(
mPendingLogs.size() - (BUFFER_ENTRIES_MAXIMUM_LEVEL / 2),
mPendingLogs.size()));
+ mCriticalLevelLogged = false;
Slog.i(TAG, "Pending logs buffer full. Discarding old logs.");
}
if (DEBUG) Slog.d(TAG, mPendingLogs.size() + " pending events in the buffer after merging,"
@@ -357,6 +373,20 @@
}
@GuardedBy("mLock")
+ private void checkCriticalLevel() {
+ if (!SecurityLog.isLoggingEnabled()) {
+ return;
+ }
+
+ if (mPendingLogs.size() >= BUFFER_ENTRIES_CRITICAL_LEVEL) {
+ if (!mCriticalLevelLogged) {
+ mCriticalLevelLogged = true;
+ SecurityLog.writeEvent(SecurityLog.TAG_LOG_BUFFER_SIZE_CRITICAL);
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
private void assignLogId(SecurityEvent event) {
event.setId(mId);
if (mId == Long.MAX_VALUE) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 94a356e..210fd47 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -111,6 +111,7 @@
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.storage.DeviceStorageMonitorService;
import com.android.server.telecom.TelecomLoaderService;
+import com.android.server.textclassifier.TextClassificationManagerService;
import com.android.server.trust.TrustManagerService;
import com.android.server.tv.TvInputManagerService;
import com.android.server.tv.TvRemoteService;
@@ -160,7 +161,7 @@
* them from the build system somehow.
*/
private static final String BACKUP_MANAGER_SERVICE_CLASS =
- "com.android.server.backup.RefactoredBackupManagerService$Lifecycle";
+ "com.android.server.backup.BackupManagerService$Lifecycle";
private static final String APPWIDGET_SERVICE_CLASS =
"com.android.server.appwidget.AppWidgetService";
private static final String VOICE_RECOGNITION_MANAGER_SERVICE_CLASS =
@@ -733,6 +734,8 @@
false);
boolean disableTextServices = SystemProperties.getBoolean("config.disable_textservices",
false);
+ boolean disableSystemTextClassifier = SystemProperties.getBoolean(
+ "config.disable_systemtextclassifier", false);
boolean disableConsumerIr = SystemProperties.getBoolean("config.disable_consumerir", false);
boolean disableVrManager = SystemProperties.getBoolean("config.disable_vrmanager", false);
boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice",
@@ -1066,6 +1069,12 @@
traceEnd();
}
+ if (!disableSystemTextClassifier) {
+ traceBeginAndSlog("StartTextClassificationManagerService");
+ mSystemServiceManager.startService(TextClassificationManagerService.Lifecycle.class);
+ traceEnd();
+ }
+
traceBeginAndSlog("StartNetworkScoreService");
try {
networkScore = new NetworkScoreService(context);
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
index c397f23..0752537 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
@@ -26,6 +26,7 @@
import com.android.server.testing.FrameworkRobolectricTestRunner;
import com.android.server.testing.SystemLoaderClasses;
+import com.android.server.testing.SystemLoaderPackages;
import org.junit.Before;
import org.junit.Test;
@@ -36,7 +37,7 @@
@RunWith(FrameworkRobolectricTestRunner.class)
@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderClasses({BackupManagerConstants.class})
+@SystemLoaderPackages({"com.android.server.backup"})
@Presubmit
public class BackupManagerConstantsTest {
private static final String PACKAGE_NAME = "some.package.name";
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index e072800..df09780 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -41,13 +41,15 @@
import android.os.HandlerThread;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
+import com.android.server.backup.PackageManagerBackupAgent;
import com.android.server.backup.testing.ShadowAppBackupUtils;
import com.android.server.backup.testing.ShadowBackupPolicyEnforcer;
import com.android.server.backup.testing.TransportData;
import com.android.server.backup.testing.TransportTestUtils.TransportMock;
import com.android.server.backup.transport.TransportNotRegisteredException;
import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
+import com.android.server.testing.SystemLoaderPackages;
+
import java.io.File;
import java.util.HashMap;
import java.util.List;
@@ -73,7 +75,7 @@
sdk = 26,
shadows = {ShadowAppBackupUtils.class, ShadowBackupPolicyEnforcer.class}
)
-@SystemLoaderClasses({RefactoredBackupManagerService.class, TransportManager.class})
+@SystemLoaderPackages({"com.android.server.backup"})
@Presubmit
public class BackupManagerServiceTest {
private static final String TAG = "BMSTest";
@@ -126,8 +128,7 @@
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
.thenReturn("destinationString");
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
String destination = backupManagerService.getDestinationString(mTransportName);
@@ -139,8 +140,7 @@
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
.thenThrow(TransportNotRegisteredException.class);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
String destination = backupManagerService.getDestinationString(mTransportName);
@@ -152,8 +152,7 @@
mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName)))
.thenThrow(TransportNotRegisteredException.class);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
expectThrows(
SecurityException.class,
@@ -167,8 +166,7 @@
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
TransportMock transportMock = setUpCurrentTransport(mTransportManager, backupTransport());
ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> true;
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
boolean result = backupManagerService.isAppEligibleForBackup("app.package");
@@ -183,8 +181,7 @@
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
setUpCurrentTransport(mTransportManager, mTransport);
ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false;
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
boolean result = backupManagerService.isAppEligibleForBackup("app.package");
@@ -195,8 +192,7 @@
public void testIsAppEligibleForBackup_withoutPermission() throws Exception {
mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
setUpCurrentTransport(mTransportManager, mTransport);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
expectThrows(
SecurityException.class,
@@ -211,8 +207,7 @@
packagesMap.put("package.a", true);
packagesMap.put("package.b", false);
ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = packagesMap::get;
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
String[] packages = packagesMap.keySet().toArray(new String[packagesMap.size()]);
String[] filtered = backupManagerService.filterAppsEligibleForBackup(packages);
@@ -226,8 +221,7 @@
public void testFilterAppsEligibleForBackup_whenNoneIsEligible() throws Exception {
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false;
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
String[] filtered =
backupManagerService.filterAppsEligibleForBackup(
@@ -240,8 +234,7 @@
public void testFilterAppsEligibleForBackup_withoutPermission() throws Exception {
mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
setUpCurrentTransport(mTransportManager, mTransport);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
expectThrows(
SecurityException.class,
@@ -276,8 +269,7 @@
public void testSelectBackupTransport() throws Exception {
setUpForSelectTransport();
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
String oldTransport =
backupManagerService.selectBackupTransport(mNewTransport.transportName);
@@ -292,8 +284,7 @@
public void testSelectBackupTransport_withoutPermission() throws Exception {
setUpForSelectTransport();
mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
expectThrows(
SecurityException.class,
@@ -306,8 +297,7 @@
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
.thenReturn(BackupManager.SUCCESS);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
@@ -327,8 +317,7 @@
when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
.thenReturn(BackupManager.SUCCESS);
ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
@@ -347,8 +336,7 @@
when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
.thenReturn(BackupManager.SUCCESS);
ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
@@ -363,8 +351,7 @@
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent)))
.thenReturn(BackupManager.ERROR_TRANSPORT_UNAVAILABLE);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback);
@@ -381,8 +368,7 @@
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
when(mTransportManager.registerAndSelectTransport(eq(newTransportComponent)))
.thenReturn(BackupManager.SUCCESS);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
backupManagerService.selectBackupTransportAsync(newTransportComponent, callback);
@@ -396,8 +382,7 @@
public void testSelectBackupTransportAsync_withoutPermission() throws Exception {
setUpForSelectTransport();
mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
ComponentName newTransportComponent = mNewTransport.getTransportComponent();
expectThrows(
@@ -437,8 +422,7 @@
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
Intent configurationIntent = new Intent();
Intent dataManagementIntent = new Intent();
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
backupManagerService.updateTransportAttributes(
mTransportUid,
@@ -464,8 +448,7 @@
throws Exception {
setUpForUpdateTransportAttributes();
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
expectThrows(
SecurityException.class,
@@ -485,8 +468,7 @@
throws Exception {
setUpForUpdateTransportAttributes();
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
expectThrows(
RuntimeException.class,
@@ -505,8 +487,7 @@
public void testUpdateTransportAttributes_whenNameNull_throwsException() throws Exception {
setUpForUpdateTransportAttributes();
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
expectThrows(
RuntimeException.class,
@@ -526,8 +507,7 @@
throws Exception {
setUpForUpdateTransportAttributes();
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
expectThrows(
RuntimeException.class,
@@ -548,8 +528,7 @@
throws Exception {
setUpForUpdateTransportAttributes();
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
expectThrows(
RuntimeException.class,
@@ -583,8 +562,7 @@
mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
Intent configurationIntent = new Intent();
Intent dataManagementIntent = new Intent();
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
backupManagerService.updateTransportAttributes(
mTransportUid,
@@ -610,8 +588,7 @@
throws Exception {
setUpForUpdateTransportAttributes();
mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
- RefactoredBackupManagerService backupManagerService =
- createInitializedBackupManagerService();
+ BackupManagerService backupManagerService = createInitializedBackupManagerService();
expectThrows(
SecurityException.class,
@@ -648,8 +625,8 @@
verify(mTransportManager, never()).registerTransports();
}
- private RefactoredBackupManagerService createBackupManagerService() {
- return new RefactoredBackupManagerService(
+ private BackupManagerService createBackupManagerService() {
+ return new BackupManagerService(
mContext,
new Trampoline(mContext),
mBackupThread,
@@ -658,9 +635,9 @@
mTransportManager);
}
- private RefactoredBackupManagerService createInitializedBackupManagerService() {
- RefactoredBackupManagerService backupManagerService =
- new RefactoredBackupManagerService(
+ private BackupManagerService createInitializedBackupManagerService() {
+ BackupManagerService backupManagerService =
+ new BackupManagerService(
mContext,
new Trampoline(mContext),
mBackupThread,
diff --git a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
index 3668350..e103464 100644
--- a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
@@ -69,6 +69,7 @@
import com.android.server.backup.transport.TransportClient;
import com.android.server.testing.FrameworkRobolectricTestRunner;
import com.android.server.testing.SystemLoaderClasses;
+import com.android.server.testing.SystemLoaderPackages;
import com.android.server.testing.shadows.FrameworkShadowPackageManager;
import com.android.server.testing.shadows.ShadowBackupDataInput;
import com.android.server.testing.shadows.ShadowBackupDataOutput;
@@ -102,11 +103,10 @@
ShadowQueuedWork.class
}
)
+@SystemLoaderPackages({"com.android.server.backup"})
@SystemLoaderClasses({
- PerformBackupTask.class,
BackupDataOutput.class,
FullBackupDataOutput.class,
- TransportManager.class,
BackupAgent.class,
IBackupTransport.class,
IBackupAgent.class,
@@ -117,7 +117,7 @@
private static final String PACKAGE_1 = "com.example.package1";
private static final String PACKAGE_2 = "com.example.package2";
- @Mock private RefactoredBackupManagerService mBackupManagerService;
+ @Mock private BackupManagerService mBackupManagerService;
@Mock private TransportManager mTransportManager;
@Mock private DataChangedJournal mDataChangedJournal;
@Mock private IBackupObserver mObserver;
diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
index 068fe81..44ac803 100644
--- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
@@ -51,7 +51,7 @@
import com.android.server.backup.transport.TransportClientManager;
import com.android.server.backup.transport.TransportNotRegisteredException;
import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
+import com.android.server.testing.SystemLoaderPackages;
import com.android.server.testing.shadows.FrameworkShadowContextImpl;
import com.android.server.testing.shadows.FrameworkShadowPackageManager;
import java.util.ArrayList;
@@ -75,7 +75,7 @@
sdk = 26,
shadows = {FrameworkShadowPackageManager.class, FrameworkShadowContextImpl.class}
)
-@SystemLoaderClasses({TransportManager.class})
+@SystemLoaderPackages({"com.android.server.backup"})
@Presubmit
public class TransportManagerTest {
private static final String PACKAGE_A = "some.package.a";
diff --git a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
index ace0441..5810c30 100644
--- a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
@@ -42,14 +42,14 @@
import android.platform.test.annotations.Presubmit;
import com.android.internal.backup.IBackupTransport;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.TransportManager;
import com.android.server.backup.testing.TransportTestUtils;
import com.android.server.backup.testing.TransportData;
import com.android.server.backup.testing.TransportTestUtils.TransportMock;
import com.android.server.backup.transport.TransportClient;
import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
+import com.android.server.testing.SystemLoaderPackages;
import org.junit.Before;
import org.junit.Test;
@@ -67,10 +67,10 @@
@RunWith(FrameworkRobolectricTestRunner.class)
@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderClasses({PerformInitializeTaskTest.class, TransportManager.class})
+@SystemLoaderPackages({"com.android.server.backup"})
@Presubmit
public class PerformInitializeTaskTest {
- @Mock private RefactoredBackupManagerService mBackupManagerService;
+ @Mock private BackupManagerService mBackupManagerService;
@Mock private TransportManager mTransportManager;
@Mock private OnTaskFinishedListener mListener;
@Mock private IBackupTransport mTransportBinder;
diff --git a/services/robotests/src/com/android/server/backup/testing/ShadowBackupPolicyEnforcer.java b/services/robotests/src/com/android/server/backup/testing/ShadowBackupPolicyEnforcer.java
index 88b30da..ef4764d 100644
--- a/services/robotests/src/com/android/server/backup/testing/ShadowBackupPolicyEnforcer.java
+++ b/services/robotests/src/com/android/server/backup/testing/ShadowBackupPolicyEnforcer.java
@@ -3,7 +3,6 @@
import android.content.ComponentName;
import com.android.server.backup.BackupPolicyEnforcer;
-import com.android.server.backup.RefactoredBackupManagerService;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
index db6e62f..ff1644c 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
@@ -46,6 +46,7 @@
import com.android.server.backup.TransportManager;
import com.android.server.testing.FrameworkRobolectricTestRunner;
import com.android.server.testing.SystemLoaderClasses;
+import com.android.server.testing.SystemLoaderPackages;
import com.android.server.testing.shadows.ShadowCloseGuard;
import com.android.server.testing.shadows.ShadowEventLog;
import com.android.server.testing.shadows.ShadowSlog;
@@ -66,7 +67,7 @@
sdk = 26,
shadows = {ShadowEventLog.class, ShadowCloseGuard.class, ShadowSlog.class}
)
-@SystemLoaderClasses({TransportManager.class, TransportClient.class})
+@SystemLoaderPackages({"com.android.server.backup"})
@Presubmit
public class TransportClientTest {
private static final String PACKAGE_NAME = "some.package.name";
diff --git a/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java b/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java
index c94d598..d2a4d06 100644
--- a/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java
+++ b/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java
@@ -16,8 +16,7 @@
package com.android.server.testing;
-import com.android.server.backup.PerformBackupTaskTest;
-import com.android.server.backup.internal.PerformBackupTask;
+import static java.util.Arrays.asList;
import com.google.common.collect.ImmutableSet;
@@ -33,10 +32,11 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.util.Arrays;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.Set;
+import java.util.stream.Stream;
import javax.annotation.Nonnull;
@@ -51,9 +51,9 @@
* against the actual classes that are in the tree, not a past version of them. Ideally we would
* have a locally built jar referenced by Robolectric, but until that happens one can use this
* class.
- * This class reads the {@link SystemLoaderClasses} annotation on test classes and for each class
- * in that annotation value it will bypass the android jar and load it from the system class loader.
- * Allowing the test to test the actual class in the tree.
+ * This class reads the {@link SystemLoaderClasses} or {@link SystemLoaderPackages} annotations on
+ * test classes, for classes that match the annotations it will bypass the android jar and load it
+ * from the system class loader. Allowing the test to test the actual class in the tree.
*
* Implementation note: One could think about overriding
* {@link RobolectricTestRunner#createClassLoaderConfig(FrameworkMethod)} method and putting the
@@ -72,11 +72,21 @@
public FrameworkRobolectricTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
- SystemLoaderClasses annotation = testClass.getAnnotation(SystemLoaderClasses.class);
- Class<?>[] systemLoaderClasses =
- (annotation != null) ? annotation.value() : new Class<?>[0];
- Set<String> systemLoaderClassNames = classesToClassNames(systemLoaderClasses);
- mSandboxFactory = new FrameworkSandboxFactory(systemLoaderClassNames);
+ Set<String> classPrefixes = getSystemLoaderClassPrefixes(testClass);
+ mSandboxFactory = new FrameworkSandboxFactory(classPrefixes);
+ }
+
+ private Set<String> getSystemLoaderClassPrefixes(Class<?> testClass) {
+ Set<String> classPrefixes = new HashSet<>();
+ SystemLoaderClasses byClass = testClass.getAnnotation(SystemLoaderClasses.class);
+ if (byClass != null) {
+ Stream.of(byClass.value()).map(Class::getName).forEach(classPrefixes::add);
+ }
+ SystemLoaderPackages byPackage = testClass.getAnnotation(SystemLoaderPackages.class);
+ if (byPackage != null) {
+ classPrefixes.addAll(asList(byPackage.value()));
+ }
+ return classPrefixes;
}
@Nonnull
@@ -92,15 +102,15 @@
}
private static class FrameworkClassLoader extends SandboxClassLoader {
- private final Set<String> mSystemLoaderClasses;
+ private final Set<String> mSystemLoaderClassPrefixes;
private FrameworkClassLoader(
- Set<String> systemLoaderClasses,
+ Set<String> systemLoaderClassPrefixes,
ClassLoader systemClassLoader,
InstrumentationConfiguration instrumentationConfig,
URL... urls) {
super(systemClassLoader, instrumentationConfig, urls);
- mSystemLoaderClasses = systemLoaderClasses;
+ mSystemLoaderClassPrefixes = systemLoaderClassPrefixes;
}
@Override
@@ -146,8 +156,8 @@
* loader, so we test if the classes in the annotation are prefixes of the class to load.
*/
private boolean shouldLoadFromSystemLoader(String className) {
- for (String classNamePrefix : mSystemLoaderClasses) {
- if (className.startsWith(classNamePrefix)) {
+ for (String classPrefix : mSystemLoaderClassPrefixes) {
+ if (className.startsWith(classPrefix)) {
return true;
}
}
@@ -156,10 +166,10 @@
}
private static class FrameworkSandboxFactory extends SandboxFactory {
- private final Set<String> mSystemLoaderClasses;
+ private final Set<String> mSystemLoaderClassPrefixes;
- private FrameworkSandboxFactory(Set<String> systemLoaderClasses) {
- mSystemLoaderClasses = systemLoaderClasses;
+ private FrameworkSandboxFactory(Set<String> systemLoaderClassPrefixes) {
+ mSystemLoaderClassPrefixes = systemLoaderClassPrefixes;
}
@Nonnull
@@ -167,18 +177,10 @@
public ClassLoader createClassLoader(
InstrumentationConfiguration instrumentationConfig, URL... urls) {
return new FrameworkClassLoader(
- mSystemLoaderClasses,
+ mSystemLoaderClassPrefixes,
ClassLoader.getSystemClassLoader(),
instrumentationConfig,
urls);
}
}
-
- private static Set<String> classesToClassNames(Class<?>[] classes) {
- ImmutableSet.Builder<String> builder = ImmutableSet.builder();
- for (Class<?> classObject : classes) {
- builder.add(classObject.getName());
- }
- return builder.build();
- }
}
diff --git a/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java b/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java
new file mode 100644
index 0000000..e01c0a4
--- /dev/null
+++ b/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java
@@ -0,0 +1,35 @@
+/*
+ * 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.server.testing;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to be used in test classes that run with {@link FrameworkRobolectricTestRunner}.
+ * This will make the classes under the specified packages be loaded from the system class loader,
+ * NOT from the Robolectric android jar.
+ *
+ * @see FrameworkRobolectricTestRunner
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SystemLoaderPackages {
+ String[] value() default {};
+}
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 372b5be..5d8aca1 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -59,7 +59,6 @@
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Uses API introduced in O (26) -->
diff --git a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
index b68bf2d..a16f118 100644
--- a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
@@ -15,8 +15,6 @@
*/
package com.android.server;
-import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
-
import static com.android.server.ForceAppStandbyTracker.TARGET_OP;
import static org.junit.Assert.assertEquals;
@@ -35,12 +33,14 @@
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.PackageOps;
import android.app.IActivityManager;
import android.app.IUidObserver;
+import android.app.usage.UsageStatsManager;
+import android.app.usage.UsageStatsManagerInternal;
+import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -76,6 +76,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
@@ -112,6 +113,18 @@
}
@Override
+ UsageStatsManagerInternal injectUsageStatsManagerInternal() {
+ return mMockUsageStatsManagerInternal;
+ }
+
+ @Override
+ int injectGetGlobalSettingInt(String key, int def) {
+ Integer val = mGlobalSettings.get(key);
+
+ return (val == null) ? def : val;
+ }
+
+ @Override
boolean isSmallBatteryDevice() { return mIsSmallBatteryDevice; };
}
@@ -143,19 +156,24 @@
@Mock
private PowerManagerInternal mMockPowerManagerInternal;
+ @Mock
+ private UsageStatsManagerInternal mMockUsageStatsManagerInternal;
+
+ private MockContentResolver mMockContentResolver;
+
private IUidObserver mIUidObserver;
private IAppOpsCallback.Stub mAppOpsCallback;
private Consumer<PowerSaveState> mPowerSaveObserver;
private BroadcastReceiver mReceiver;
-
- private MockContentResolver mMockContentResolver;
- private FakeSettingsProvider mFakeSettingsProvider;
+ private AppIdleStateChangeListener mAppIdleStateChangeListener;
private boolean mPowerSaveMode;
private boolean mIsSmallBatteryDevice;
private final ArraySet<Pair<Integer, String>> mRestrictedPackages = new ArraySet();
+ private final HashMap<String, Integer> mGlobalSettings = new HashMap<>();
+
@Before
public void setUp() {
mMainHandler = new Handler(Looper.getMainLooper());
@@ -198,9 +216,7 @@
)).thenAnswer(inv -> new ArrayList<AppOpsManager.PackageOps>());
mMockContentResolver = new MockContentResolver();
- mFakeSettingsProvider = new FakeSettingsProvider();
when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
- mMockContentResolver.addProvider(Settings.AUTHORITY, mFakeSettingsProvider);
// Call start.
instance.start();
@@ -214,6 +230,8 @@
ArgumentCaptor.forClass(Consumer.class);
ArgumentCaptor<BroadcastReceiver> receiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
+ ArgumentCaptor<AppIdleStateChangeListener> appIdleStateChangeListenerCaptor =
+ ArgumentCaptor.forClass(AppIdleStateChangeListener.class);
verify(mMockIActivityManager).registerUidObserver(
uidObserverArgumentCaptor.capture(),
@@ -231,11 +249,14 @@
verify(mMockContext).registerReceiver(
receiverCaptor.capture(), any(IntentFilter.class));
+ verify(mMockUsageStatsManagerInternal).addAppIdleStateChangeListener(
+ appIdleStateChangeListenerCaptor.capture());
mIUidObserver = uidObserverArgumentCaptor.getValue();
mAppOpsCallback = appOpsCallbackCaptor.getValue();
mPowerSaveObserver = powerSaveObserverCaptor.getValue();
mReceiver = receiverCaptor.getValue();
+ mAppIdleStateChangeListener = appIdleStateChangeListenerCaptor.getValue();
assertNotNull(mIUidObserver);
assertNotNull(mAppOpsCallback);
@@ -275,6 +296,12 @@
/*exemptFromBatterySaver=*/ false);
}
+ private void areRestrictedWithExemption(ForceAppStandbyTrackerTestable instance,
+ int uid, String packageName, int restrictionTypes) {
+ areRestricted(instance, uid, packageName, restrictionTypes,
+ /*exemptFromBatterySaver=*/ true);
+ }
+
@Test
public void testAll() throws Exception {
final ForceAppStandbyTrackerTestable instance = newInstance();
@@ -285,6 +312,10 @@
areRestricted(instance, UID_2, PACKAGE_2, NONE);
areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areRestrictedWithExemption(instance, UID_1, PACKAGE_1, NONE);
+ areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE);
+ areRestrictedWithExemption(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+
mPowerSaveMode = true;
mPowerSaveObserver.accept(getPowerSaveState());
@@ -294,6 +325,10 @@
areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areRestrictedWithExemption(instance, UID_1, PACKAGE_1, NONE);
+ areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE);
+ areRestrictedWithExemption(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+
// Toggle the foreground state.
mPowerSaveMode = true;
mPowerSaveObserver.accept(getPowerSaveState());
@@ -420,6 +455,73 @@
assertTrue(instance.isUidTempPowerSaveWhitelisted(UID_10_2));
}
+ @Test
+ public void testExempt() throws Exception {
+ final ForceAppStandbyTrackerTestable instance = newInstance();
+ callStart(instance);
+
+ assertFalse(instance.isForceAllAppsStandbyEnabled());
+ areRestricted(instance, UID_1, PACKAGE_1, NONE);
+ areRestricted(instance, UID_2, PACKAGE_2, NONE);
+ areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+
+ mPowerSaveMode = true;
+ mPowerSaveObserver.accept(getPowerSaveState());
+
+ assertTrue(instance.isForceAllAppsStandbyEnabled());
+
+ areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
+ areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
+ areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
+ areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+
+ // Exempt package 2 on user-10.
+ mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_2, /*user=*/ 10, false,
+ UsageStatsManager.STANDBY_BUCKET_EXEMPTED);
+
+ areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
+ areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
+ areRestricted(instance, UID_10_2, PACKAGE_2, NONE);
+
+ areRestrictedWithExemption(instance, UID_1, PACKAGE_1, NONE);
+ areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE);
+ areRestrictedWithExemption(instance, UID_10_2, PACKAGE_2, NONE);
+
+ // Exempt package 1 on user-0.
+ mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_1, /*user=*/ 0, false,
+ UsageStatsManager.STANDBY_BUCKET_EXEMPTED);
+
+ areRestricted(instance, UID_1, PACKAGE_1, NONE);
+ areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
+ areRestricted(instance, UID_10_2, PACKAGE_2, NONE);
+
+ // Unexempt package 2 on user-10.
+ mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_2, /*user=*/ 10, false,
+ UsageStatsManager.STANDBY_BUCKET_ACTIVE);
+
+ areRestricted(instance, UID_1, PACKAGE_1, NONE);
+ areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
+ areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
+
+ // Check force-app-standby.
+ // EXEMPT doesn't exempt from force-app-standby.
+ mPowerSaveMode = false;
+ mPowerSaveObserver.accept(getPowerSaveState());
+
+ mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_1, /*user=*/ 0, false,
+ UsageStatsManager.STANDBY_BUCKET_EXEMPTED);
+ mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_2, /*user=*/ 0, false,
+ UsageStatsManager.STANDBY_BUCKET_EXEMPTED);
+
+ setAppOps(UID_1, PACKAGE_1, true);
+
+ areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
+ areRestricted(instance, UID_2, PACKAGE_2, NONE);
+
+ areRestrictedWithExemption(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
+ areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE);
+ }
+
public void loadPersistedAppOps() throws Exception {
final ForceAppStandbyTrackerTestable instance = newInstance();
@@ -661,6 +763,7 @@
mPowerSaveMode = true;
mPowerSaveObserver.accept(getPowerSaveState());
+ waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
verify(l, times(0)).updateJobsForUid(anyInt());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
@@ -780,6 +883,7 @@
mPowerSaveMode = false;
mPowerSaveObserver.accept(getPowerSaveState());
+ waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
verify(l, times(0)).updateJobsForUid(eq(UID_10_1));
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
@@ -878,7 +982,7 @@
assertFalse(instance.isForceAllAppsStandbyEnabled());
// Setting/experiment for all app standby for small battery is enabled
- Global.putInt(mMockContentResolver, Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 1);
+ mGlobalSettings.put(Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 1);
instance.mFlagsObserver.onChange(true,
Global.getUriFor(Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED));
assertTrue(instance.isForceAllAppsStandbyEnabled());
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 96bf49b..10253c5 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -30,6 +30,7 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.spy;
+import com.android.server.wm.DisplayWindowController;
import org.mockito.invocation.InvocationOnMock;
import android.app.IApplicationThread;
@@ -345,7 +346,7 @@
}
}
- private static class TestActivityDisplay extends ActivityDisplay {
+ protected static class TestActivityDisplay extends ActivityDisplay {
private final ActivityStackSupervisor mSupervisor;
TestActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
@@ -374,6 +375,11 @@
this, stackId, mSupervisor, windowingMode, activityType, onTop);
}
}
+
+ @Override
+ protected DisplayWindowController createWindowContainerController() {
+ return mock(DisplayWindowController.class);
+ }
}
private static WindowManagerService prepareMockWindowManager() {
diff --git a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
index d2ae22b..1cbb399 100644
--- a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
@@ -90,7 +90,6 @@
@Mock private IStatusBarService mStatusBarService;
@Mock private WindowManagerService mWindowManager;
@Mock private LockPatternUtils mLockPatternUtils;
- @Mock private LockTaskNotify mLockTaskNotify;
@Mock private StatusBarManagerInternal mStatusBarManagerInternal;
@Mock private TelecomManager mTelecomManager;
@Mock private RecentTasks mRecentTasks;
@@ -123,7 +122,6 @@
mLockTaskController.mDevicePolicyManager = mDevicePolicyManager;
mLockTaskController.mTelecomManager = mTelecomManager;
mLockTaskController.mLockPatternUtils = mLockPatternUtils;
- mLockTaskController.mLockTaskNotify = mLockTaskNotify;
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal);
@@ -208,7 +206,7 @@
// THEN lock task mode should be started
verifyLockTaskStarted(STATUS_BAR_MASK_PINNED, DISABLE2_NONE);
// THEN screen pinning toast should be shown
- verify(mLockTaskNotify).showPinningStartToast();
+ verify(mStatusBarService).showPinningEnterExitToast(true /* entering */);
}
@Test
@@ -377,7 +375,7 @@
// THEN the keyguard should be shown
verify(mLockPatternUtils).requireCredentialEntry(UserHandle.USER_ALL);
// THEN screen pinning toast should be shown
- verify(mLockTaskNotify).showPinningExitToast();
+ verify(mStatusBarService).showPinningEnterExitToast(false /* entering */);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index 5a21102..24566fc 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -573,7 +573,8 @@
assertSecurityException(expectCallable, () -> mService.getTaskDescription(0));
assertSecurityException(expectCallable, () -> mService.cancelTaskWindowTransition(0));
assertSecurityException(expectCallable, () -> mService.startRecentsActivity(null, null,
- null, 0));
+ null));
+ assertSecurityException(expectCallable, () -> mService.cancelRecentsAnimation());
}
private void testGetTasksApis(boolean expectCallable) {
@@ -676,8 +677,8 @@
@Override
public void initialize() {
super.initialize();
- mDisplay = new ActivityDisplay(this, DEFAULT_DISPLAY);
- mOtherDisplay = new ActivityDisplay(this, DEFAULT_DISPLAY);
+ mDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
+ mOtherDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
attachDisplay(mOtherDisplay);
attachDisplay(mDisplay);
}
diff --git a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
index fc75628..c6ce7e1 100644
--- a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
@@ -68,7 +68,7 @@
// Create a number of stacks with tasks (of incrementing active time)
final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
final SparseArray<ActivityDisplay> displays = new SparseArray<>();
- final ActivityDisplay display = new ActivityDisplay(supervisor, DEFAULT_DISPLAY);
+ final ActivityDisplay display = new TestActivityDisplay(supervisor, DEFAULT_DISPLAY);
displays.put(DEFAULT_DISPLAY, display);
final int numStacks = 2;
diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
index 5786095..bbd999b 100644
--- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
@@ -82,7 +82,7 @@
};
private final int NON_USER_SYSTEM = UserHandle.USER_SYSTEM + 1;
- @Mock private RefactoredBackupManagerService mBackupManagerServiceMock;
+ @Mock private BackupManagerService mBackupManagerServiceMock;
@Mock private Context mContextMock;
@Mock private File mSuppressFileMock;
@Mock private File mSuppressFileParentMock;
@@ -101,7 +101,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- TrampolineTestable.sRefactoredBackupManagerServiceMock = mBackupManagerServiceMock;
+ TrampolineTestable.sBackupManagerServiceMock = mBackupManagerServiceMock;
TrampolineTestable.sSuppressFile = mSuppressFileMock;
TrampolineTestable.sCallingUid = Process.SYSTEM_UID;
TrampolineTestable.sBackupDisabled = false;
@@ -863,7 +863,7 @@
static boolean sBackupDisabled = false;
static File sSuppressFile = null;
static int sCallingUid = -1;
- static RefactoredBackupManagerService sRefactoredBackupManagerServiceMock = null;
+ static BackupManagerService sBackupManagerServiceMock = null;
private int mCreateServiceCallsCount = 0;
TrampolineTestable(Context context) {
@@ -886,9 +886,9 @@
}
@Override
- protected BackupManagerServiceInterface createRefactoredBackupManagerService() {
+ protected BackupManagerServiceInterface createBackupManagerService() {
mCreateServiceCallsCount++;
- return sRefactoredBackupManagerServiceMock;
+ return sBackupManagerServiceMock;
}
int getCreateServiceCallsCount() {
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
index ed26296..86c83d6 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
@@ -27,7 +27,7 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.testutils.PackageManagerStub;
import org.junit.Test;
@@ -82,7 +82,7 @@
applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
applicationInfo.uid = Process.SYSTEM_UID;
applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
- applicationInfo.packageName = RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+ applicationInfo.packageName = BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
mPackageManagerStub);
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
index 6b25d12..0cdf04b 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
@@ -47,7 +47,7 @@
import com.android.frameworks.servicestests.R;
import com.android.server.backup.FileMetadata;
-import com.android.server.backup.RefactoredBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.restore.PerformAdbRestoreTask;
import com.android.server.backup.restore.RestorePolicy;
import com.android.server.backup.testutils.PackageManagerStub;
@@ -143,8 +143,7 @@
assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
- assertThat(fileMetadata.path).isEqualTo(
- RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME);
+ assertThat(fileMetadata.path).isEqualTo(BackupManagerService.BACKUP_MANIFEST_FILENAME);
tarBackupReader.skipTarPadding(fileMetadata.size);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 6b87ea9..00a85a5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2160,6 +2160,51 @@
() -> dpm.getMeteredDataDisabled(admin1));
}
+ public void testGetMeteredDataDisabledForUser() throws Exception {
+ setAsProfileOwner(admin1);
+
+ // Setup
+ final ArrayList<String> emptyList = new ArrayList<>();
+ final ArrayList<String> pkgsToRestrict = new ArrayList<>();
+ final String package1 = "com.example.one";
+ final String package2 = "com.example.two";
+ final String package3 = "com.example.three";
+ pkgsToRestrict.add(package1);
+ pkgsToRestrict.add(package2);
+ setupPackageInPackageManager(package1, DpmMockContext.CALLER_USER_HANDLE, 123, 0);
+ setupPackageInPackageManager(package2, DpmMockContext.CALLER_USER_HANDLE, 456, 0);
+ List<String> excludedPkgs = dpm.setMeteredDataDisabled(admin1, pkgsToRestrict);
+
+ // Verify
+ assertEquals(emptyList, excludedPkgs);
+ mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
+ assertTrue(package1 + "should be restricted",
+ dpm.isMeteredDataDisabledForUser(admin1, package1,
+ DpmMockContext.CALLER_USER_HANDLE));
+ assertTrue(package2 + "should be restricted",
+ dpm.isMeteredDataDisabledForUser(admin1, package2,
+ DpmMockContext.CALLER_USER_HANDLE));
+ assertFalse(package3 + "should not be restricted",
+ dpm.isMeteredDataDisabledForUser(admin1, package3,
+ DpmMockContext.CALLER_USER_HANDLE));
+ }
+
+ public void testGetMeteredDataDisabledForUser_nonSystemUidCaller() throws Exception {
+ setAsProfileOwner(admin1);
+ assertExpectException(SecurityException.class,
+ /* messageRegex= */ "Only the system can query restricted pkgs",
+ () -> dpm.isMeteredDataDisabledForUser(
+ admin1, "com.example.one", DpmMockContext.CALLER_USER_HANDLE));
+ dpm.clearProfileOwner(admin1);
+
+ setDeviceOwner();
+ assertExpectException(SecurityException.class,
+ /* messageRegex= */ "Only the system can query restricted pkgs",
+ () -> dpm.isMeteredDataDisabledForUser(
+ admin1, "com.example.one", DpmMockContext.CALLER_USER_HANDLE));
+ clearDeviceOwner();
+ }
+
public void testCreateAdminSupportIntent() throws Exception {
// Setup device owner.
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
new file mode 100644
index 0000000..98c428d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
@@ -0,0 +1,371 @@
+/*
+ * 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.server.devicepolicy;
+
+import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE;
+import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG;
+import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_DUPLICATE_OR_OVERLAP;
+import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE;
+import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_NEW_FREEZE_PERIOD_TOO_LONG;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.admin.FreezeInterval;
+import android.app.admin.SystemUpdatePolicy;
+import android.os.Parcel;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Pair;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit tests for {@link android.app.admin.SystemUpdatePolicy}.
+ * Throughout this test, we use "MM-DD" format to denote dates without year.
+ *
+ * atest com.android.server.devicepolicy.SystemUpdatePolicyTest
+ * runtest -c com.android.server.devicepolicy.SystemUpdatePolicyTest frameworks-services
+ */
+@RunWith(AndroidJUnit4.class)
+public final class SystemUpdatePolicyTest {
+
+ private static final int DUPLICATE_OR_OVERLAP = ERROR_DUPLICATE_OR_OVERLAP;
+ private static final int TOO_LONG = ERROR_NEW_FREEZE_PERIOD_TOO_LONG;
+ private static final int TOO_CLOSE = ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE;
+ private static final int COMBINED_TOO_LONG = ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG;
+ private static final int COMBINED_TOO_CLOSE = ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE;
+
+ @Test
+ public void testSimplePeriod() throws Exception {
+ testFreezePeriodsSucceeds("01-01", "01-02");
+ testFreezePeriodsSucceeds("01-31", "01-31");
+ testFreezePeriodsSucceeds("11-01", "01-15");
+ testFreezePeriodsSucceeds("02-01", "02-29"); // Leap year
+ testFreezePeriodsSucceeds("02-01", "03-01");
+ testFreezePeriodsSucceeds("12-01", "01-30"); // Wrapped Period
+ testFreezePeriodsSucceeds("11-02", "01-30", "04-01", "04-30"); // Wrapped Period
+ }
+
+ @Test
+ public void testCanonicalizationValidation() throws Exception {
+ testFreezePeriodsSucceeds("03-01", "03-31", "09-01", "09-30");
+ testFreezePeriodsSucceeds("06-01", "07-01", "09-01", "09-30");
+ testFreezePeriodsSucceeds("10-01", "10-31", "12-31", "01-31");
+ testFreezePeriodsSucceeds("01-01", "01-30", "04-01", "04-30");
+ testFreezePeriodsSucceeds("01-01", "02-28", "05-01", "06-30", "09-01", "10-31");
+
+ // One interval fully covers the other
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "03-01", "03-31", "03-15", "03-31");
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "03-01", "03-31", "03-15", "03-16");
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "11-15", "01-31", "12-01", "12-31");
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "12-01", "01-31", "01-01", "01-15");
+
+ // Partial overlap
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "03-01", "03-31", "03-15", "01-01");
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "11-15", "01-31", "12-01", "02-28");
+
+ // No gap between two intervals
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "01-31", "01-31", "02-01", "02-01");
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "12-01", "12-15", "12-15", "02-01");
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "12-01", "12-15", "12-16", "02-01");
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "12-01", "01-15", "01-15", "02-01");
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "12-01", "01-15", "01-16", "02-01");
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "01-01", "01-30", "12-01", "12-31");
+ testFreezePeriodsFails(DUPLICATE_OR_OVERLAP, "12-01", "12-31", "04-01", "04-01",
+ "01-01", "01-30");
+ }
+
+ @Test
+ public void testLengthValidation() throws Exception {
+ testFreezePeriodsSucceeds("03-01", "03-31");
+ testFreezePeriodsSucceeds("03-03", "03-03", "12-31", "01-01");
+ testFreezePeriodsSucceeds("01-01", "03-31", "06-01", "08-29");
+ // entire year
+ testFreezePeriodsFails(TOO_LONG, "01-01", "12-31");
+ // long period spanning across year end
+ testFreezePeriodsSucceeds("11-01", "01-29");
+ testFreezePeriodsFails(TOO_LONG, "11-01", "01-30");
+ // Leap year handling
+ testFreezePeriodsSucceeds("12-01", "02-28");
+ testFreezePeriodsSucceeds("12-01", "02-29");
+ testFreezePeriodsFails(TOO_LONG, "12-01", "03-01");
+ // Regular long period
+ testFreezePeriodsSucceeds("01-01", "03-31", "06-01", "08-29");
+ testFreezePeriodsFails(TOO_LONG, "01-01", "03-31", "06-01", "08-30");
+ }
+
+ @Test
+ public void testSeparationValidation() throws Exception {
+ testFreezePeriodsSucceeds("01-01", "03-31", "06-01", "08-29");
+ testFreezePeriodsFails(TOO_CLOSE, "01-01", "01-01", "01-03", "01-03");
+ testFreezePeriodsFails(TOO_CLOSE, "03-01", "03-31", "05-01", "05-31");
+ // Short interval spans across end of year
+ testFreezePeriodsSucceeds("01-31", "03-01", "11-01", "12-01");
+ testFreezePeriodsFails(TOO_CLOSE, "01-30", "03-01", "11-01", "12-01");
+ // Short separation is after wrapped period
+ testFreezePeriodsSucceeds("03-03", "03-31", "12-31", "01-01");
+ testFreezePeriodsFails(TOO_CLOSE, "03-02", "03-31", "12-31", "01-01");
+ // Short separation including Feb 29
+ testFreezePeriodsSucceeds("12-01", "01-15", "03-17", "04-01");
+ testFreezePeriodsFails(TOO_CLOSE, "12-01", "01-15", "03-16", "04-01");
+ // Short separation including Feb 29
+ testFreezePeriodsSucceeds("01-01", "02-28", "04-30", "06-01");
+ testFreezePeriodsSucceeds("01-01", "02-29", "04-30", "06-01");
+ testFreezePeriodsFails(TOO_CLOSE, "01-01", "03-01", "04-30", "06-01");
+ }
+
+ @Test
+ public void testValidateTotalLengthWithPreviousPeriods() throws Exception {
+ testPrevFreezePeriodSucceeds("2018-01-19", "2018-01-19", /* now */"2018-01-19",
+ "07-01", "07-31", "10-01", "11-30");
+ testPrevFreezePeriodSucceeds("2018-01-01", "2018-01-19", /* now */"2018-01-19",
+ "01-01", "03-30");
+ testPrevFreezePeriodSucceeds("2018-01-01", "2018-02-01", /* now */"2018-02-01",
+ "11-01", "12-31");
+
+ testPrevFreezePeriodSucceeds("2017-11-01", "2018-01-02", /* now */"2018-01-02",
+ "01-01", "01-29");
+ testPrevFreezePeriodFails(COMBINED_TOO_LONG, "2017-11-01", "2018-01-02", "2018-01-02",
+ "01-01", "01-30");
+ testPrevFreezePeriodSucceeds("2017-11-01", "2018-01-02", /* now */"2018-01-01",
+ "01-02", "01-29");
+ testPrevFreezePeriodFails(COMBINED_TOO_LONG, "2017-11-01", "2018-01-02", "2018-01-01",
+ "01-02", "01-30");
+
+ testPrevFreezePeriodSucceeds("2017-11-01", "2017-12-01", /* now */"2017-12-01",
+ "11-15", "01-29");
+ testPrevFreezePeriodFails(COMBINED_TOO_LONG, "2017-11-01", "2017-12-01", "2017-12-01",
+ "11-15", "01-30");
+
+ testPrevFreezePeriodSucceeds("2017-11-01", "2018-01-01", /* now */"2018-01-01",
+ "11-15", "01-29");
+ testPrevFreezePeriodFails(COMBINED_TOO_LONG, "2017-11-01", "2018-01-01", "2018-01-01",
+ "11-15", "01-30");
+
+ testPrevFreezePeriodSucceeds("2018-03-01", "2018-03-31", /* now */"2018-03-31",
+ "04-01", "05-29");
+ testPrevFreezePeriodFails(COMBINED_TOO_LONG, "2018-03-01", "2018-03-31", "2018-03-31",
+ "04-01", "05-30");
+
+ // Leap year handing
+ testPrevFreezePeriodSucceeds("2017-12-01", "2018-01-02", /* now */"2018-01-02",
+ "01-01", "02-28");
+ testPrevFreezePeriodSucceeds("2017-12-01", "2018-01-02", /* now */"2018-01-02",
+ "01-01", "02-29");
+ testPrevFreezePeriodFails(COMBINED_TOO_LONG, "2017-12-01", "2018-01-02", "2018-01-02",
+ "01-01", "03-01");
+
+ testPrevFreezePeriodSucceeds("2016-01-01", "2016-02-28", /* now */"2016-02-28",
+ "02-01", "03-31");
+ testPrevFreezePeriodSucceeds("2016-01-01", "2016-02-28", /* now */"2016-02-29",
+ "02-01", "03-31");
+ testPrevFreezePeriodFails(COMBINED_TOO_LONG, "2016-01-01", "2016-02-28", "2016-02-29",
+ "02-01", "04-01");
+
+ }
+
+ @Test
+ public void testValidateSeparationWithPreviousPeriods() throws Exception {
+ testPrevFreezePeriodSucceeds("2018-01-01", "2018-01-02", /* now */"2018-03-04",
+ "01-01", "03-30");
+ testPrevFreezePeriodSucceeds("2018-01-01", "2018-01-02", /* now */"2018-01-19",
+ "04-01", "06-29");
+ testPrevFreezePeriodSucceeds("2017-01-01", "2017-03-30", /* now */"2018-12-01",
+ "01-01", "03-30");
+
+ testPrevFreezePeriodSucceeds("2018-01-01", "2018-02-01", "2018-02-01",
+ "04-03", "06-01");
+ testPrevFreezePeriodFails(COMBINED_TOO_CLOSE, "2018-01-01", "2018-02-01", "2018-02-01",
+ "04-02", "06-01");
+
+ testPrevFreezePeriodSucceeds("2018-04-01", "2018-06-01", "2018-08-01",
+ "07-01", "08-30");
+ testPrevFreezePeriodFails(COMBINED_TOO_CLOSE, "2018-04-01", "2018-06-01", "2018-07-30",
+ "07-01", "08-30");
+
+
+ testPrevFreezePeriodSucceeds("2018-03-01", "2018-04-01", "2018-06-01",
+ "05-01", "07-01");
+ testPrevFreezePeriodFails(COMBINED_TOO_CLOSE, "2018-03-01", "2018-04-01", "2018-05-31",
+ "05-01", "07-01");
+ }
+
+ @Test
+ public void testDistanceWithoutLeapYear() {
+ assertEquals(364, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2016, 12, 31), LocalDate.of(2016, 1, 1)));
+ assertEquals(365, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2017, 1, 1), LocalDate.of(2016, 1, 1)));
+ assertEquals(365, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2017, 2, 28), LocalDate.of(2016, 2, 29)));
+ assertEquals(-365, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2016, 1, 1), LocalDate.of(2017, 1, 1)));
+ assertEquals(1, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 29)));
+ assertEquals(1, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 28)));
+ assertEquals(0, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2016, 2, 29), LocalDate.of(2016, 2, 28)));
+ assertEquals(0, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2016, 2, 28), LocalDate.of(2016, 2, 28)));
+
+ assertEquals(59, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2016, 3, 1), LocalDate.of(2016, 1, 1)));
+ assertEquals(59, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2017, 3, 1), LocalDate.of(2017, 1, 1)));
+
+ assertEquals(365 * 40, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2040, 1, 1), LocalDate.of(2000, 1, 1)));
+
+ assertEquals(365 * 2, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2019, 3, 1), LocalDate.of(2017, 3, 1)));
+ assertEquals(365 * 2, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2018, 3, 1), LocalDate.of(2016, 3, 1)));
+ assertEquals(365 * 2, FreezeInterval.distanceWithoutLeapYear(
+ LocalDate.of(2017, 3, 1), LocalDate.of(2015, 3, 1)));
+
+ }
+
+ private void testFreezePeriodsSucceeds(String...dates) throws Exception {
+ SystemUpdatePolicy p = SystemUpdatePolicy.createPostponeInstallPolicy();
+ setFreezePeriods(p, dates);
+ }
+
+ private void testFreezePeriodsFails(int expectedError, String... dates) throws Exception {
+ SystemUpdatePolicy p = SystemUpdatePolicy.createPostponeInstallPolicy();
+ try {
+ setFreezePeriods(p, dates);
+ fail("Invalid periods (" + expectedError + ") not flagged: " + String.join(" ", dates));
+ } catch (SystemUpdatePolicy.ValidationFailedException e) {
+ assertTrue("Exception not expected: " + e.getMessage(),
+ e.getErrorCode() == expectedError);
+ }
+ }
+
+ private void testPrevFreezePeriodSucceeds(String prevStart, String prevEnd, String now,
+ String... dates) throws Exception {
+ createPrevFreezePeriod(prevStart, prevEnd, now, dates);
+ }
+
+ private void testPrevFreezePeriodFails(int expectedError, String prevStart, String prevEnd,
+ String now, String... dates) throws Exception {
+ try {
+ createPrevFreezePeriod(prevStart, prevEnd, now, dates);
+ fail("Invalid period (" + expectedError + ") not flagged: " + String.join(" ", dates));
+ } catch (SystemUpdatePolicy.ValidationFailedException e) {
+ assertTrue("Exception not expected: " + e.getMessage(),
+ e.getErrorCode() == expectedError);
+ }
+ }
+
+ private void createPrevFreezePeriod(String prevStart, String prevEnd, String now,
+ String... dates) throws Exception {
+ SystemUpdatePolicy p = SystemUpdatePolicy.createPostponeInstallPolicy();
+ setFreezePeriods(p, dates);
+ p.validateAgainstPreviousFreezePeriod(parseDate(prevStart), parseDate(prevEnd),
+ parseDate(now));
+ }
+
+ // "MM-DD" format for date
+ private void setFreezePeriods(SystemUpdatePolicy policy, String... dates) throws Exception {
+ List<Pair<Integer, Integer>> periods = new ArrayList<>();
+ LocalDate lastDate = null;
+ for (String date : dates) {
+ LocalDate currentDate = parseDate(date);
+ if (lastDate != null) {
+ periods.add(new Pair<>(lastDate.getDayOfYear(), currentDate.getDayOfYear()));
+ lastDate = null;
+ } else {
+ lastDate = currentDate;
+ }
+ }
+ policy.setFreezePeriods(periods);
+ testSerialization(policy, periods);
+ }
+
+ private void testSerialization(SystemUpdatePolicy policy,
+ List<Pair<Integer, Integer>> expectedPeriods) throws Exception {
+ // Test parcel / unparcel
+ Parcel parcel = Parcel.obtain();
+ policy.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ SystemUpdatePolicy q = SystemUpdatePolicy.CREATOR.createFromParcel(parcel);
+ checkFreezePeriods(q, expectedPeriods);
+ parcel.recycle();
+
+ // Test XML serialization
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ final XmlSerializer outXml = new FastXmlSerializer();
+ outXml.setOutput(outStream, StandardCharsets.UTF_8.name());
+ outXml.startDocument(null, true);
+ outXml.startTag(null, "ota");
+ policy.saveToXml(outXml);
+ outXml.endTag(null, "ota");
+ outXml.endDocument();
+ outXml.flush();
+
+ ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new InputStreamReader(inStream));
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ checkFreezePeriods(SystemUpdatePolicy.restoreFromXml(parser), expectedPeriods);
+ }
+
+ private void checkFreezePeriods(SystemUpdatePolicy policy,
+ List<Pair<Integer, Integer>> expectedPeriods) {
+ int i = 0;
+ for (Pair<Integer, Integer> period : policy.getFreezePeriods()) {
+ assertEquals(expectedPeriods.get(i).first, period.first);
+ assertEquals(expectedPeriods.get(i).second, period.second);
+ i++;
+ }
+ }
+
+ private LocalDate parseDate(String date) {
+ // Use leap year when parsing date string to handle "02-29", but force round down
+ // to Feb 28th by overriding the year to non-leap year.
+ final int year;
+ boolean monthDateOnly = false;
+ if (date.length() == 5) {
+ year = 2000;
+ monthDateOnly = true;
+ } else {
+ year = Integer.parseInt(date.substring(0, 4));
+ date = date.substring(5);
+ }
+ LocalDate result = LocalDate.of(year, Integer.parseInt(date.substring(0, 2)),
+ Integer.parseInt(date.substring(3, 5)));
+ if (monthDateOnly) {
+ return result.withYear(2001);
+ } else {
+ return result;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
new file mode 100644
index 0000000..83bd9fc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.server.job;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.job.JobInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManagerInternal;
+import android.os.Build;
+import android.os.UserHandle;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.server.LocalServices;
+import com.android.server.job.controllers.JobStatus;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class JobSetTest {
+ private static final String TAG = JobSetTest.class.getSimpleName();
+ private static final int SECONDARY_USER_ID_1 = 12;
+ private static final int SECONDARY_USER_ID_2 = 13;
+
+ private Context mContext;
+ private ComponentName mComponent;
+ private JobStore.JobSet mJobSet;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mComponent = new ComponentName(mContext, JobStoreTest.class);
+ mJobSet = new JobStore.JobSet();
+ final PackageManagerInternal pm = mock(PackageManagerInternal.class);
+ when(pm.getPackageTargetSdkVersion(anyString()))
+ .thenReturn(Build.VERSION_CODES.CUR_DEVELOPMENT);
+ LocalServices.addService(PackageManagerInternal.class, pm);
+ assumeFalse("Test cannot run in user " + mContext.getUserId(),
+ mContext.getUserId() == SECONDARY_USER_ID_1
+ || mContext.getUserId() == SECONDARY_USER_ID_2);
+ }
+
+ private JobStatus getJobStatusWithCallinUid(int jobId, int callingUid) {
+ final JobInfo jobInfo = new JobInfo.Builder(jobId, mComponent)
+ .setPeriodic(10)
+ .setRequiresCharging(true)
+ .build();
+ return JobStatus.createFromJobInfo(jobInfo, callingUid, mContext.getPackageName(),
+ mContext.getUserId(), "Test");
+ }
+
+ @Test
+ public void testBothMapsHaveSameJobs() {
+ final int callingUid1 = UserHandle.getUid(SECONDARY_USER_ID_1, 1);
+ final int callingUid2 = UserHandle.getUid(SECONDARY_USER_ID_2, 1);
+ final JobStatus testJob1 = getJobStatusWithCallinUid(1, callingUid1);
+ final JobStatus testJob2 = getJobStatusWithCallinUid(2, callingUid2);
+ mJobSet.add(testJob1);
+ mJobSet.add(testJob2);
+ for (int i = 11; i <= 20; i++) {
+ mJobSet.add(getJobStatusWithCallinUid(i, (i%2 == 0) ? callingUid2 : callingUid1));
+ }
+ assertHaveSameJobs(mJobSet.mJobsPerSourceUid, mJobSet.mJobs);
+ mJobSet.remove(testJob1);
+ mJobSet.remove(testJob2);
+ assertHaveSameJobs(mJobSet.mJobsPerSourceUid, mJobSet.mJobs);
+ mJobSet.removeJobsOfNonUsers(new int[] {mContext.getUserId(), SECONDARY_USER_ID_1});
+ assertHaveSameJobs(mJobSet.mJobsPerSourceUid, mJobSet.mJobs);
+ mJobSet.removeJobsOfNonUsers(new int[] {mContext.getUserId()});
+ assertTrue("mJobs should be empty", mJobSet.mJobs.size() == 0);
+ assertTrue("mJobsPerSourceUid should be empty", mJobSet.mJobsPerSourceUid.size() == 0);
+ }
+
+ private static void assertHaveSameJobs(SparseArray<ArraySet<JobStatus>> map1,
+ SparseArray<ArraySet<JobStatus>> map2) {
+ final ArraySet<JobStatus> set1 = new ArraySet<>();
+ final ArraySet<JobStatus> set2 = new ArraySet<>();
+ int size1 = 0;
+ for (int i = 0; i < map1.size(); i++) {
+ final ArraySet<JobStatus> jobs = map1.valueAt(i);
+ if (jobs == null) return;
+ size1 += jobs.size();
+ set1.addAll(jobs);
+ }
+ for (int i = 0; i < map2.size(); i++) {
+ final ArraySet<JobStatus> jobs = map2.valueAt(i);
+ if (jobs == null) return;
+ size1 -= jobs.size();
+ set2.addAll(jobs);
+ }
+ if (size1 != 0 || !set1.equals(set2)) {
+ dump("map1", map1);
+ dump("map2", map2);
+ fail("Both maps have different sets of jobs");
+ }
+ }
+
+ private static void dump(String prefix, SparseArray<ArraySet<JobStatus>> jobMap) {
+ final StringBuilder str = new StringBuilder();
+ for (int i = 0; i < jobMap.size(); i++) {
+ final ArraySet<JobStatus> jobs = jobMap.valueAt(i);
+ if (jobs == null) return;
+ str.append("[Key: " + jobMap.keyAt(i) + ", Value: {");
+ for (int j = 0; j < jobs.size(); j++) {
+ final JobStatus job = jobs.valueAt(j);
+ str.append("(s=" + job.getSourceUid() + ", c=" + job.getUid() + "), ");
+ }
+ str.append("}], ");
+ }
+ Log.d(TAG, prefix + ": " + str.toString());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 6a3a260..ce5ee13 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -121,7 +121,7 @@
TEST_CREDENTIAL_TYPE,
TEST_CREDENTIAL,
/*credentialUpdated=*/ false,
- () -> mPlatformKeyManager);
+ mPlatformKeyManager);
mWrappingKey = generateAndroidKeyStoreKey();
mEncryptKey = new PlatformEncryptionKey(TEST_GENERATION_ID, mWrappingKey);
@@ -327,8 +327,7 @@
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
- SecretKey applicationKey =
- addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
mKeySyncTask.run();
@@ -343,6 +342,26 @@
}
@Test
+ public void run_recreatesMissingSnapshot() throws Exception {
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+
+ mKeySyncTask.run();
+
+ KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(1); // default value;
+
+ mRecoverySnapshotStorage.remove(TEST_RECOVERY_AGENT_UID); // corrupt snapshot.
+
+ mKeySyncTask.run();
+
+ keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(1); // Same version
+ }
+
+ @Test
public void run_setsCorrectTypeForPassword() throws Exception {
mKeySyncTask = new KeySyncTask(
mRecoverableKeyStoreDb,
@@ -352,7 +371,7 @@
CREDENTIAL_TYPE_PASSWORD,
"password",
/*credentialUpdated=*/ false,
- () -> mPlatformKeyManager);
+ mPlatformKeyManager);
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
@@ -378,7 +397,7 @@
CREDENTIAL_TYPE_PASSWORD,
/*credential=*/ "1234",
/*credentialUpdated=*/ false,
- () -> mPlatformKeyManager);
+ mPlatformKeyManager);
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
@@ -405,7 +424,7 @@
CREDENTIAL_TYPE_PATTERN,
"12345",
/*credentialUpdated=*/ false,
- () -> mPlatformKeyManager);
+ mPlatformKeyManager);
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
index 6fc9e08..f9ffccd 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
@@ -252,6 +252,10 @@
@Test
public void getDecryptKey_getsDecryptKeyWithCorrectAlias() throws Exception {
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/1/decrypt")).thenReturn(true);
+
mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).getKey(
@@ -265,6 +269,13 @@
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"),
any());
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/1/encrypt")).thenReturn(true);
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/2/encrypt")).thenReturn(true);
+
mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).getKey(
@@ -282,11 +293,18 @@
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
any());
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/1/decrypt")).thenReturn(false); // was removed.
+
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/2/decrypt")).thenReturn(true); // new version is available
+
mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
- verify(mKeyStoreProxy).getKey(
- eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
- any());
+ verify(mKeyStoreProxy).containsAlias(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"));
// Attempt to get regenerated key.
verify(mKeyStoreProxy).getKey(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"),
@@ -294,7 +312,31 @@
}
@Test
- public void getEncryptKey_getsDecryptKeyWithCorrectAlias() throws Exception {
+ public void getEncryptKey_generatesNewKeyIfOldWasRemoved() throws Exception {
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/1/encrypt")).thenReturn(false); // was removed.
+
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/2/encrypt")).thenReturn(true); // new version is available
+
+ mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
+
+ verify(mKeyStoreProxy).containsAlias(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"));
+ // Attempt to get regenerated key.
+ verify(mKeyStoreProxy).getKey(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/encrypt"),
+ any());
+ }
+
+ @Test
+ public void getEncryptKey_getsEndryptKeyWithCorrectAlias() throws Exception {
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/1/encrypt")).thenReturn(true);
+
mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).getKey(
@@ -312,6 +354,26 @@
}
@Test
+ public void regenerate_deletesOldKeysFromKeystore() throws Exception {
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
+
+ mPlatformKeyManager.regenerate(USER_ID_FIXTURE);
+
+ verify(mKeyStoreProxy).deleteEntry(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"));
+ verify(mKeyStoreProxy).deleteEntry(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"));
+
+ mPlatformKeyManager.regenerate(USER_ID_FIXTURE);
+
+ // Removes second generation keys.
+ verify(mKeyStoreProxy).deleteEntry(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/encrypt"));
+ verify(mKeyStoreProxy).deleteEntry(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"));
+ }
+
+ @Test
public void regenerate_generatesANewEncryptKeyWithTheCorrectAlias() throws Exception {
mPlatformKeyManager.init(USER_ID_FIXTURE);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/PersistentKeyChainSnapshotTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/PersistentKeyChainSnapshotTest.java
new file mode 100644
index 0000000..aad5295
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/PersistentKeyChainSnapshotTest.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.locksettings.recoverablekeystore.storage;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.testng.Assert.assertThrows;
+
+import android.security.keystore.recovery.KeyDerivationParams;
+import android.security.keystore.recovery.WrappedApplicationKey;
+import android.security.keystore.recovery.KeyChainSnapshot;
+import android.security.keystore.recovery.KeyChainProtectionParams;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PersistentKeyChainSnapshotTest {
+
+ private static final String ALIAS = "some_key";
+ private static final String ALIAS2 = "another_key";
+ private static final byte[] RECOVERY_KEY_MATERIAL = "recovery_key_data"
+ .getBytes(StandardCharsets.UTF_8);
+ private static final byte[] KEY_MATERIAL = "app_key_data".getBytes(StandardCharsets.UTF_8);
+ private static final byte[] PUBLIC_KEY = "public_key_data".getBytes(StandardCharsets.UTF_8);
+ private static final byte[] ACCOUNT = "test_account".getBytes(StandardCharsets.UTF_8);
+ private static final byte[] SALT = "salt".getBytes(StandardCharsets.UTF_8);
+ private static final int SNAPSHOT_VERSION = 2;
+ private static final int MAX_ATTEMPTS = 10;
+ private static final long COUNTER_ID = 123456789L;
+ private static final byte[] SERVER_PARAMS = "server_params".getBytes(StandardCharsets.UTF_8);
+ private static final byte[] ZERO_BYTES = new byte[0];
+ private static final byte[] ONE_BYTE = new byte[]{(byte) 11};
+ private static final byte[] TWO_BYTES = new byte[]{(byte) 222,(byte) 222};
+
+ @Test
+ public void testWriteInt() throws Exception {
+ PersistentKeyChainSnapshot writer = new PersistentKeyChainSnapshot();
+ writer.initWriter();
+ writer.writeInt(Integer.MIN_VALUE);
+ writer.writeInt(Integer.MAX_VALUE);
+ byte[] result = writer.getOutput();
+
+ PersistentKeyChainSnapshot reader = new PersistentKeyChainSnapshot();
+ reader.initReader(result);
+ assertThat(reader.readInt()).isEqualTo(Integer.MIN_VALUE);
+ assertThat(reader.readInt()).isEqualTo(Integer.MAX_VALUE);
+
+ assertThrows(
+ IOException.class,
+ () -> reader.readInt());
+ }
+
+ @Test
+ public void testWriteLong() throws Exception {
+ PersistentKeyChainSnapshot writer = new PersistentKeyChainSnapshot();
+ writer.initWriter();
+ writer.writeLong(Long.MIN_VALUE);
+ writer.writeLong(Long.MAX_VALUE);
+ byte[] result = writer.getOutput();
+
+ PersistentKeyChainSnapshot reader = new PersistentKeyChainSnapshot();
+ reader.initReader(result);
+ assertThat(reader.readLong()).isEqualTo(Long.MIN_VALUE);
+ assertThat(reader.readLong()).isEqualTo(Long.MAX_VALUE);
+
+ assertThrows(
+ IOException.class,
+ () -> reader.readLong());
+ }
+
+ @Test
+ public void testWriteBytes() throws Exception {
+ PersistentKeyChainSnapshot writer = new PersistentKeyChainSnapshot();
+ writer.initWriter();
+ writer.writeBytes(ZERO_BYTES);
+ writer.writeBytes(ONE_BYTE);
+ writer.writeBytes(TWO_BYTES);
+ byte[] result = writer.getOutput();
+
+ PersistentKeyChainSnapshot reader = new PersistentKeyChainSnapshot();
+ reader.initReader(result);
+ assertThat(reader.readBytes()).isEqualTo(ZERO_BYTES);
+ assertThat(reader.readBytes()).isEqualTo(ONE_BYTE);
+ assertThat(reader.readBytes()).isEqualTo(TWO_BYTES);
+
+ assertThrows(
+ IOException.class,
+ () -> reader.readBytes());
+ }
+
+ @Test
+ public void testReadBytes_returnsNullArrayAsEmpty() throws Exception {
+ PersistentKeyChainSnapshot writer = new PersistentKeyChainSnapshot();
+ writer.initWriter();
+ writer.writeBytes(null);
+ byte[] result = writer.getOutput();
+
+ PersistentKeyChainSnapshot reader = new PersistentKeyChainSnapshot();
+ reader.initReader(result);
+ assertThat(reader.readBytes()).isEqualTo(new byte[]{}); // null -> empty array
+ }
+
+ @Test
+ public void testWriteKeyEntry() throws Exception {
+ PersistentKeyChainSnapshot writer = new PersistentKeyChainSnapshot();
+ writer.initWriter();
+ WrappedApplicationKey entry = new WrappedApplicationKey.Builder()
+ .setAlias(ALIAS)
+ .setEncryptedKeyMaterial(KEY_MATERIAL)
+ .setAccount(ACCOUNT)
+ .build();
+ writer.writeKeyEntry(entry);
+
+ byte[] result = writer.getOutput();
+
+ PersistentKeyChainSnapshot reader = new PersistentKeyChainSnapshot();
+ reader.initReader(result);
+
+ WrappedApplicationKey copy = reader.readKeyEntry();
+ assertThat(copy.getAlias()).isEqualTo(ALIAS);
+ assertThat(copy.getEncryptedKeyMaterial()).isEqualTo(KEY_MATERIAL);
+ assertThat(copy.getAccount()).isEqualTo(ACCOUNT);
+
+ assertThrows(
+ IOException.class,
+ () -> reader.readKeyEntry());
+ }
+
+ public void testWriteProtectionParams() throws Exception {
+ PersistentKeyChainSnapshot writer = new PersistentKeyChainSnapshot();
+ writer.initWriter();
+ KeyDerivationParams derivationParams = KeyDerivationParams.createSha256Params(SALT);
+ KeyChainProtectionParams protectionParams = new KeyChainProtectionParams.Builder()
+ .setUserSecretType(1)
+ .setLockScreenUiFormat(2)
+ .setKeyDerivationParams(derivationParams)
+ .build();
+ writer.writeProtectionParams(protectionParams);
+
+ byte[] result = writer.getOutput();
+
+ PersistentKeyChainSnapshot reader = new PersistentKeyChainSnapshot();
+ reader.initReader(result);
+
+ KeyChainProtectionParams copy = reader.readProtectionParams();
+ assertThat(copy.getUserSecretType()).isEqualTo(1);
+ assertThat(copy.getLockScreenUiFormat()).isEqualTo(2);
+ assertThat(copy.getKeyDerivationParams().getSalt()).isEqualTo(SALT);
+
+ assertThrows(
+ IOException.class,
+ () -> reader.readProtectionParams());
+ }
+
+ public void testKeyChainSnapshot() throws Exception {
+ PersistentKeyChainSnapshot writer = new PersistentKeyChainSnapshot();
+ writer.initWriter();
+
+ KeyDerivationParams derivationParams = KeyDerivationParams.createSha256Params(SALT);
+
+ ArrayList<KeyChainProtectionParams> protectionParamsList = new ArrayList<>();
+ protectionParamsList.add(new KeyChainProtectionParams.Builder()
+ .setUserSecretType(1)
+ .setLockScreenUiFormat(2)
+ .setKeyDerivationParams(derivationParams)
+ .build());
+
+ ArrayList<WrappedApplicationKey> appKeysList = new ArrayList<>();
+ appKeysList.add(new WrappedApplicationKey.Builder()
+ .setAlias(ALIAS)
+ .setEncryptedKeyMaterial(KEY_MATERIAL)
+ .setAccount(ACCOUNT)
+ .build());
+
+ KeyChainSnapshot snapshot = new KeyChainSnapshot.Builder()
+ .setSnapshotVersion(SNAPSHOT_VERSION)
+ .setKeyChainProtectionParams(protectionParamsList)
+ .setEncryptedRecoveryKeyBlob(KEY_MATERIAL)
+ .setWrappedApplicationKeys(appKeysList)
+ .setMaxAttempts(MAX_ATTEMPTS)
+ .setCounterId(COUNTER_ID)
+ .setServerParams(SERVER_PARAMS)
+ .setTrustedHardwarePublicKey(PUBLIC_KEY)
+ .build();
+
+ writer.writeKeyChainSnapshot(snapshot);
+
+ byte[] result = writer.getOutput();
+
+ PersistentKeyChainSnapshot reader = new PersistentKeyChainSnapshot();
+ reader.initReader(result);
+
+ KeyChainSnapshot copy = reader.readKeyChainSnapshot();
+ assertThat(copy.getSnapshotVersion()).isEqualTo(SNAPSHOT_VERSION);
+ assertThat(copy.getKeyChainProtectionParams()).hasSize(2);
+ assertThat(copy.getKeyChainProtectionParams().get(0).getUserSecretType()).isEqualTo(1);
+ assertThat(copy.getKeyChainProtectionParams().get(1).getUserSecretType()).isEqualTo(2);
+ assertThat(copy.getEncryptedRecoveryKeyBlob()).isEqualTo(RECOVERY_KEY_MATERIAL);
+ assertThat(copy.getWrappedApplicationKeys()).hasSize(2);
+ assertThat(copy.getWrappedApplicationKeys().get(0).getAlias()).isEqualTo(ALIAS);
+ assertThat(copy.getWrappedApplicationKeys().get(1).getAlias()).isEqualTo(ALIAS2);
+ assertThat(copy.getMaxAttempts()).isEqualTo(MAX_ATTEMPTS);
+ assertThat(copy.getCounterId()).isEqualTo(COUNTER_ID);
+ assertThat(copy.getServerParams()).isEqualTo(SERVER_PARAMS);
+ assertThat(copy.getTrustedHardwarePublicKey()).isEqualTo(PUBLIC_KEY);
+
+ assertThrows(
+ IOException.class,
+ () -> reader.readKeyChainSnapshot());
+
+ verifyDeserialize(snapshot);
+ }
+
+ public void testKeyChainSnapshot_withManyKeysAndProtectionParams() throws Exception {
+ PersistentKeyChainSnapshot writer = new PersistentKeyChainSnapshot();
+ writer.initWriter();
+
+ KeyDerivationParams derivationParams = KeyDerivationParams.createSha256Params(SALT);
+
+ ArrayList<KeyChainProtectionParams> protectionParamsList = new ArrayList<>();
+ protectionParamsList.add(new KeyChainProtectionParams.Builder()
+ .setUserSecretType(1)
+ .setLockScreenUiFormat(2)
+ .setKeyDerivationParams(derivationParams)
+ .build());
+ protectionParamsList.add(new KeyChainProtectionParams.Builder()
+ .setUserSecretType(2)
+ .setLockScreenUiFormat(3)
+ .setKeyDerivationParams(derivationParams)
+ .build());
+ ArrayList<WrappedApplicationKey> appKeysList = new ArrayList<>();
+ appKeysList.add(new WrappedApplicationKey.Builder()
+ .setAlias(ALIAS)
+ .setEncryptedKeyMaterial(KEY_MATERIAL)
+ .setAccount(ACCOUNT)
+ .build());
+ appKeysList.add(new WrappedApplicationKey.Builder()
+ .setAlias(ALIAS2)
+ .setEncryptedKeyMaterial(KEY_MATERIAL)
+ .setAccount(ACCOUNT)
+ .build());
+
+
+ KeyChainSnapshot snapshot = new KeyChainSnapshot.Builder()
+ .setSnapshotVersion(SNAPSHOT_VERSION)
+ .setKeyChainProtectionParams(protectionParamsList)
+ .setEncryptedRecoveryKeyBlob(KEY_MATERIAL)
+ .setWrappedApplicationKeys(appKeysList)
+ .setMaxAttempts(MAX_ATTEMPTS)
+ .setCounterId(COUNTER_ID)
+ .setServerParams(SERVER_PARAMS)
+ .setTrustedHardwarePublicKey(PUBLIC_KEY)
+ .build();
+
+ writer.writeKeyChainSnapshot(snapshot);
+
+ byte[] result = writer.getOutput();
+
+ PersistentKeyChainSnapshot reader = new PersistentKeyChainSnapshot();
+ reader.initReader(result);
+
+ KeyChainSnapshot copy = reader.readKeyChainSnapshot();
+ assertThat(copy.getSnapshotVersion()).isEqualTo(SNAPSHOT_VERSION);
+ assertThat(copy.getKeyChainProtectionParams().get(0).getUserSecretType()).isEqualTo(1);
+ assertThat(copy.getEncryptedRecoveryKeyBlob()).isEqualTo(RECOVERY_KEY_MATERIAL);
+ assertThat(copy.getWrappedApplicationKeys().get(0).getAlias()).isEqualTo(ALIAS);
+ assertThat(copy.getMaxAttempts()).isEqualTo(MAX_ATTEMPTS);
+ assertThat(copy.getCounterId()).isEqualTo(COUNTER_ID);
+ assertThat(copy.getServerParams()).isEqualTo(SERVER_PARAMS);
+ assertThat(copy.getTrustedHardwarePublicKey()).isEqualTo(PUBLIC_KEY);
+
+ assertThrows(
+ IOException.class,
+ () -> reader.readKeyChainSnapshot());
+
+ verifyDeserialize(snapshot);
+ }
+
+ private void verifyDeserialize(KeyChainSnapshot snapshot) throws Exception {
+ byte[] serialized = PersistentKeyChainSnapshot.serialize(snapshot);
+ KeyChainSnapshot copy = PersistentKeyChainSnapshot.deserialize(serialized);
+ assertThat(copy.getSnapshotVersion())
+ .isEqualTo(snapshot.getSnapshotVersion());
+ assertThat(copy.getKeyChainProtectionParams().size())
+ .isEqualTo(copy.getKeyChainProtectionParams().size());
+ assertThat(copy.getEncryptedRecoveryKeyBlob())
+ .isEqualTo(snapshot.getEncryptedRecoveryKeyBlob());
+ assertThat(copy.getWrappedApplicationKeys().size())
+ .isEqualTo(snapshot.getWrappedApplicationKeys().size());
+ assertThat(copy.getMaxAttempts()).isEqualTo(snapshot.getMaxAttempts());
+ assertThat(copy.getCounterId()).isEqualTo(snapshot.getCounterId());
+ assertThat(copy.getServerParams()).isEqualTo(snapshot.getServerParams());
+ assertThat(copy.getTrustedHardwarePublicKey())
+ .isEqualTo(snapshot.getTrustedHardwarePublicKey());
+ }
+
+
+ public void testDeserialize_failsForNewerVersion() throws Exception {
+ byte[] newVersion = new byte[]{(byte) 2, (byte) 0, (byte) 0, (byte) 0};
+ assertThrows(
+ IOException.class,
+ () -> PersistentKeyChainSnapshot.deserialize(newVersion));
+ }
+
+ public void testDeserialize_failsForEmptyData() throws Exception {
+ byte[] empty = new byte[]{};
+ assertThrows(
+ IOException.class,
+ () -> PersistentKeyChainSnapshot.deserialize(empty));
+ }
+
+}
+
diff --git a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
index c7fa62e..376db5b 100644
--- a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
@@ -388,7 +388,8 @@
latch.countDown();
}
});
- launchIntent.putExtras(extras);
+ launchIntent.putExtras(extras)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(launchIntent);
if (latch.await(NETWORK_CHECK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
if (errors[0] != null) {
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java
new file mode 100644
index 0000000..c3714c8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java
@@ -0,0 +1,310 @@
+/*
+ * 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.server.power.batterysaver;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.server.power.batterysaver.BatterySavingStats.BatterySaverState;
+import com.android.server.power.batterysaver.BatterySavingStats.DozeState;
+import com.android.server.power.batterysaver.BatterySavingStats.InteractiveState;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+
+/**
+ atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BatterySavingStatsTest {
+ private class BatterySavingStatsTestable extends BatterySavingStats {
+ private long mTime = 1_000_000; // Some random starting time.
+
+ private int mBatteryLevel = 1_000_000_000;
+
+ private BatterySavingStatsTestable() {
+ super(mMetricsLogger);
+ }
+
+ @Override
+ long injectCurrentTime() {
+ return mTime;
+ }
+
+ @Override
+ int injectBatteryLevel() {
+ return mBatteryLevel;
+ }
+
+ void assertDumpable() {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ dump(new PrintWriter(out), ""); // Just make sure it won't crash.
+ }
+
+ void advanceClock(int minutes) {
+ mTime += 60_000 * minutes;
+ }
+
+ void drainBattery(int value) {
+ mBatteryLevel -= value;
+ if (mBatteryLevel < 0) {
+ mBatteryLevel = 0;
+ }
+ }
+
+ String toDebugString() {
+ final StringBuilder sb = new StringBuilder();
+ String sep = "";
+ for (int i = 0; i < mStats.size(); i++) {
+ sb.append(sep);
+ sb.append(stateToString(mStats.keyAt(i)));
+ sb.append(":");
+ sb.append(mStats.valueAt(i).toStringForTest());
+ sep = "\n";
+ }
+ return sb.toString();
+ }
+ }
+
+ public MetricsLogger mMetricsLogger = mock(MetricsLogger.class);
+
+ @Test
+ public void testAll() {
+ final BatterySavingStatsTestable target = new BatterySavingStatsTestable();
+
+ target.assertDumpable();
+
+ target.advanceClock(1);
+ target.drainBattery(2);
+
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ target.advanceClock(4);
+ target.drainBattery(1);
+
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.NON_INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ target.advanceClock(2);
+ target.drainBattery(5);
+
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ target.advanceClock(4);
+ target.drainBattery(1);
+
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.NON_INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ target.advanceClock(2);
+ target.drainBattery(5);
+
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ target.advanceClock(3);
+ target.drainBattery(1);
+
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.NON_INTERACTIVE,
+ DozeState.LIGHT);
+
+ target.advanceClock(5);
+ target.drainBattery(1);
+
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.NON_INTERACTIVE,
+ DozeState.DEEP);
+
+ target.advanceClock(1);
+ target.drainBattery(2);
+
+ target.transitionState(
+ BatterySaverState.ON,
+ InteractiveState.INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ target.advanceClock(1);
+ target.drainBattery(3);
+
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ target.advanceClock(3);
+ target.drainBattery(5);
+
+ target.transitionState(
+ BatterySaverState.ON,
+ InteractiveState.INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ target.advanceClock(3);
+ target.drainBattery(5);
+
+ target.startCharging();
+
+ target.advanceClock(5);
+ target.drainBattery(10);
+
+ target.transitionState(
+ BatterySaverState.ON,
+ InteractiveState.INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ target.advanceClock(5);
+ target.drainBattery(1);
+
+ target.startCharging();
+
+ target.assertDumpable();
+
+ assertEquals(
+ "BS=0,I=0,D=0:{4m,10,150.00}\n" +
+ "BS=1,I=0,D=0:{0m,0,0.00}\n" +
+ "BS=0,I=1,D=0:{14m,8,34.29}\n" +
+ "BS=1,I=1,D=0:{9m,9,60.00}\n" +
+ "BS=0,I=0,D=1:{5m,1,12.00}\n" +
+ "BS=1,I=0,D=1:{0m,0,0.00}\n" +
+ "BS=0,I=1,D=1:{0m,0,0.00}\n" +
+ "BS=1,I=1,D=1:{0m,0,0.00}\n" +
+ "BS=0,I=0,D=2:{1m,2,120.00}\n" +
+ "BS=1,I=0,D=2:{0m,0,0.00}\n" +
+ "BS=0,I=1,D=2:{0m,0,0.00}\n" +
+ "BS=1,I=1,D=2:{0m,0,0.00}",
+ target.toDebugString());
+ }
+
+ private void assertMetricsLog(String counter, int value) {
+ verify(mMetricsLogger, times(1)).count(eq(counter), eq(value));
+ }
+
+ @Test
+ public void testMetricsLogger() {
+ final BatterySavingStatsTestable target = new BatterySavingStatsTestable();
+
+ target.advanceClock(1);
+ target.drainBattery(1000);
+
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
+
+ target.advanceClock(1);
+ target.drainBattery(2000);
+
+ reset(mMetricsLogger);
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.NON_INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ assertMetricsLog(BatterySavingStats.COUNTER_POWER_MILLIAMPS_PREFIX + "01", 2);
+ assertMetricsLog(BatterySavingStats.COUNTER_TIME_SECONDS_PREFIX + "01", 60);
+
+ target.advanceClock(1);
+ target.drainBattery(2000);
+
+ reset(mMetricsLogger);
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.NON_INTERACTIVE,
+ DozeState.DEEP);
+
+ target.advanceClock(1);
+ target.drainBattery(2000);
+
+ verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
+
+ target.transitionState(
+ BatterySaverState.OFF,
+ InteractiveState.NON_INTERACTIVE,
+ DozeState.LIGHT);
+
+ target.advanceClock(1);
+ target.drainBattery(2000);
+
+ verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
+
+ target.transitionState(
+ BatterySaverState.ON,
+ InteractiveState.INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ assertMetricsLog(BatterySavingStats.COUNTER_POWER_MILLIAMPS_PREFIX + "00", 2 * 3);
+ assertMetricsLog(BatterySavingStats.COUNTER_TIME_SECONDS_PREFIX + "00", 60 * 3);
+
+ target.advanceClock(10);
+ target.drainBattery(10_000);
+
+ reset(mMetricsLogger);
+ target.startCharging();
+
+ assertMetricsLog(BatterySavingStats.COUNTER_POWER_MILLIAMPS_PREFIX + "11", 10);
+ assertMetricsLog(BatterySavingStats.COUNTER_TIME_SECONDS_PREFIX + "11", 60 * 10);
+
+ target.advanceClock(1);
+ target.drainBattery(2000);
+
+ reset(mMetricsLogger);
+ target.transitionState(
+ BatterySaverState.ON,
+ InteractiveState.NON_INTERACTIVE,
+ DozeState.NOT_DOZING);
+
+ verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
+
+ target.advanceClock(1);
+ target.drainBattery(2000);
+
+ target.startCharging();
+
+ assertMetricsLog(BatterySavingStats.COUNTER_POWER_MILLIAMPS_PREFIX + "10", 2);
+ assertMetricsLog(BatterySavingStats.COUNTER_TIME_SECONDS_PREFIX + "10", 60);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
index 70906df..396fef4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
@@ -16,11 +16,14 @@
package com.android.server.wm;
-import java.util.HashMap;
-
-import org.junit.Test;
-import org.junit.Before;
-import org.junit.runner.RunWith;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -28,22 +31,25 @@
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.eq;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.stubbing.Answer;
/**
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.DimmerTests;
+ * atest FrameworksServicesTests:com.android.server.wm.DimmerTests;
*/
@Presubmit
+@Ignore("b/72450130")
@RunWith(AndroidJUnit4.class)
public class DimmerTests extends WindowTestsBase {
+
+ public DimmerTests() {
+ super(spy(new SurfaceAnimationRunner()));
+ }
+
private class TestWindowContainer extends WindowContainer<TestWindowContainer> {
final SurfaceControl mControl = mock(SurfaceControl.class);
final SurfaceControl.Transaction mTransaction = mock(SurfaceControl.Transaction.class);
@@ -65,12 +71,14 @@
private class MockSurfaceBuildingContainer extends WindowContainer<TestWindowContainer> {
final SurfaceSession mSession = new SurfaceSession();
- SurfaceControl mBuiltSurface = null;
- final SurfaceControl mHostControl = mock(SurfaceControl.class);
final SurfaceControl.Transaction mHostTransaction = mock(SurfaceControl.Transaction.class);
MockSurfaceBuildingContainer() {
super(sWm);
+ mSurfaceControl = sWm.makeSurfaceBuilder(mSession)
+ .setName("test surface")
+ .setSize(1, 1)
+ .build();
}
class MockSurfaceBuilder extends SurfaceControl.Builder {
@@ -80,12 +88,19 @@
@Override
public SurfaceControl build() {
- SurfaceControl sc = mock(SurfaceControl.class);
- mBuiltSurface = sc;
- return sc;
+ return spy(sWm.makeSurfaceBuilder(mSession)
+ .setName("test surface")
+ .setSize(1, 1)
+ .build());
}
}
+ @Override
+ SurfaceControl.Builder makeSurface() {
+ return sWm.makeSurfaceBuilder(mSession)
+ .setName("test surface")
+ .setSize(1, 1);
+ }
@Override
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
@@ -93,11 +108,6 @@
}
@Override
- public SurfaceControl getSurfaceControl() {
- return mHostControl;
- }
-
- @Override
public SurfaceControl.Transaction getPendingTransaction() {
return mHostTransaction;
}
@@ -114,29 +124,37 @@
mTransaction = mock(SurfaceControl.Transaction.class);
mDimmer = new Dimmer(mHost);
+
+ doAnswer((Answer<Void>) invocation -> {
+ Runnable runnable = invocation.getArgument(3);
+ runnable.run();
+ return null;
+ }).when(sWm.mSurfaceAnimationRunner).startAnimation(any(), any(), any(), any());
}
@Test
public void testDimAboveNoChildCreatesSurface() throws Exception {
final float alpha = 0.8f;
mDimmer.dimAbove(mTransaction, alpha);
- assertNotNull("Dimmer should have created a surface", mHost.mBuiltSurface);
- verify(mTransaction).setAlpha(mHost.mBuiltSurface, alpha);
- verify(mTransaction).show(mHost.mBuiltSurface);
- verify(mTransaction).setLayer(mHost.mBuiltSurface, Integer.MAX_VALUE);
+ SurfaceControl dimLayer = getDimLayer(null);
+
+ assertNotNull("Dimmer should have created a surface", dimLayer);
+
+ verify(mTransaction).setAlpha(dimLayer, alpha);
+ verify(mTransaction).setLayer(dimLayer, Integer.MAX_VALUE);
}
@Test
public void testDimAboveNoChildRedundantlyUpdatesAlphaOnExistingSurface() throws Exception {
float alpha = 0.8f;
mDimmer.dimAbove(mTransaction, alpha);
- final SurfaceControl firstSurface = mHost.mBuiltSurface;
+ final SurfaceControl firstSurface = getDimLayer(null);
alpha = 0.9f;
mDimmer.dimAbove(mTransaction, alpha);
- assertEquals(firstSurface, mHost.mBuiltSurface);
+ assertEquals(firstSurface, getDimLayer(null));
verify(mTransaction).setAlpha(firstSurface, 0.9f);
}
@@ -148,16 +166,20 @@
int height = 300;
Rect bounds = new Rect(0, 0, width, height);
mDimmer.updateDims(mTransaction, bounds);
- verify(mTransaction).setSize(mHost.mBuiltSurface, width, height);
+
+ verify(mTransaction).setSize(getDimLayer(null), width, height);
+ verify(mTransaction).show(getDimLayer(null));
}
@Test
public void testDimAboveNoChildNotReset() throws Exception {
mDimmer.dimAbove(mTransaction, 0.8f);
+ SurfaceControl dimLayer = getDimLayer(null);
mDimmer.resetDimStates();
mDimmer.updateDims(mTransaction, new Rect());
- verify(mHost.mBuiltSurface, never()).destroy();
+ verify(mTransaction).show(getDimLayer(null));
+ verify(dimLayer, never()).destroy();
}
@Test
@@ -167,11 +189,12 @@
final float alpha = 0.8f;
mDimmer.dimAbove(mTransaction, child, alpha);
- assertNotNull("Dimmer should have created a surface", mHost.mBuiltSurface);
+ SurfaceControl mDimLayer = getDimLayer(child);
- verify(mTransaction).setAlpha(mHost.mBuiltSurface, alpha);
- verify(mTransaction).show(mHost.mBuiltSurface);
- verify(mTransaction).setRelativeLayer(mHost.mBuiltSurface, child.mControl, 1);
+ assertNotNull("Dimmer should have created a surface", mDimLayer);
+
+ verify(mTransaction).setAlpha(mDimLayer, alpha);
+ verify(mTransaction).setRelativeLayer(mDimLayer, child.mControl, 1);
}
@Test
@@ -181,11 +204,12 @@
final float alpha = 0.8f;
mDimmer.dimBelow(mTransaction, child, alpha);
- assertNotNull("Dimmer should have created a surface", mHost.mBuiltSurface);
+ SurfaceControl mDimLayer = getDimLayer(child);
- verify(mTransaction).setAlpha(mHost.mBuiltSurface, alpha);
- verify(mTransaction).show(mHost.mBuiltSurface);
- verify(mTransaction).setRelativeLayer(mHost.mBuiltSurface, child.mControl, -1);
+ assertNotNull("Dimmer should have created a surface", mDimLayer);
+
+ verify(mTransaction).setAlpha(mDimLayer, alpha);
+ verify(mTransaction).setRelativeLayer(mDimLayer, child.mControl, -1);
}
@Test
@@ -195,9 +219,11 @@
final float alpha = 0.8f;
mDimmer.dimAbove(mTransaction, child, alpha);
+ SurfaceControl dimLayer = getDimLayer(child);
mDimmer.resetDimStates();
+
mDimmer.updateDims(mTransaction, new Rect());
- verify(mHost.mBuiltSurface).destroy();
+ verify(dimLayer).destroy();
}
@Test
@@ -207,10 +233,16 @@
final float alpha = 0.8f;
mDimmer.dimAbove(mTransaction, child, alpha);
+ SurfaceControl dimLayer = getDimLayer(child);
mDimmer.resetDimStates();
mDimmer.dimAbove(mTransaction, child, alpha);
mDimmer.updateDims(mTransaction, new Rect());
- verify(mHost.mBuiltSurface, never()).destroy();
+ verify(mTransaction).show(dimLayer);
+ verify(dimLayer, never()).destroy();
+ }
+
+ private SurfaceControl getDimLayer(WindowContainer windowContainer) {
+ return mDimmer.mDimLayerUsers.get(windowContainer).mDimLayer;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 897be34..f860195 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import android.graphics.Point;
import android.graphics.Rect;
@@ -134,4 +135,10 @@
verify(mMockRunner).onAnimationCancelled();
verify(mFinishedCallback).onAnimationFinished(eq(adapter));
}
+
+ @Test
+ public void testZeroAnimations() throws Exception {
+ mController.goodToGo();
+ verifyZeroInteractions(mMockRunner);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 35ca493..81fd889 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.spy;
import android.os.PowerSaveState;
import android.util.proto.ProtoOutputStream;
@@ -68,6 +69,11 @@
private Runnable mRunnableWhenAddingSplashScreen;
static synchronized WindowManagerService getWindowManagerService(Context context) {
+ return getWindowManagerService(context, new SurfaceAnimationRunner());
+ }
+
+ static synchronized WindowManagerService getWindowManagerService(Context context,
+ SurfaceAnimationRunner surfaceAnimationRunner) {
if (sWm == null) {
// We only want to do this once for the test process as we don't want WM to try to
// register a bunch of local services again.
@@ -105,7 +111,7 @@
}
sWm = WindowManagerService.main(context, ims, true, false,
- false, new TestWindowManagerPolicy());
+ false, new TestWindowManagerPolicy(), surfaceAnimationRunner);
}
return sWm;
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index 196b4a9..1bd9a93 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -20,6 +20,7 @@
import org.junit.runner.RunWith;
import android.content.res.Configuration;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -41,11 +42,16 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
/**
* Test class for {@link WindowContainer}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.WindowContainerTests
+ * atest FrameworksServicesTests:com.android.server.wm.WindowContainerTests
*/
@SmallTest
@Presubmit
@@ -644,6 +650,37 @@
assertEquals(1, child2.getPrefixOrderIndex());
}
+ /**
+ * Ensure children of a {@link WindowContainer} do not have
+ * {@link WindowContainer#onParentResize()} called when {@link WindowContainer#onParentResize()}
+ * is invoked with overridden bounds.
+ */
+ @Test
+ public void testOnParentResizePropagation() throws Exception {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+ final TestWindowContainer root = builder.build();
+
+ final TestWindowContainer child = root.addChildWindow();
+ child.setBounds(new Rect(1,1,2,2));
+
+ final TestWindowContainer grandChild = mock(TestWindowContainer.class);
+
+ child.addChildWindow(grandChild);
+ root.onResize();
+
+ // Make sure the child does not propagate resize through onParentResize when bounds are set.
+ verify(grandChild, never()).onParentResize();
+
+ child.removeChild(grandChild);
+
+ child.setBounds(null);
+ child.addChildWindow(grandChild);
+ root.onResize();
+
+ // Make sure the child propagates resize through onParentResize when no bounds set.
+ verify(grandChild, times(1)).onParentResize();
+ }
+
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
private class TestWindowContainer extends WindowContainer<TestWindowContainer> {
private final int mLayer;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 69b1378..7918901 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -84,6 +84,16 @@
WindowState mChildAppWindowBelow;
HashSet<WindowState> mCommonWindows;
+ private final SurfaceAnimationRunner mSurfaceAnimationRunner;
+
+ public WindowTestsBase() {
+ this(new SurfaceAnimationRunner());
+ }
+
+ public WindowTestsBase(SurfaceAnimationRunner surfaceAnimationRunner) {
+ mSurfaceAnimationRunner = surfaceAnimationRunner;
+ }
+
@Before
public void setUp() throws Exception {
if (!sOneTimeSetupDone) {
@@ -98,7 +108,7 @@
final Context context = InstrumentationRegistry.getTargetContext();
AttributeCache.init(context);
- sWm = TestWindowManagerPolicy.getWindowManagerService(context);
+ sWm = TestWindowManagerPolicy.getWindowManagerService(context, mSurfaceAnimationRunner);
beforeCreateDisplay();
context.getDisplay().getDisplayInfo(mDisplayInfo);
diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml
index 3475572..aabf9ea 100644
--- a/services/tests/uiservicestests/AndroidManifest.xml
+++ b/services/tests/uiservicestests/AndroidManifest.xml
@@ -26,6 +26,7 @@
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
+ <uses-permission android:name="android.permission.DEVICE_POWER" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
index d3bb804..cfd155e 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
@@ -1,5 +1,7 @@
package com.android.server.slice;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -11,7 +13,9 @@
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -20,6 +24,7 @@
import android.app.slice.SliceProvider;
import android.app.slice.SliceSpec;
import android.content.ContentProvider;
+import android.content.Context;
import android.content.IContentProvider;
import android.net.Uri;
import android.os.Binder;
@@ -70,8 +75,8 @@
@Before
public void setup() {
mSliceService = mock(SliceManagerService.class);
- when(mSliceService.getLock()).thenReturn(new Object());
when(mSliceService.getContext()).thenReturn(mContext);
+ when(mSliceService.getLock()).thenReturn(new Object());
when(mSliceService.getHandler()).thenReturn(new Handler(TestableLooper.get(this).getLooper()));
mContentProvider = mock(ContentProvider.class);
mIContentProvider = mock(IContentProvider.class);
@@ -99,8 +104,11 @@
}
@Test
- public void testSendPinnedOnCreate() throws RemoteException {
- // When created, a pinned message should be sent.
+ public void testSendPinnedOnPin() throws RemoteException {
+ TestableLooper.get(this).processAllMessages();
+
+ // When pinned for the first time, a pinned message should be sent.
+ mPinnedSliceManager.pin("pkg", FIRST_SPECS);
TestableLooper.get(this).processAllMessages();
verify(mIContentProvider).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null),
@@ -111,10 +119,46 @@
}
@Test
+ public void testSendPinnedOnListen() throws RemoteException {
+ TestableLooper.get(this).processAllMessages();
+
+ // When a listener is added for the first time, a pinned message should be sent.
+ ISliceListener listener = mock(ISliceListener.class);
+ when(listener.asBinder()).thenReturn(new Binder());
+
+ mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS,
+ true);
+ TestableLooper.get(this).processAllMessages();
+
+ verify(mIContentProvider).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null),
+ argThat(b -> {
+ assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
+ return true;
+ }));
+ }
+
+ @Test
+ public void testNoSendPinnedWithoutPermission() throws RemoteException {
+ TestableLooper.get(this).processAllMessages();
+
+ // When a listener is added for the first time, a pinned message should be sent.
+ ISliceListener listener = mock(ISliceListener.class);
+ when(listener.asBinder()).thenReturn(new Binder());
+
+ mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS,
+ false);
+ TestableLooper.get(this).processAllMessages();
+
+ verify(mIContentProvider, never()).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null),
+ any());
+ }
+
+ @Test
public void testSendUnpinnedOnDestroy() throws RemoteException {
TestableLooper.get(this).processAllMessages();
clearInvocations(mIContentProvider);
+ mPinnedSliceManager.pin("pkg", FIRST_SPECS);
mPinnedSliceManager.destroy();
TestableLooper.get(this).processAllMessages();
@@ -127,39 +171,40 @@
@Test
public void testPkgPin() {
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
mPinnedSliceManager.pin("pkg", FIRST_SPECS);
- assertTrue(mPinnedSliceManager.isPinned());
+ assertTrue(mPinnedSliceManager.hasPinOrListener());
assertTrue(mPinnedSliceManager.unpin("pkg"));
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
}
@Test
public void testMultiPkgPin() {
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
mPinnedSliceManager.pin("pkg", FIRST_SPECS);
- assertTrue(mPinnedSliceManager.isPinned());
+ assertTrue(mPinnedSliceManager.hasPinOrListener());
mPinnedSliceManager.pin("pkg2", FIRST_SPECS);
assertFalse(mPinnedSliceManager.unpin("pkg"));
assertTrue(mPinnedSliceManager.unpin("pkg2"));
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
}
@Test
public void testListenerPin() {
ISliceListener listener = mock(ISliceListener.class);
when(listener.asBinder()).thenReturn(new Binder());
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
- mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS);
- assertTrue(mPinnedSliceManager.isPinned());
+ mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS,
+ true);
+ assertTrue(mPinnedSliceManager.hasPinOrListener());
assertTrue(mPinnedSliceManager.removeSliceListener(listener));
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
}
@Test
@@ -170,15 +215,17 @@
ISliceListener listener2 = mock(ISliceListener.class);
Binder value2 = new Binder();
when(listener2.asBinder()).thenReturn(value2);
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
- mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS);
- assertTrue(mPinnedSliceManager.isPinned());
- mPinnedSliceManager.addSliceListener(listener2, mContext.getPackageName(), FIRST_SPECS);
+ mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS,
+ true);
+ assertTrue(mPinnedSliceManager.hasPinOrListener());
+ mPinnedSliceManager.addSliceListener(listener2, mContext.getPackageName(), FIRST_SPECS,
+ true);
assertFalse(mPinnedSliceManager.removeSliceListener(listener));
assertTrue(mPinnedSliceManager.removeSliceListener(listener2));
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
}
@Test
@@ -187,10 +234,11 @@
IBinder binder = mock(IBinder.class);
when(binder.isBinderAlive()).thenReturn(true);
when(listener.asBinder()).thenReturn(binder);
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
- mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS);
- assertTrue(mPinnedSliceManager.isPinned());
+ mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS,
+ true);
+ assertTrue(mPinnedSliceManager.hasPinOrListener());
ArgumentCaptor<DeathRecipient> arg = ArgumentCaptor.forClass(DeathRecipient.class);
verify(binder).linkToDeath(arg.capture(), anyInt());
@@ -198,23 +246,25 @@
when(binder.isBinderAlive()).thenReturn(false);
arg.getValue().binderDied();
+ verify(mSliceService).unlisten(eq(TEST_URI));
verify(mSliceService).removePinnedSlice(eq(TEST_URI));
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
}
@Test
public void testPkgListenerPin() {
ISliceListener listener = mock(ISliceListener.class);
when(listener.asBinder()).thenReturn(new Binder());
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
- mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS);
- assertTrue(mPinnedSliceManager.isPinned());
+ mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS,
+ true);
+ assertTrue(mPinnedSliceManager.hasPinOrListener());
mPinnedSliceManager.pin("pkg", FIRST_SPECS);
assertFalse(mPinnedSliceManager.removeSliceListener(listener));
assertTrue(mPinnedSliceManager.unpin("pkg"));
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
}
@Test
@@ -230,9 +280,10 @@
when(mIContentProvider.call(anyString(), eq(SliceProvider.METHOD_SLICE), eq(null),
any())).thenReturn(b);
- assertFalse(mPinnedSliceManager.isPinned());
+ assertFalse(mPinnedSliceManager.hasPinOrListener());
- mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS);
+ mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS,
+ true);
mPinnedSliceManager.onChange();
TestableLooper.get(this).processAllMessages();
@@ -244,4 +295,30 @@
}));
verify(listener).onSliceUpdated(eq(s));
}
+
+ @Test
+ public void testRecheckPackage() throws RemoteException {
+ TestableLooper.get(this).processAllMessages();
+
+ ISliceListener listener = mock(ISliceListener.class);
+ when(listener.asBinder()).thenReturn(new Binder());
+
+ mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS,
+ false);
+ TestableLooper.get(this).processAllMessages();
+
+ verify(mIContentProvider, never()).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null),
+ any());
+
+ when(mSliceService.checkAccess(any(), any(), anyInt(), anyInt()))
+ .thenReturn(PERMISSION_GRANTED);
+ mPinnedSliceManager.recheckPackage(mContext.getPackageName());
+ TestableLooper.get(this).processAllMessages();
+
+ verify(mIContentProvider).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null),
+ argThat(b -> {
+ assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
+ return true;
+ }));
+ }
}
\ No newline at end of file
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceFullAccessListTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceFullAccessListTest.java
new file mode 100644
index 0000000..7c14d08
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceFullAccessListTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.server.slice;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.util.Xml.Encoding;
+
+import com.android.server.UiServiceTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+@SmallTest
+public class SliceFullAccessListTest extends UiServiceTestCase {
+
+ private static final String TEST_XML = "<slice-access-list version=\"1\"><user "
+ + "user=\"0\"><pkg>pkg</pkg><pkg>pkg1</pkg></user><user "
+ + "user=\"1\"><pkg>pkg</pkg></user><user "
+ + "user=\"3\"><pkg>pkg2</pkg></user></slice-access-list>";
+
+ private SliceFullAccessList mAccessList;
+
+ @Before
+ public void setup() {
+ mAccessList = new SliceFullAccessList(mContext);
+ }
+
+ @Test
+ public void testNoDefaultAccess() {
+ assertFalse(mAccessList.hasFullAccess("pkg", 0));
+ }
+
+ @Test
+ public void testGrantAccess() {
+ mAccessList.grantFullAccess("pkg", 0);
+ assertTrue(mAccessList.hasFullAccess("pkg", 0));
+ }
+
+ @Test
+ public void testUserSeparation() {
+ mAccessList.grantFullAccess("pkg", 1);
+ assertFalse(mAccessList.hasFullAccess("pkg", 0));
+ }
+
+ @Test
+ public void testSerialization() throws XmlPullParserException, IOException {
+ mAccessList.grantFullAccess("pkg", 0);
+ mAccessList.grantFullAccess("pkg1", 0);
+ mAccessList.grantFullAccess("pkg", 1);
+ mAccessList.grantFullAccess("pkg2", 3);
+
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ XmlSerializer out = XmlPullParserFactory.newInstance().newSerializer();
+ out.setOutput(output, Encoding.UTF_8.name());
+ mAccessList.writeXml(out);
+ out.flush();
+
+ assertEquals(TEST_XML, output.toString(Encoding.UTF_8.name()));
+ }
+
+ @Test
+ public void testDeSerialization() throws XmlPullParserException, IOException {
+ ByteArrayInputStream input = new ByteArrayInputStream(TEST_XML.getBytes());
+ XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+ parser.setInput(input, Encoding.UTF_8.name());
+
+ mAccessList.readXml(parser);
+
+ assertTrue(mAccessList.hasFullAccess("pkg", 0));
+ assertTrue(mAccessList.hasFullAccess("pkg1", 0));
+ assertTrue(mAccessList.hasFullAccess("pkg", 1));
+ assertTrue(mAccessList.hasFullAccess("pkg2", 3));
+
+ assertFalse(mAccessList.hasFullAccess("pkg3", 0));
+ assertFalse(mAccessList.hasFullAccess("pkg1", 1));
+ assertFalse(mAccessList.hasFullAccess("pkg", 3));
+ assertFalse(mAccessList.hasFullAccess("pkg", 2));
+ }
+}
\ No newline at end of file
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index 0cbda28..2becdf2 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -36,6 +36,8 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerInternal;
import libcore.io.IoUtils;
@@ -202,27 +204,23 @@
* that's in the future, then the usage event is temporary and keeps the app in the specified
* bucket at least until the timeout is reached. This can be used to keep the app in an
* elevated bucket for a while until some important task gets to run.
- * @param packageName
- * @param userId
- * @param bucket the bucket to set the app to
+ * @param appUsageHistory the usage record for the app being updated
+ * @param packageName name of the app being updated, for logging purposes
+ * @param newBucket the bucket to set the app to
* @param elapsedRealtime mark as used time if non-zero
* @param timeout set the timeout of the specified bucket, if non-zero
* @return
*/
- public int reportUsage(String packageName, int userId, int bucket, long elapsedRealtime,
- long timeout) {
- ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
- AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
- elapsedRealtime, true);
-
+ public AppUsageHistory reportUsage(AppUsageHistory appUsageHistory, String packageName,
+ int newBucket, long elapsedRealtime, long timeout) {
if (elapsedRealtime != 0) {
appUsageHistory.lastUsedElapsedTime = mElapsedDuration
+ (elapsedRealtime - mElapsedSnapshot);
appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
}
- if (appUsageHistory.currentBucket > bucket) {
- appUsageHistory.currentBucket = bucket;
+ if (appUsageHistory.currentBucket > newBucket) {
+ appUsageHistory.currentBucket = newBucket;
if (DEBUG) {
Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory
.currentBucket
@@ -235,7 +233,26 @@
}
appUsageHistory.bucketingReason = REASON_USAGE;
- return appUsageHistory.currentBucket;
+ return appUsageHistory;
+ }
+
+ /**
+ * Mark the app as used and update the bucket if necessary. If there is a timeout specified
+ * that's in the future, then the usage event is temporary and keeps the app in the specified
+ * bucket at least until the timeout is reached. This can be used to keep the app in an
+ * elevated bucket for a while until some important task gets to run.
+ * @param packageName
+ * @param userId
+ * @param newBucket the bucket to set the app to
+ * @param elapsedRealtime mark as used time if non-zero
+ * @param timeout set the timeout of the specified bucket, if non-zero
+ * @return
+ */
+ public AppUsageHistory reportUsage(String packageName, int userId, int newBucket,
+ long nowElapsed, long timeout) {
+ ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
+ AppUsageHistory history = getPackageHistory(userHistory, packageName, nowElapsed, true);
+ return reportUsage(history, packageName, newBucket, nowElapsed, timeout);
}
private ArrayMap<String, AppUsageHistory> getUserHistory(int userId) {
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 6782188..8cb2eec 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -27,7 +27,6 @@
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
-
import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
@@ -81,6 +80,7 @@
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
+import com.android.server.usage.AppIdleHistory.AppUsageHistory;
import java.io.File;
import java.io.PrintWriter;
@@ -198,6 +198,48 @@
private PackageManager mPackageManager;
Injector mInjector;
+ static final ArrayList<StandbyUpdateRecord> sStandbyUpdatePool = new ArrayList<>(4);
+
+ public static class StandbyUpdateRecord {
+ // Identity of the app whose standby state has changed
+ String packageName;
+ int userId;
+
+ // What the standby bucket the app is now in
+ int bucket;
+
+ // Whether the bucket change is because the user has started interacting with the app
+ boolean isUserInteraction;
+
+ StandbyUpdateRecord(String pkgName, int userId, int bucket, boolean isInteraction) {
+ this.packageName = pkgName;
+ this.userId = userId;
+ this.bucket = bucket;
+ this.isUserInteraction = isInteraction;
+ }
+
+ public static StandbyUpdateRecord obtain(String pkgName, int userId,
+ int bucket, boolean isInteraction) {
+ synchronized (sStandbyUpdatePool) {
+ final int size = sStandbyUpdatePool.size();
+ if (size < 1) {
+ return new StandbyUpdateRecord(pkgName, userId, bucket, isInteraction);
+ }
+ StandbyUpdateRecord r = sStandbyUpdatePool.remove(size - 1);
+ r.packageName = pkgName;
+ r.userId = userId;
+ r.bucket = bucket;
+ r.isUserInteraction = isInteraction;
+ return r;
+ }
+ }
+
+ public void recycle() {
+ synchronized (sStandbyUpdatePool) {
+ sStandbyUpdatePool.add(this);
+ }
+ }
+ }
AppStandbyController(Context context, Looper looper) {
this(new Injector(context, looper));
@@ -279,11 +321,11 @@
}
if (!packageName.equals(providerPkgName)) {
synchronized (mAppIdleLock) {
- int newBucket = mAppIdleHistory.reportUsage(packageName, userId,
+ AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId,
STANDBY_BUCKET_ACTIVE, elapsedRealtime,
elapsedRealtime + 2 * ONE_HOUR);
maybeInformListeners(packageName, userId, elapsedRealtime,
- newBucket);
+ appUsage.currentBucket, false);
}
}
} catch (PackageManager.NameNotFoundException e) {
@@ -417,7 +459,7 @@
STANDBY_BUCKET_EXEMPTED, REASON_DEFAULT);
}
maybeInformListeners(packageName, userId, elapsedRealtime,
- STANDBY_BUCKET_EXEMPTED);
+ STANDBY_BUCKET_EXEMPTED, false);
} else {
synchronized (mAppIdleLock) {
AppIdleHistory.AppUsageHistory app =
@@ -446,7 +488,7 @@
mAppIdleHistory.setAppStandbyBucket(packageName, userId,
elapsedRealtime, newBucket, REASON_TIMEOUT);
maybeInformListeners(packageName, userId, elapsedRealtime,
- newBucket);
+ newBucket, false);
}
}
}
@@ -474,13 +516,16 @@
}
private void maybeInformListeners(String packageName, int userId,
- long elapsedRealtime, int bucket) {
+ long elapsedRealtime, int bucket, boolean userStartedInteracting) {
synchronized (mAppIdleLock) {
// TODO: fold these into one call + lookup for efficiency if needed
if (mAppIdleHistory.shouldInformListeners(packageName, userId,
elapsedRealtime, bucket)) {
+ StandbyUpdateRecord r = StandbyUpdateRecord.obtain(packageName, userId,
+ bucket, userStartedInteracting);
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
- userId, bucket, packageName));
+ StandbyUpdateRecord.obtain(packageName, userId,
+ bucket, userStartedInteracting)));
}
}
}
@@ -566,19 +611,27 @@
|| event.mEventType == UsageEvents.Event.USER_INTERACTION
|| event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN)) {
- final int newBucket;
+ final AppUsageHistory appHistory = mAppIdleHistory.getAppUsageHistory(
+ event.mPackage, userId, elapsedRealtime);
+ final int prevBucket = appHistory.currentBucket;
+ final String prevBucketReason = appHistory.bucketingReason;
if (event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN) {
- newBucket = mAppIdleHistory.reportUsage(event.mPackage, userId,
+ mAppIdleHistory.reportUsage(appHistory, event.mPackage,
STANDBY_BUCKET_WORKING_SET,
elapsedRealtime, elapsedRealtime + 2 * ONE_HOUR);
} else {
- newBucket = mAppIdleHistory.reportUsage(event.mPackage, userId,
+ mAppIdleHistory.reportUsage(event.mPackage, userId,
STANDBY_BUCKET_ACTIVE,
elapsedRealtime, elapsedRealtime + 2 * ONE_HOUR);
}
+ final boolean userStartedInteracting =
+ appHistory.currentBucket == STANDBY_BUCKET_ACTIVE &&
+ prevBucket != appHistory.currentBucket &&
+ prevBucketReason != REASON_USAGE;
maybeInformListeners(event.mPackage, userId, elapsedRealtime,
- newBucket);
+ appHistory.currentBucket, userStartedInteracting);
+
if (previouslyIdle) {
notifyBatteryStats(event.mPackage, userId, false);
}
@@ -611,7 +664,7 @@
userId, elapsedRealtime);
// Inform listeners if necessary
if (previouslyIdle != stillIdle) {
- maybeInformListeners(packageName, userId, elapsedRealtime, standbyBucket);
+ maybeInformListeners(packageName, userId, elapsedRealtime, standbyBucket, false);
if (!stillIdle) {
notifyBatteryStats(packageName, userId, idle);
}
@@ -871,8 +924,7 @@
mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket,
reason);
}
- maybeInformListeners(packageName, userId, elapsedRealtime,
- newBucket);
+ maybeInformListeners(packageName, userId, elapsedRealtime, newBucket, false);
}
@VisibleForTesting
@@ -972,11 +1024,14 @@
return packageName != null && packageName.equals(activeScorer);
}
- void informListeners(String packageName, int userId, int bucket) {
+ void informListeners(String packageName, int userId, int bucket, boolean userInteraction) {
final boolean idle = bucket >= STANDBY_BUCKET_RARE;
synchronized (mPackageAccessListeners) {
for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
listener.onAppIdleStateChanged(packageName, userId, idle, bucket);
+ if (userInteraction) {
+ listener.onUserInteractionStarted(packageName, userId);
+ }
}
}
}
@@ -1230,7 +1285,9 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_INFORM_LISTENERS:
- informListeners((String) msg.obj, msg.arg1, msg.arg2);
+ StandbyUpdateRecord r = (StandbyUpdateRecord) msg.obj;
+ informListeners(r.packageName, r.userId, r.bucket, r.isUserInteraction);
+ r.recycle();
break;
case MSG_FORCE_IDLE_STATE:
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 096fdcc..36a2a95 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1043,6 +1043,12 @@
return mAppStandby.getTimeSinceLastJobRun(packageName, userId);
}
+ @Override
+ public void reportAppJobState(String packageName, int userId,
+ int numDeferredJobs, long timeSinceLastJobRun) {
+ }
+
+ @Override
public void onActiveAdminAdded(String packageName, int userId) {
mAppStandby.addActiveDeviceAdmin(packageName, userId);
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index e3e5e3e..55ffea6 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -41,7 +41,6 @@
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
-import android.hardware.usb.gadget.V1_0.GadgetFunction;
import android.hardware.usb.gadget.V1_0.IUsbGadget;
import android.hardware.usb.gadget.V1_0.IUsbGadgetCallback;
import android.hardware.usb.gadget.V1_0.Status;
@@ -68,6 +67,8 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.SomeArgs;
@@ -86,21 +87,20 @@
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.Set;
-import java.util.StringJoiner;
/**
* UsbDeviceManager manages USB state in device mode.
*/
public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver {
- private static final String TAG = "UsbDeviceManager";
+ private static final String TAG = UsbDeviceManager.class.getSimpleName();
private static final boolean DEBUG = false;
/**
* The SharedPreference setting per user that stores the screen unlocked functions between
* sessions.
*/
- private static final String UNLOCKED_CONFIG_PREF = "usb-screen-unlocked-config-%d";
+ static final String UNLOCKED_CONFIG_PREF = "usb-screen-unlocked-config-%d";
/**
* ro.bootmode value when phone boots into usual Android.
@@ -156,8 +156,6 @@
private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv";
private UsbHandler mHandler;
- private boolean mBootCompleted;
- private boolean mSystemReady;
private final Object mLock = new Object();
@@ -165,22 +163,13 @@
private final ContentResolver mContentResolver;
@GuardedBy("mLock")
private UsbProfileGroupSettingsManager mCurrentSettings;
- private NotificationManager mNotificationManager;
private final boolean mHasUsbAccessory;
- private boolean mUseUsbNotification;
- private boolean mAdbEnabled;
- private boolean mAudioSourceEnabled;
- private boolean mMidiEnabled;
- private int mMidiCard;
- private int mMidiDevice;
+ @GuardedBy("mLock")
private String[] mAccessoryStrings;
private UsbDebuggingManager mDebuggingManager;
- private final UsbAlsaManager mUsbAlsaManager;
- private final UsbSettingsManager mSettingsManager;
- private Intent mBroadcastedIntent;
- private boolean mPendingBootBroadcast;
+ private final UEventObserver mUEventObserver;
+
private static Set<Integer> sBlackListedInterfaces;
- private SharedPreferences mSettings;
static {
sBlackListedInterfaces = new HashSet<>();
@@ -213,7 +202,7 @@
/*
* Listens for uevent messages from the kernel to monitor the USB state
*/
- private final UEventObserver mUEventObserver = new UEventObserver() {
+ private final class UsbUEventObserver extends UEventObserver {
@Override
public void onUEvent(UEventObserver.UEvent event) {
if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());
@@ -227,7 +216,7 @@
startAccessoryMode();
}
}
- };
+ }
@Override
public void onKeyguardStateChanged(boolean isShowing) {
@@ -257,8 +246,6 @@
public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
UsbSettingsManager settingsManager) {
mContext = context;
- mUsbAlsaManager = alsaManager;
- mSettingsManager = settingsManager;
mContentResolver = context.getContentResolver();
PackageManager pm = mContext.getPackageManager();
mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
@@ -274,16 +261,24 @@
Slog.i(TAG, "USB GADGET HAL not present in the device", e);
}
+ boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
+ boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
+ if (secureAdbEnabled && !dataEncrypted) {
+ mDebuggingManager = new UsbDebuggingManager(context);
+ }
+
if (halNotPresent) {
/**
* Initialze the legacy UsbHandler
*/
- mHandler = new UsbHandlerLegacy(FgThread.get().getLooper(), mContext);
+ mHandler = new UsbHandlerLegacy(FgThread.get().getLooper(), mContext, this,
+ mDebuggingManager, alsaManager, settingsManager);
} else {
/**
* Initialize HAL based UsbHandler
*/
- mHandler = new UsbHandlerHal(FgThread.get().getLooper());
+ mHandler = new UsbHandlerHal(FgThread.get().getLooper(), mContext, this,
+ mDebuggingManager, alsaManager, settingsManager);
}
if (nativeIsStartRequested()) {
@@ -291,12 +286,6 @@
startAccessoryMode();
}
- boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
- boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
- if (secureAdbEnabled && !dataEncrypted) {
- mDebuggingManager = new UsbDebuggingManager(context);
- }
-
BroadcastReceiver portReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -347,41 +336,35 @@
mContext.registerReceiver(languageChangedReceiver,
new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
+
+ // Watch for USB configuration changes
+ mUEventObserver = new UsbUEventObserver();
+ mUEventObserver.startObserving(USB_STATE_MATCH);
+ mUEventObserver.startObserving(ACCESSORY_START_MATCH);
+
+ // register observer to listen for settings changes
+ mContentResolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
+ false, new AdbSettingsObserver());
}
- private UsbProfileGroupSettingsManager getCurrentSettings() {
+ UsbProfileGroupSettingsManager getCurrentSettings() {
synchronized (mLock) {
return mCurrentSettings;
}
}
+ String[] getAccessoryStrings() {
+ synchronized (mLock) {
+ return mAccessoryStrings;
+ }
+ }
+
public void systemReady() {
if (DEBUG) Slog.d(TAG, "systemReady");
LocalServices.getService(ActivityManagerInternal.class).registerScreenObserver(this);
- mNotificationManager = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
-
- // Ensure that the notification channels are set up
- if (isTv()) {
- // TV-specific notification channel
- mNotificationManager.createNotificationChannel(
- new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV,
- mContext.getString(
- com.android.internal.R.string
- .adb_debugging_notification_channel_tv),
- NotificationManager.IMPORTANCE_HIGH));
- }
-
- // We do not show the USB notification if the primary volume supports mass storage.
- // The legacy mass storage UI will be used instead.
- boolean massStorageSupported;
- final StorageManager storageManager = StorageManager.from(mContext);
- final StorageVolume primary = storageManager.getPrimaryVolume();
- massStorageSupported = primary != null && primary.allowMassStorage();
- mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_usbChargingMessage);
mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
}
@@ -410,21 +393,19 @@
boolean enableAccessory = (mAccessoryStrings != null &&
mAccessoryStrings[UsbAccessory.MANUFACTURER_STRING] != null &&
mAccessoryStrings[UsbAccessory.MODEL_STRING] != null);
- String functions = null;
- if (enableAccessory && enableAudio) {
- functions = UsbManager.USB_FUNCTION_ACCESSORY + ","
- + UsbManager.USB_FUNCTION_AUDIO_SOURCE;
- } else if (enableAccessory) {
- functions = UsbManager.USB_FUNCTION_ACCESSORY;
- } else if (enableAudio) {
- functions = UsbManager.USB_FUNCTION_AUDIO_SOURCE;
+ long functions = UsbManager.FUNCTION_NONE;
+ if (enableAccessory) {
+ functions |= UsbManager.FUNCTION_ACCESSORY;
+ }
+ if (enableAudio) {
+ functions |= UsbManager.FUNCTION_AUDIO_SOURCE;
}
- if (functions != null) {
+ if (functions != UsbManager.FUNCTION_NONE) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSORY_MODE_ENTER_TIMEOUT),
ACCESSORY_REQUEST_TIMEOUT);
- setCurrentFunctions(functions, false);
+ setCurrentFunctions(functions);
}
}
@@ -451,19 +432,7 @@
}
}
- private boolean isTv() {
- return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
- }
-
- private SharedPreferences getPinnedSharedPrefs(Context context) {
- final File prefsFile = new File(new File(
- Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
- context.getUserId(), context.getPackageName()), "shared_prefs"),
- UsbDeviceManager.class.getSimpleName() + ".xml");
- return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
- }
-
- private abstract class UsbHandler extends Handler {
+ abstract static class UsbHandler extends Handler {
// current USB state
private boolean mConnected;
@@ -471,21 +440,40 @@
private boolean mSourcePower;
private boolean mSinkPower;
private boolean mConfigured;
- protected boolean mUsbDataUnlocked;
private boolean mAudioAccessoryConnected;
private boolean mAudioAccessorySupported;
- protected String mCurrentFunctions;
- protected boolean mCurrentFunctionsApplied;
+
private UsbAccessory mCurrentAccessory;
private int mUsbNotificationId;
private boolean mAdbNotificationShown;
- private int mCurrentUser;
private boolean mUsbCharging;
private boolean mHideUsbNotification;
private boolean mSupportsAllCombinations;
- private String mScreenUnlockedFunctions = UsbManager.USB_FUNCTION_NONE;
private boolean mScreenLocked;
- protected boolean mCurrentUsbFunctionsRequested;
+ private boolean mSystemReady;
+ private Intent mBroadcastedIntent;
+ private boolean mPendingBootBroadcast;
+ private boolean mAudioSourceEnabled;
+ private boolean mMidiEnabled;
+ private int mMidiCard;
+ private int mMidiDevice;
+
+ private final Context mContext;
+ private final UsbDebuggingManager mDebuggingManager;
+ private final UsbAlsaManager mUsbAlsaManager;
+ private final UsbSettingsManager mSettingsManager;
+ private NotificationManager mNotificationManager;
+
+ protected long mScreenUnlockedFunctions;
+ protected boolean mAdbEnabled;
+ protected boolean mBootCompleted;
+ protected boolean mCurrentFunctionsApplied;
+ protected boolean mUseUsbNotification;
+ protected long mCurrentFunctions;
+ protected final UsbDeviceManager mUsbDeviceManager;
+ protected final ContentResolver mContentResolver;
+ protected SharedPreferences mSettings;
+ protected int mCurrentUser;
protected boolean mCurrentUsbFunctionsReceived;
/**
@@ -494,31 +482,36 @@
*/
protected static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
- public UsbHandler(Looper looper) {
+ UsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager,
+ UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
+ UsbSettingsManager settingsManager) {
super(looper);
+ mContext = context;
+ mDebuggingManager = debuggingManager;
+ mUsbDeviceManager = deviceManager;
+ mUsbAlsaManager = alsaManager;
+ mSettingsManager = settingsManager;
+ mContentResolver = context.getContentResolver();
mCurrentUser = ActivityManager.getCurrentUser();
+ mScreenUnlockedFunctions = UsbManager.FUNCTION_NONE;
mScreenLocked = true;
/*
* Use the normal bootmode persistent prop to maintain state of adb across
* all boot modes.
*/
- mAdbEnabled = UsbManager.containsFunction(
- SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY),
- UsbManager.USB_FUNCTION_ADB);
+ mAdbEnabled = UsbHandlerLegacy.containsFunction(getSystemProperty(
+ USB_PERSISTENT_CONFIG_PROPERTY, ""), UsbManager.USB_FUNCTION_ADB);
- /*
- * Previous versions can set persist config to mtp/ptp but it does not
- * get reset on OTA. Reset the property here instead.
- */
- String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
- if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)
- || UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_PTP)) {
- SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
- UsbManager.removeFunction(UsbManager.removeFunction(persisted,
- UsbManager.USB_FUNCTION_MTP), UsbManager.USB_FUNCTION_PTP));
- }
+ // We do not show the USB notification if the primary volume supports mass storage.
+ // The legacy mass storage UI will be used instead.
+ final StorageManager storageManager = StorageManager.from(mContext);
+ final StorageVolume primary = storageManager.getPrimaryVolume();
+
+ boolean massStorageSupported = primary != null && primary.allowMassStorage();
+ mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_usbChargingMessage);
}
public void sendMessage(int what, boolean arg) {
@@ -602,20 +595,14 @@
if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
if (enable != mAdbEnabled) {
mAdbEnabled = enable;
- String oldFunctions = mCurrentFunctions;
- // Persist the adb setting
- String newFunction = applyAdbFunction(SystemProperties.get(
- USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_NONE));
- SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunction);
-
- // Remove mtp from the config if file transfer is not enabled
- if (oldFunctions.equals(UsbManager.USB_FUNCTION_MTP) &&
- !mUsbDataUnlocked && enable) {
- oldFunctions = UsbManager.USB_FUNCTION_NONE;
+ if (enable) {
+ setSystemProperty(USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_ADB);
+ } else {
+ setSystemProperty(USB_PERSISTENT_CONFIG_PROPERTY, "");
}
- setEnabledFunctions(oldFunctions, true, mUsbDataUnlocked);
+ setEnabledFunctions(mCurrentFunctions, true);
updateAdbNotification(false);
}
@@ -624,21 +611,7 @@
}
}
- protected String applyAdbFunction(String functions) {
- // Do not pass null pointer to the UsbManager.
- // There isnt a check there.
- if (functions == null) {
- functions = "";
- }
- if (mAdbEnabled) {
- functions = UsbManager.addFunction(functions, UsbManager.USB_FUNCTION_ADB);
- } else {
- functions = UsbManager.removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
- }
- return functions;
- }
-
- private boolean isUsbTransferAllowed() {
+ protected boolean isUsbTransferAllowed() {
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
return !userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER);
}
@@ -650,12 +623,13 @@
if (mConfigured && enteringAccessoryMode) {
// successfully entered accessory mode
- if (mAccessoryStrings != null) {
- mCurrentAccessory = new UsbAccessory(mAccessoryStrings);
+ String[] accessoryStrings = mUsbDeviceManager.getAccessoryStrings();
+ if (accessoryStrings != null) {
+ mCurrentAccessory = new UsbAccessory(accessoryStrings);
Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
// defer accessoryAttached if system is not ready
if (mBootCompleted) {
- getCurrentSettings().accessoryAttached(mCurrentAccessory);
+ mUsbDeviceManager.getCurrentSettings().accessoryAttached(mCurrentAccessory);
} // else handle in boot completed
} else {
Slog.e(TAG, "nativeGetAccessoryStrings failed");
@@ -673,17 +647,24 @@
// make sure accessory mode is off
// and restore default functions
Slog.d(TAG, "exited USB accessory mode");
- setEnabledFunctions(null, false, false);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
if (mCurrentAccessory != null) {
if (mBootCompleted) {
mSettingsManager.usbAccessoryRemoved(mCurrentAccessory);
}
mCurrentAccessory = null;
- mAccessoryStrings = null;
}
}
+ protected SharedPreferences getPinnedSharedPrefs(Context context) {
+ final File prefsFile = new File(new File(
+ Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
+ context.getUserId(), context.getPackageName()), "shared_prefs"),
+ UsbDeviceManager.class.getSimpleName() + ".xml");
+ return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
+ }
+
private boolean isUsbStateChanged(Intent intent) {
final Set<String> keySet = intent.getExtras().keySet();
if (mBroadcastedIntent == null) {
@@ -706,7 +687,8 @@
return false;
}
- protected void updateUsbStateBroadcastIfNeeded(boolean configChanged) {
+ protected void updateUsbStateBroadcastIfNeeded(long functions,
+ boolean configChanged) {
// send a sticky broadcast containing current USB state
Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
@@ -716,18 +698,14 @@
intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected);
intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
intent.putExtra(UsbManager.USB_DATA_UNLOCKED,
- isUsbTransferAllowed() && mUsbDataUnlocked);
+ isUsbTransferAllowed() && isUsbDataTransferActive(mCurrentFunctions));
intent.putExtra(UsbManager.USB_CONFIG_CHANGED, configChanged);
- if (mCurrentFunctions != null) {
- String[] functions = mCurrentFunctions.split(",");
- for (int i = 0; i < functions.length; i++) {
- final String function = functions[i];
- if (UsbManager.USB_FUNCTION_NONE.equals(function)) {
- continue;
- }
- intent.putExtra(function, true);
- }
+ long remainingFunctions = functions;
+ while (remainingFunctions != 0) {
+ intent.putExtra(UsbManager.usbFunctionsToString(
+ Long.highestOneBit(remainingFunctions)), true);
+ remainingFunctions -= Long.highestOneBit(remainingFunctions);
}
// send broadcast intent only if the USB state has changed
@@ -739,18 +717,21 @@
}
if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras());
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ sendStickyBroadcast(intent);
mBroadcastedIntent = intent;
}
+ protected void sendStickyBroadcast(Intent intent) {
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
private void updateUsbFunctions() {
updateAudioSourceFunction();
updateMidiFunction();
}
private void updateAudioSourceFunction() {
- boolean enabled = UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_AUDIO_SOURCE);
+ boolean enabled = (mCurrentFunctions & UsbManager.FUNCTION_AUDIO_SOURCE) != 0;
if (enabled != mAudioSourceEnabled) {
int card = -1;
int device = -1;
@@ -775,8 +756,7 @@
}
private void updateMidiFunction() {
- boolean enabled = UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_MIDI);
+ boolean enabled = (mCurrentFunctions & UsbManager.FUNCTION_MIDI) != 0;
if (enabled != mMidiEnabled) {
if (enabled) {
Scanner scanner = null;
@@ -800,11 +780,21 @@
}
private void setScreenUnlockedFunctions() {
- setEnabledFunctions(mScreenUnlockedFunctions, false,
- UsbManager.containsFunction(mScreenUnlockedFunctions,
- UsbManager.USB_FUNCTION_MTP)
- || UsbManager.containsFunction(mScreenUnlockedFunctions,
- UsbManager.USB_FUNCTION_PTP));
+ setEnabledFunctions(mScreenUnlockedFunctions, false);
+ }
+
+ /**
+ * Returns the functions that are passed down to the low level driver once adb and
+ * charging are accounted for.
+ */
+ long getAppliedFunctions(long functions) {
+ if (functions == UsbManager.FUNCTION_NONE) {
+ return getChargingFunctions();
+ }
+ if (mAdbEnabled) {
+ return functions | UsbManager.FUNCTION_ADB;
+ }
+ return functions;
}
@Override
@@ -817,10 +807,10 @@
updateUsbNotification(false);
updateAdbNotification(false);
if (mBootCompleted) {
- updateUsbStateBroadcastIfNeeded(false);
+ updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions),
+ false);
}
- if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_ACCESSORY)) {
+ if ((mCurrentFunctions & UsbManager.FUNCTION_ACCESSORY) != 0) {
updateCurrentAccessory();
}
if (mBootCompleted) {
@@ -828,11 +818,10 @@
&& !hasMessages(MSG_FUNCTION_SWITCH_TIMEOUT)) {
// restore defaults when USB is disconnected
if (!mScreenLocked
- && !UsbManager.USB_FUNCTION_NONE.equals(
- mScreenUnlockedFunctions)) {
+ && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
setScreenUnlockedFunctions();
} else {
- setEnabledFunctions(null, !mAdbEnabled, false);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, !mAdbEnabled);
}
}
updateUsbFunctions();
@@ -867,7 +856,8 @@
updateUsbNotification(false);
if (mBootCompleted) {
if (mHostConnected || prevHostConnected) {
- updateUsbStateBroadcastIfNeeded(false);
+ updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions),
+ false);
}
} else {
mPendingBootBroadcast = true;
@@ -913,17 +903,17 @@
setAdbEnabled(msg.arg1 == 1);
break;
case MSG_SET_CURRENT_FUNCTIONS:
- String functions = (String) msg.obj;
- setEnabledFunctions(functions, false, msg.arg1 == 1);
+ long functions = (Long) msg.obj;
+ setEnabledFunctions(functions, false);
break;
case MSG_SET_SCREEN_UNLOCKED_FUNCTIONS:
- mScreenUnlockedFunctions = (String) msg.obj;
+ mScreenUnlockedFunctions = (Long) msg.obj;
SharedPreferences.Editor editor = mSettings.edit();
editor.putString(String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF,
- mCurrentUser), mScreenUnlockedFunctions);
+ mCurrentUser),
+ UsbManager.usbFunctionsToString(mScreenUnlockedFunctions));
editor.commit();
- if (!mScreenLocked && !UsbManager.USB_FUNCTION_NONE.equals(
- mScreenUnlockedFunctions)) {
+ if (!mScreenLocked && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
// If the screen is unlocked, also set current functions.
setScreenUnlockedFunctions();
}
@@ -936,22 +926,21 @@
if (mSettings == null && !mScreenLocked) {
// Shared preferences aren't accessible until the user has been unlocked.
mSettings = getPinnedSharedPrefs(mContext);
- mScreenUnlockedFunctions = mSettings.getString(
+ mScreenUnlockedFunctions = UsbManager.usbFunctionsFromString(
+ mSettings.getString(
String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
- UsbManager.USB_FUNCTION_NONE);
+ ""));
}
if (!mBootCompleted) {
break;
}
if (mScreenLocked) {
if (!mConnected) {
- setEnabledFunctions(null, false, false);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
}
} else {
- if (!UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)
- && (UsbManager.USB_FUNCTION_ADB.equals(mCurrentFunctions)
- || (UsbManager.USB_FUNCTION_MTP.equals(mCurrentFunctions)
- && !mUsbDataUnlocked))) {
+ if (mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE
+ && mCurrentFunctions == UsbManager.FUNCTION_NONE) {
// Set the screen unlocked functions if current function is charging.
setScreenUnlockedFunctions();
}
@@ -959,13 +948,24 @@
break;
case MSG_UPDATE_USER_RESTRICTIONS:
// Restart the USB stack if USB transfer is enabled but no longer allowed.
- final boolean forceRestart = mUsbDataUnlocked
- && isUsbDataTransferActive()
- && !isUsbTransferAllowed();
- setEnabledFunctions(
- mCurrentFunctions, forceRestart, mUsbDataUnlocked && !forceRestart);
+ if (isUsbDataTransferActive(mCurrentFunctions) && !isUsbTransferAllowed()) {
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, true);
+ }
break;
case MSG_SYSTEM_READY:
+ mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ // Ensure that the notification channels are set up
+ if (isTv()) {
+ // TV-specific notification channel
+ mNotificationManager.createNotificationChannel(
+ new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV,
+ mContext.getString(
+ com.android.internal.R.string
+ .adb_debugging_notification_channel_tv),
+ NotificationManager.IMPORTANCE_HIGH));
+ }
mSystemReady = true;
finishBoot();
break;
@@ -984,10 +984,14 @@
}
mCurrentUser = msg.arg1;
mScreenLocked = true;
- mScreenUnlockedFunctions = mSettings.getString(
- String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
- UsbManager.USB_FUNCTION_NONE);
- setEnabledFunctions(null, false, false);
+ if (mSettings != null) {
+ mScreenUnlockedFunctions = UsbManager.usbFunctionsFromString(
+ mSettings.getString(
+ String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF,
+ mCurrentUser),
+ ""));
+ }
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
}
break;
}
@@ -995,9 +999,7 @@
if (DEBUG) {
Slog.v(TAG, "Accessory mode enter timeout: " + mConnected);
}
- if (!mConnected || !UsbManager.containsFunction(
- mCurrentFunctions,
- UsbManager.USB_FUNCTION_ACCESSORY)) {
+ if (!mConnected || (mCurrentFunctions & UsbManager.FUNCTION_ACCESSORY) == 0) {
notifyAccessoryModeExit();
}
break;
@@ -1008,17 +1010,17 @@
protected void finishBoot() {
if (mBootCompleted && mCurrentUsbFunctionsReceived && mSystemReady) {
if (mPendingBootBroadcast) {
- updateUsbStateBroadcastIfNeeded(false);
+ updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions), false);
mPendingBootBroadcast = false;
}
if (!mScreenLocked
- && !UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)) {
+ && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
setScreenUnlockedFunctions();
} else {
- setEnabledFunctions(null, false, false);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
}
if (mCurrentAccessory != null) {
- getCurrentSettings().accessoryAttached(mCurrentAccessory);
+ mUsbDeviceManager.getCurrentSettings().accessoryAttached(mCurrentAccessory);
}
if (mDebuggingManager != null) {
mDebuggingManager.setAdbEnabled(mAdbEnabled);
@@ -1026,8 +1028,8 @@
// make sure the ADB_ENABLED setting value matches the current state
try {
- Settings.Global.putInt(mContentResolver,
- Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
+ putGlobalSettings(mContentResolver, Settings.Global.ADB_ENABLED,
+ mAdbEnabled ? 1 : 0);
} catch (SecurityException e) {
// If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't
// be changed.
@@ -1040,9 +1042,9 @@
}
}
- private boolean isUsbDataTransferActive() {
- return UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)
- || UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP);
+ protected boolean isUsbDataTransferActive(long functions) {
+ return (functions & UsbManager.FUNCTION_MTP) != 0
+ || (functions & UsbManager.FUNCTION_PTP) != 0;
}
public UsbAccessory getCurrentAccessory() {
@@ -1051,7 +1053,7 @@
protected void updateUsbNotification(boolean force) {
if (mNotificationManager == null || !mUseUsbNotification
- || ("0".equals(SystemProperties.get("persist.charging.notify")))) {
+ || ("0".equals(getSystemProperty("persist.charging.notify", "")))) {
return;
}
@@ -1070,30 +1072,37 @@
int id = 0;
int titleRes = 0;
Resources r = mContext.getResources();
+ CharSequence message = r.getText(
+ com.android.internal.R.string.usb_notification_message);
if (mAudioAccessoryConnected && !mAudioAccessorySupported) {
titleRes = com.android.internal.R.string.usb_unsupported_audio_accessory_title;
id = SystemMessage.NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED;
} else if (mConnected) {
- if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_MTP) && mUsbDataUnlocked) {
+ if (mCurrentFunctions == UsbManager.FUNCTION_MTP) {
titleRes = com.android.internal.R.string.usb_mtp_notification_title;
id = SystemMessage.NOTE_USB_MTP;
- } else if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_PTP) && mUsbDataUnlocked) {
+ } else if (mCurrentFunctions == UsbManager.FUNCTION_PTP) {
titleRes = com.android.internal.R.string.usb_ptp_notification_title;
id = SystemMessage.NOTE_USB_PTP;
- } else if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_MIDI)) {
+ } else if (mCurrentFunctions == UsbManager.FUNCTION_MIDI) {
titleRes = com.android.internal.R.string.usb_midi_notification_title;
id = SystemMessage.NOTE_USB_MIDI;
- } else if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_ACCESSORY)) {
+ } else if (mCurrentFunctions == UsbManager.FUNCTION_RNDIS) {
+ titleRes = com.android.internal.R.string.usb_tether_notification_title;
+ id = SystemMessage.NOTE_USB_TETHER;
+ } else if (mCurrentFunctions == UsbManager.FUNCTION_ACCESSORY) {
titleRes = com.android.internal.R.string.usb_accessory_notification_title;
id = SystemMessage.NOTE_USB_ACCESSORY;
- } else if (mSourcePower) {
- titleRes = com.android.internal.R.string.usb_supplying_notification_title;
- id = SystemMessage.NOTE_USB_SUPPLYING;
- } else {
+ }
+ if (mSourcePower) {
+ if (titleRes != 0) {
+ message = r.getText(
+ com.android.internal.R.string.usb_power_notification_message);
+ } else {
+ titleRes = com.android.internal.R.string.usb_supplying_notification_title;
+ id = SystemMessage.NOTE_USB_SUPPLYING;
+ }
+ } else if (titleRes == 0) {
titleRes = com.android.internal.R.string.usb_charging_notification_title;
id = SystemMessage.NOTE_USB_CHARGING;
}
@@ -1113,7 +1122,6 @@
mUsbNotificationId = 0;
}
if (id != 0) {
- CharSequence message;
CharSequence title = r.getText(titleRes);
PendingIntent pi;
String channel;
@@ -1123,12 +1131,10 @@
.usb_unsupported_audio_accessory_title) {
Intent intent = Intent.makeRestartActivityTask(
new ComponentName("com.android.settings",
- "com.android.settings.deviceinfo.UsbModeChooserActivity"));
+ "com.android.settings.Settings$UsbDetailsActivity"));
pi = PendingIntent.getActivityAsUser(mContext, 0,
intent, 0, null, UserHandle.CURRENT);
channel = SystemNotificationChannels.USB;
- message = r.getText(
- com.android.internal.R.string.usb_notification_message);
} else {
final Intent intent = new Intent();
intent.setClassName("com.android.settings",
@@ -1184,7 +1190,7 @@
final int titleRes = com.android.internal.R.string.adb_active_notification_title;
if (mAdbEnabled && mConnected) {
- if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
+ if ("0".equals(getSystemProperty("persist.adb.notify", ""))) return;
if (force && mAdbNotificationShown) {
mAdbNotificationShown = false;
@@ -1230,20 +1236,41 @@
}
}
- protected String getChargingFunctions() {
+ private boolean isTv() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ }
+
+ protected long getChargingFunctions() {
// if ADB is enabled, reset functions to ADB
// else enable MTP as usual.
if (mAdbEnabled) {
- return UsbManager.USB_FUNCTION_ADB;
+ return UsbManager.FUNCTION_ADB;
} else {
- return UsbManager.USB_FUNCTION_MTP;
+ return UsbManager.FUNCTION_MTP;
}
}
- public boolean isFunctionEnabled(String function) {
- return UsbManager.containsFunction(mCurrentFunctions, function);
+ protected void setSystemProperty(String prop, String val) {
+ SystemProperties.set(prop, val);
}
+ protected String getSystemProperty(String prop, String def) {
+ return SystemProperties.get(prop, def);
+ }
+
+ protected void putGlobalSettings(ContentResolver contentResolver, String setting, int val) {
+ Settings.Global.putInt(contentResolver, setting, val);
+ }
+
+ public long getEnabledFunctions() {
+ return mCurrentFunctions;
+ }
+
+ public long getScreenUnlockedFunctions() {
+ return mScreenUnlockedFunctions;
+ }
+
+
public void dump(IndentingPrintWriter pw) {
pw.println("USB Device State:");
pw.println(" mCurrentFunctions: " + mCurrentFunctions);
@@ -1252,7 +1279,6 @@
pw.println(" mScreenLocked: " + mScreenLocked);
pw.println(" mConnected: " + mConnected);
pw.println(" mConfigured: " + mConfigured);
- pw.println(" mUsbDataUnlocked: " + mUsbDataUnlocked);
pw.println(" mCurrentAccessory: " + mCurrentAccessory);
pw.println(" mHostConnected: " + mHostConnected);
pw.println(" mSourcePower: " + mSourcePower);
@@ -1275,12 +1301,10 @@
/**
* Evaluates USB function policies and applies the change accordingly.
*/
- protected abstract void setEnabledFunctions(String functions, boolean forceRestart,
- boolean usbDataUnlocked);
-
+ protected abstract void setEnabledFunctions(long functions, boolean forceRestart);
}
- private final class UsbHandlerLegacy extends UsbHandler {
+ private static final class UsbHandlerLegacy extends UsbHandler {
/**
* The non-persistent property which stores the current USB settings.
*/
@@ -1293,46 +1317,44 @@
private HashMap<String, HashMap<String, Pair<String, String>>> mOemModeMap;
private String mCurrentOemFunctions;
+ private String mCurrentFunctionsStr;
+ private boolean mUsbDataUnlocked;
- UsbHandlerLegacy(Looper looper, Context context) {
- super(looper);
+ UsbHandlerLegacy(Looper looper, Context context, UsbDeviceManager deviceManager,
+ UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
+ UsbSettingsManager settingsManager) {
+ super(looper, context, deviceManager, debuggingManager, alsaManager, settingsManager);
try {
readOemUsbOverrideConfig(context);
// Restore default functions.
- mCurrentOemFunctions = SystemProperties.get(getPersistProp(false),
+ mCurrentOemFunctions = getSystemProperty(getPersistProp(false),
UsbManager.USB_FUNCTION_NONE);
if (isNormalBoot()) {
- mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
+ mCurrentFunctionsStr = getSystemProperty(USB_CONFIG_PROPERTY,
UsbManager.USB_FUNCTION_NONE);
- mCurrentFunctionsApplied = mCurrentFunctions.equals(
- SystemProperties.get(USB_STATE_PROPERTY));
+ mCurrentFunctionsApplied = mCurrentFunctionsStr.equals(
+ getSystemProperty(USB_STATE_PROPERTY, UsbManager.USB_FUNCTION_NONE));
} else {
- mCurrentFunctions = SystemProperties.get(getPersistProp(true),
+ mCurrentFunctionsStr = getSystemProperty(getPersistProp(true),
UsbManager.USB_FUNCTION_NONE);
- mCurrentFunctionsApplied = SystemProperties.get(USB_CONFIG_PROPERTY,
+ mCurrentFunctionsApplied = getSystemProperty(USB_CONFIG_PROPERTY,
UsbManager.USB_FUNCTION_NONE).equals(
- SystemProperties.get(USB_STATE_PROPERTY));
+ getSystemProperty(USB_STATE_PROPERTY, UsbManager.USB_FUNCTION_NONE));
}
+ // Mask out adb, since it is stored in mAdbEnabled
+ mCurrentFunctions = UsbManager.usbFunctionsFromString(mCurrentFunctionsStr)
+ & ~UsbManager.FUNCTION_ADB;
mCurrentUsbFunctionsReceived = true;
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
-
- // register observer to listen for settings changes
- mContentResolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
- false, new AdbSettingsObserver());
-
- // Watch for USB configuration changes
- mUEventObserver.startObserving(USB_STATE_MATCH);
- mUEventObserver.startObserving(ACCESSORY_START_MATCH);
} catch (Exception e) {
Slog.e(TAG, "Error initializing UsbHandler", e);
}
}
private void readOemUsbOverrideConfig(Context context) {
- String[] configList = mContext.getResources().getStringArray(
+ String[] configList = context.getResources().getStringArray(
com.android.internal.R.array.config_oemUsbModeOverride);
if (configList != null) {
@@ -1367,7 +1389,7 @@
return usbFunctions;
}
- String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
+ String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
Slog.d(TAG, "applyOemOverride usbfunctions=" + usbFunctions + " bootmode=" + bootMode);
Map<String, Pair<String, String>> overridesMap =
@@ -1386,25 +1408,22 @@
if (!overrideFunctions.second.equals("")) {
String newFunction;
if (mAdbEnabled) {
- newFunction = UsbManager.addFunction(overrideFunctions.second,
+ newFunction = addFunction(overrideFunctions.second,
UsbManager.USB_FUNCTION_ADB);
} else {
newFunction = overrideFunctions.second;
}
Slog.d(TAG, "OEM USB override persisting: " + newFunction + "in prop: "
+ getPersistProp(false));
- SystemProperties.set(getPersistProp(false),
- newFunction);
+ setSystemProperty(getPersistProp(false), newFunction);
}
return overrideFunctions.first;
} else if (mAdbEnabled) {
- String newFunction = UsbManager.addFunction(UsbManager.USB_FUNCTION_NONE,
+ String newFunction = addFunction(UsbManager.USB_FUNCTION_NONE,
UsbManager.USB_FUNCTION_ADB);
- SystemProperties.set(getPersistProp(false),
- newFunction);
+ setSystemProperty(getPersistProp(false), newFunction);
} else {
- SystemProperties.set(getPersistProp(false),
- UsbManager.USB_FUNCTION_NONE);
+ setSystemProperty(getPersistProp(false), UsbManager.USB_FUNCTION_NONE);
}
}
// return passed in functions as is.
@@ -1417,7 +1436,7 @@
String value = null;
for (int i = 0; i < 20; i++) {
// State transition is done when sys.usb.state is set to the new configuration
- value = SystemProperties.get(USB_STATE_PROPERTY);
+ value = getSystemProperty(USB_STATE_PROPERTY, "");
if (state.equals(value)) return true;
SystemClock.sleep(50);
}
@@ -1432,14 +1451,14 @@
* we always set it due to b/23631400, where adbd was getting killed
* and not restarted due to property timeouts on some devices
*/
- SystemProperties.set(USB_CONFIG_PROPERTY, config);
+ setSystemProperty(USB_CONFIG_PROPERTY, config);
}
@Override
- protected void setEnabledFunctions(String functions, boolean forceRestart,
- boolean usbDataUnlocked) {
+ protected void setEnabledFunctions(long usbFunctions, boolean forceRestart) {
+ boolean usbDataUnlocked = isUsbDataTransferActive(usbFunctions);
if (DEBUG) {
- Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
+ Slog.d(TAG, "setEnabledFunctions functions=" + usbFunctions + ", "
+ "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked);
}
@@ -1452,9 +1471,9 @@
/**
* Try to set the enabled functions.
*/
- final String oldFunctions = mCurrentFunctions;
+ final long oldFunctions = mCurrentFunctions;
final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
- if (trySetEnabledFunctions(functions, forceRestart)) {
+ if (trySetEnabledFunctions(usbFunctions, forceRestart)) {
return;
}
@@ -1464,7 +1483,7 @@
* user restrictions independently of any other new functions we were
* trying to activate.
*/
- if (oldFunctionsApplied && !oldFunctions.equals(functions)) {
+ if (oldFunctionsApplied && oldFunctions != usbFunctions) {
Slog.e(TAG, "Failsafe 1: Restoring previous USB functions.");
if (trySetEnabledFunctions(oldFunctions, false)) {
return;
@@ -1475,7 +1494,7 @@
* Still didn't work. Try to restore the default functions.
*/
Slog.e(TAG, "Failsafe 2: Restoring default USB functions.");
- if (trySetEnabledFunctions(null, false)) {
+ if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
return;
}
@@ -1484,7 +1503,7 @@
* Try to get ADB working if enabled.
*/
Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled).");
- if (trySetEnabledFunctions(UsbManager.USB_FUNCTION_NONE, false)) {
+ if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
return;
}
@@ -1495,30 +1514,49 @@
}
private boolean isNormalBoot() {
- String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
+ String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
return bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown");
}
- private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
+ protected String applyAdbFunction(String functions) {
+ // Do not pass null pointer to the UsbManager.
+ // There isn't a check there.
+ if (functions == null) {
+ functions = "";
+ }
+ if (mAdbEnabled) {
+ functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
+ } else {
+ functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
+ }
+ return functions;
+ }
+
+ private boolean trySetEnabledFunctions(long usbFunctions, boolean forceRestart) {
+ String functions = null;
+ if (usbFunctions != UsbManager.FUNCTION_NONE) {
+ functions = UsbManager.usbFunctionsToString(usbFunctions);
+ }
+ mCurrentFunctions = usbFunctions;
if (functions == null || applyAdbFunction(functions)
.equals(UsbManager.USB_FUNCTION_NONE)) {
- functions = getChargingFunctions();
+ functions = UsbManager.usbFunctionsToString(getChargingFunctions());
}
functions = applyAdbFunction(functions);
String oemFunctions = applyOemOverrideFunction(functions);
- if (!isNormalBoot() && !mCurrentFunctions.equals(functions)) {
- SystemProperties.set(getPersistProp(true), functions);
+ if (!isNormalBoot() && !mCurrentFunctionsStr.equals(functions)) {
+ setSystemProperty(getPersistProp(true), functions);
}
if ((!functions.equals(oemFunctions)
&& !mCurrentOemFunctions.equals(oemFunctions))
- || !mCurrentFunctions.equals(functions)
+ || !mCurrentFunctionsStr.equals(functions)
|| !mCurrentFunctionsApplied
|| forceRestart) {
Slog.i(TAG, "Setting USB config to " + functions);
- mCurrentFunctions = functions;
+ mCurrentFunctionsStr = functions;
mCurrentOemFunctions = oemFunctions;
mCurrentFunctionsApplied = false;
@@ -1538,12 +1576,12 @@
setUsbConfig(oemFunctions);
if (mBootCompleted
- && (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
- || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
+ && (containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
+ || containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
/**
* Start up dependent services.
*/
- updateUsbStateBroadcastIfNeeded(true);
+ updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions), true);
}
if (!waitForState(oemFunctions)) {
@@ -1557,7 +1595,7 @@
}
private String getPersistProp(boolean functions) {
- String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
+ String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
String persistProp = USB_PERSISTENT_CONFIG_PROPERTY;
if (!(bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"))) {
if (functions) {
@@ -1568,9 +1606,54 @@
}
return persistProp;
}
+
+ private static String addFunction(String functions, String function) {
+ if (UsbManager.USB_FUNCTION_NONE.equals(functions)) {
+ return function;
+ }
+ if (!containsFunction(functions, function)) {
+ if (functions.length() > 0) {
+ functions += ",";
+ }
+ functions += function;
+ }
+ return functions;
+ }
+
+ private static String removeFunction(String functions, String function) {
+ String[] split = functions.split(",");
+ for (int i = 0; i < split.length; i++) {
+ if (function.equals(split[i])) {
+ split[i] = null;
+ }
+ }
+ if (split.length == 1 && split[0] == null) {
+ return UsbManager.USB_FUNCTION_NONE;
+ }
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < split.length; i++) {
+ String s = split[i];
+ if (s != null) {
+ if (builder.length() > 0) {
+ builder.append(",");
+ }
+ builder.append(s);
+ }
+ }
+ return builder.toString();
+ }
+
+ static boolean containsFunction(String functions, String function) {
+ int index = functions.indexOf(function);
+ if (index < 0) return false;
+ if (index > 0 && functions.charAt(index - 1) != ',') return false;
+ int charAfter = index + function.length();
+ if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
+ return true;
+ }
}
- private final class UsbHandlerHal extends UsbHandler {
+ private static final class UsbHandlerHal extends UsbHandler {
/**
* Proxy object for the usb gadget hal daemon.
@@ -1627,9 +1710,12 @@
*/
protected static final String ADBD = "adbd";
+ protected boolean mCurrentUsbFunctionsRequested;
- UsbHandlerHal(Looper looper) {
- super(looper);
+ UsbHandlerHal(Looper looper, Context context, UsbDeviceManager deviceManager,
+ UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
+ UsbSettingsManager settingsManager) {
+ super(looper, context, deviceManager, debuggingManager, alsaManager, settingsManager);
try {
ServiceNotification serviceNotification = new ServiceNotification();
@@ -1645,25 +1731,12 @@
mGadgetProxy = IUsbGadget.getService(true);
mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
USB_GADGET_HAL_DEATH_COOKIE);
- mCurrentFunctions = UsbManager.USB_FUNCTION_NONE;
+ mCurrentFunctions = UsbManager.FUNCTION_NONE;
mGadgetProxy.getCurrentUsbFunctions(new UsbGadgetCallback());
mCurrentUsbFunctionsRequested = true;
}
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
-
- /**
- * Register observer to listen for settings changes.
- */
- mContentResolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
- false, new AdbSettingsObserver());
-
- /**
- * Watch for USB configuration changes.
- */
- mUEventObserver.startObserving(USB_STATE_MATCH);
- mUEventObserver.startObserving(ACCESSORY_START_MATCH);
} catch (NoSuchElementException e) {
Slog.e(TAG, "Usb gadget hal not found", e);
} catch (RemoteException e) {
@@ -1696,7 +1769,7 @@
mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
USB_GADGET_HAL_DEATH_COOKIE);
if (!mCurrentFunctionsApplied) {
- setCurrentFunctions(mCurrentFunctions, mUsbDataUnlocked);
+ setEnabledFunctions(mCurrentFunctions, false);
}
} catch (NoSuchElementException e) {
Slog.e(TAG, "Usb gadget hal not found", e);
@@ -1711,12 +1784,12 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SET_CHARGING_FUNCTIONS:
- setEnabledFunctions(null, false, mUsbDataUnlocked);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
break;
case MSG_SET_FUNCTIONS_TIMEOUT:
Slog.e(TAG, "Set functions timed out! no reply from usb hal");
if (msg.arg1 != 1) {
- setEnabledFunctions(null, false, mUsbDataUnlocked);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
}
break;
case MSG_GET_CURRENT_USB_FUNCTIONS:
@@ -1725,7 +1798,8 @@
if (mCurrentUsbFunctionsRequested) {
Slog.e(TAG, "updating mCurrentFunctions");
- mCurrentFunctions = functionListToString((Long) msg.obj);
+ // Mask out adb, since it is stored in mAdbEnabled
+ mCurrentFunctions = ((Long) msg.obj) & ~UsbManager.FUNCTION_ADB;
Slog.e(TAG,
"mCurrentFunctions:" + mCurrentFunctions + "applied:" + msg.arg1);
mCurrentFunctionsApplied = msg.arg1 == 1;
@@ -1737,7 +1811,7 @@
* Dont force to default when the configuration is already set to default.
*/
if (msg.arg1 != 1) {
- setEnabledFunctions(null, !mAdbEnabled, false);
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, !mAdbEnabled);
}
break;
default:
@@ -1789,70 +1863,7 @@
}
}
- private long stringToFunctionList(String config) {
- long functionsMask = 0;
- String[] functions = config.split(",");
- for (int i = 0; i < functions.length; i++) {
- switch (functions[i]) {
- case "none":
- functionsMask |= GadgetFunction.NONE;
- break;
- case "adb":
- functionsMask |= GadgetFunction.ADB;
- break;
- case "mtp":
- functionsMask |= GadgetFunction.MTP;
- break;
- case "ptp":
- functionsMask |= GadgetFunction.PTP;
- break;
- case "midi":
- functionsMask |= GadgetFunction.MIDI;
- break;
- case "accessory":
- functionsMask |= GadgetFunction.ACCESSORY;
- break;
- case "rndis":
- functionsMask |= GadgetFunction.RNDIS;
- break;
- }
- }
- return functionsMask;
- }
-
- private String functionListToString(Long functionList) {
- StringJoiner functions = new StringJoiner(",");
- if (functionList == GadgetFunction.NONE) {
- functions.add("none");
- return functions.toString();
- }
- if ((functionList & GadgetFunction.ADB) != 0) {
- functions.add("adb");
- }
- if ((functionList & GadgetFunction.MTP) != 0) {
- functions.add("mtp");
- }
- if ((functionList & GadgetFunction.PTP) != 0) {
- functions.add("ptp");
- }
- if ((functionList & GadgetFunction.MIDI) != 0) {
- functions.add("midi");
- }
- if ((functionList & GadgetFunction.ACCESSORY) != 0) {
- functions.add("accessory");
- }
- if ((functionList & GadgetFunction.RNDIS) != 0) {
- functions.add("rndis");
- }
- /**
- * Remove the trailing comma.
- */
- return functions.toString();
- }
-
-
- private void setUsbConfig(String config, boolean chargingFunctions) {
- Long functions = stringToFunctionList(config);
+ private void setUsbConfig(long config, boolean chargingFunctions) {
if (true) Slog.d(TAG, "setUsbConfig(" + config + ") request:" + ++mCurrentRequest);
/**
* Cancel any ongoing requests, if present.
@@ -1867,20 +1878,20 @@
return;
}
try {
- if ((functions & GadgetFunction.ADB) != 0) {
+ if ((config & UsbManager.FUNCTION_ADB) != 0) {
/**
* Start adbd if ADB function is included in the configuration.
*/
- SystemProperties.set(CTL_START, ADBD);
+ setSystemProperty(CTL_START, ADBD);
} else {
/**
* Stop adbd otherwise.
*/
- SystemProperties.set(CTL_STOP, ADBD);
+ setSystemProperty(CTL_STOP, ADBD);
}
UsbGadgetCallback usbGadgetCallback = new UsbGadgetCallback(mCurrentRequest,
- functions, chargingFunctions);
- mGadgetProxy.setCurrentUsbFunctions(functions, usbGadgetCallback,
+ config, chargingFunctions);
+ mGadgetProxy.setCurrentUsbFunctions(config, usbGadgetCallback,
SET_FUNCTIONS_TIMEOUT_MS - SET_FUNCTIONS_LEEWAY_MS);
sendMessageDelayed(MSG_SET_FUNCTIONS_TIMEOUT, chargingFunctions,
SET_FUNCTIONS_TIMEOUT_MS);
@@ -1894,49 +1905,29 @@
}
@Override
- protected void setEnabledFunctions(String functions, boolean forceRestart,
- boolean usbDataUnlocked) {
+ protected void setEnabledFunctions(long functions, boolean forceRestart) {
if (DEBUG) {
Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
- + "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked);
+ + "forceRestart=" + forceRestart);
}
-
- if (usbDataUnlocked != mUsbDataUnlocked) {
- mUsbDataUnlocked = usbDataUnlocked;
- updateUsbNotification(false);
- forceRestart = true;
- }
-
- trySetEnabledFunctions(functions, forceRestart);
- }
-
- private void trySetEnabledFunctions(String functions, boolean forceRestart) {
- boolean chargingFunctions = false;
-
- if (functions == null || applyAdbFunction(functions)
- .equals(UsbManager.USB_FUNCTION_NONE)) {
- functions = getChargingFunctions();
- chargingFunctions = true;
- }
- functions = applyAdbFunction(functions);
-
- if (!mCurrentFunctions.equals(functions)
+ if (mCurrentFunctions != functions
|| !mCurrentFunctionsApplied
|| forceRestart) {
- Slog.i(TAG, "Setting USB config to " + functions);
+ Slog.i(TAG, "Setting USB config to " + UsbManager.usbFunctionsToString(functions));
mCurrentFunctions = functions;
mCurrentFunctionsApplied = false;
// set the flag to false as that would be stale value
mCurrentUsbFunctionsRequested = false;
- // Set the new USB configuration.
- setUsbConfig(mCurrentFunctions, chargingFunctions);
+ boolean chargingFunctions = functions == UsbManager.FUNCTION_NONE;
+ functions = getAppliedFunctions(functions);
- if (mBootCompleted
- && (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
- || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
+ // Set the new USB configuration.
+ setUsbConfig(functions, chargingFunctions);
+
+ if (mBootCompleted && isUsbDataTransferActive(functions)) {
// Start up dependent services.
- updateUsbStateBroadcastIfNeeded(true);
+ updateUsbStateBroadcastIfNeeded(functions, true);
}
}
}
@@ -1968,27 +1959,37 @@
return nativeOpenAccessory();
}
- /**
- * Checks whether the function is present in the USB configuration.
- *
- * @param function function to be checked.
- */
- public boolean isFunctionEnabled(String function) {
- return mHandler.isFunctionEnabled(function);
+ public long getCurrentFunctions() {
+ return mHandler.getEnabledFunctions();
+ }
+
+ public long getScreenUnlockedFunctions() {
+ return mHandler.getScreenUnlockedFunctions();
}
/**
* Adds function to the current USB configuration.
*
- * @param functions name of the USB function, or null to restore the default function.
- * @param usbDataUnlocked whether user data is accessible.
+ * @param functions The functions to set, or empty to set the charging function.
*/
- public void setCurrentFunctions(String functions, boolean usbDataUnlocked) {
+ public void setCurrentFunctions(long functions) {
if (DEBUG) {
- Slog.d(TAG, "setCurrentFunctions(" + functions + ", "
- + usbDataUnlocked + ")");
+ Slog.d(TAG, "setCurrentFunctions(" + UsbManager.usbFunctionsToString(functions) + ")");
}
- mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, usbDataUnlocked);
+ if (functions == UsbManager.FUNCTION_NONE) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_CHARGING);
+ } else if (functions == UsbManager.FUNCTION_MTP) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_MTP);
+ } else if (functions == UsbManager.FUNCTION_PTP) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_PTP);
+ } else if (functions == UsbManager.FUNCTION_MIDI) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_MIDI);
+ } else if (functions == UsbManager.FUNCTION_RNDIS) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_RNDIS);
+ } else if (functions == UsbManager.FUNCTION_ACCESSORY) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_ACCESSORY);
+ }
+ mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions);
}
/**
@@ -1996,9 +1997,10 @@
*
* @param functions Functions to set.
*/
- public void setScreenUnlockedFunctions(String functions) {
+ public void setScreenUnlockedFunctions(long functions) {
if (DEBUG) {
- Slog.d(TAG, "setScreenUnlockedFunctions(" + functions + ")");
+ Slog.d(TAG, "setScreenUnlockedFunctions("
+ + UsbManager.usbFunctionsToString(functions) + ")");
}
mHandler.sendMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS, functions);
}
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 917e651..5f1f5e4 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -208,7 +208,7 @@
mParentUser = user;
mSettingsFile = new AtomicFile(new File(
Environment.getUserSystemDirectory(user.getIdentifier()),
- "usb_device_manager.xml"));
+ "usb_device_manager.xml"), "usb-state");
mDisablePermissionDialogs = context.getResources().getBoolean(
com.android.internal.R.bool.config_disableUsbPermissionDialogs);
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 1a20819..2f6e531 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -382,59 +382,44 @@
}
@Override
+ public void setCurrentFunctions(long functions) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ Preconditions.checkArgument(UsbManager.areSettableFunctions(functions));
+ Preconditions.checkState(mDeviceManager != null);
+ mDeviceManager.setCurrentFunctions(functions);
+ }
+
+ @Override
+ public void setCurrentFunction(String functions, boolean usbDataUnlocked) {
+ setCurrentFunctions(UsbManager.usbFunctionsFromString(functions));
+ }
+
+ @Override
public boolean isFunctionEnabled(String function) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
- return mDeviceManager != null && mDeviceManager.isFunctionEnabled(function);
+ return (getCurrentFunctions() & UsbManager.usbFunctionsFromString(function)) != 0;
}
@Override
- public void setCurrentFunction(String function, boolean usbDataUnlocked) {
+ public long getCurrentFunctions() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-
- if (!isSupportedCurrentFunction(function)) {
- Slog.w(TAG, "Caller of setCurrentFunction() requested unsupported USB function: "
- + function);
- function = UsbManager.USB_FUNCTION_NONE;
- }
-
- if (mDeviceManager != null) {
- mDeviceManager.setCurrentFunctions(function, usbDataUnlocked);
- } else {
- throw new IllegalStateException("USB device mode not supported");
- }
+ Preconditions.checkState(mDeviceManager != null);
+ return mDeviceManager.getCurrentFunctions();
}
@Override
- public void setScreenUnlockedFunctions(String function) {
+ public void setScreenUnlockedFunctions(long functions) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ Preconditions.checkArgument(UsbManager.areSettableFunctions(functions));
+ Preconditions.checkState(mDeviceManager != null);
- if (!isSupportedCurrentFunction(function)) {
- Slog.w(TAG, "Caller of setScreenUnlockedFunctions() requested unsupported USB function:"
- + function);
- function = UsbManager.USB_FUNCTION_NONE;
- }
-
- if (mDeviceManager != null) {
- mDeviceManager.setScreenUnlockedFunctions(function);
- } else {
- throw new IllegalStateException("USB device mode not supported");
- }
+ mDeviceManager.setScreenUnlockedFunctions(functions);
}
- private static boolean isSupportedCurrentFunction(String function) {
- if (function == null) return true;
-
- switch (function) {
- case UsbManager.USB_FUNCTION_NONE:
- case UsbManager.USB_FUNCTION_AUDIO_SOURCE:
- case UsbManager.USB_FUNCTION_MIDI:
- case UsbManager.USB_FUNCTION_MTP:
- case UsbManager.USB_FUNCTION_PTP:
- case UsbManager.USB_FUNCTION_RNDIS:
- return true;
- }
-
- return false;
+ @Override
+ public long getScreenUnlockedFunctions() {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ Preconditions.checkState(mDeviceManager != null);
+ return mDeviceManager.getScreenUnlockedFunctions();
}
@Override
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 91d86c6..a34e9f9 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -27,8 +27,8 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.carrier.CarrierService;
+import android.telephony.ims.ImsReasonInfo;
-import com.android.ims.ImsReasonInfo;
import com.android.internal.telephony.ICarrierConfigLoader;
/**
@@ -1390,7 +1390,7 @@
"allow_video_calling_fallback_bool";
/**
- * Defines operator-specific {@link com.android.ims.ImsReasonInfo} mappings.
+ * Defines operator-specific {@link ImsReasonInfo} mappings.
*
* Format: "ORIGINAL_CODE|MESSAGE|NEW_CODE"
* Where {@code ORIGINAL_CODE} corresponds to a {@link ImsReasonInfo#getCode()} code,
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index 0474362..dfaaab9 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -20,6 +20,8 @@
import android.os.Parcelable;
import android.telephony.Rlog;
+import java.util.Objects;
+
/**
* Signal strength related information.
*/
@@ -293,9 +295,7 @@
@Override
public int hashCode() {
- int primeNum = 31;
- return ((mCdmaDbm * primeNum) + (mCdmaEcio * primeNum)
- + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum));
+ return Objects.hash(mCdmaDbm, mCdmaEcio, mEvdoDbm, mEvdoEcio, mEvdoSnr);
}
@Override
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index 4137853..f68d2ca 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -20,6 +20,8 @@
import android.os.Parcelable;
import android.telephony.Rlog;
+import java.util.Objects;
+
/**
* GSM signal strength related information.
*/
@@ -185,8 +187,7 @@
@Override
public int hashCode() {
- int primeNum = 31;
- return (mSignalStrength * primeNum) + (mBitErrorRate * primeNum);
+ return Objects.hash(mSignalStrength, mBitErrorRate, mTimingAdvance);
}
@Override
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 0d07a40..6ffc8b6 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -20,6 +20,8 @@
import android.os.Parcelable;
import android.telephony.Rlog;
+import java.util.Objects;
+
/**
* LTE signal strength related information.
*/
@@ -231,10 +233,7 @@
@Override
public int hashCode() {
- int primeNum = 31;
- return (mSignalStrength * primeNum) + (mRsrp * primeNum)
- + (mRsrq * primeNum) + (mRssnr * primeNum) + (mCqi * primeNum)
- + (mTimingAdvance * primeNum);
+ return Objects.hash(mSignalStrength, mRsrp, mRsrq, mRssnr, mCqi, mTimingAdvance);
}
@Override
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index b94b01d..2cd56b8 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -20,6 +20,8 @@
import android.os.Parcelable;
import android.telephony.Rlog;
+import java.util.Objects;
+
/**
* Wcdma signal strength related information.
*/
@@ -156,8 +158,7 @@
@Override
public int hashCode() {
- int primeNum = 31;
- return (mSignalStrength * primeNum) + (mBitErrorRate * primeNum);
+ return Objects.hash(mSignalStrength, mBitErrorRate);
}
@Override
diff --git a/telephony/java/android/telephony/DataConnectionRealTimeInfo.java b/telephony/java/android/telephony/DataConnectionRealTimeInfo.java
index f71f58d..fc4e17a 100644
--- a/telephony/java/android/telephony/DataConnectionRealTimeInfo.java
+++ b/telephony/java/android/telephony/DataConnectionRealTimeInfo.java
@@ -28,10 +28,14 @@
public class DataConnectionRealTimeInfo implements Parcelable {
private long mTime; // Time the info was collected since boot in nanos;
- public static final int DC_POWER_STATE_LOW = 1;
- public static final int DC_POWER_STATE_MEDIUM = 2;
- public static final int DC_POWER_STATE_HIGH = 3;
- public static final int DC_POWER_STATE_UNKNOWN = Integer.MAX_VALUE;
+ public static final int DC_POWER_STATE_LOW
+ = TelephonyProtoEnums.DATA_CONNECTION_POWER_STATE_LOW ; // = 1
+ public static final int DC_POWER_STATE_MEDIUM
+ = TelephonyProtoEnums.DATA_CONNECTION_POWER_STATE_MEDIUM; // = 2
+ public static final int DC_POWER_STATE_HIGH
+ = TelephonyProtoEnums.DATA_CONNECTION_POWER_STATE_HIGH; // = 3
+ public static final int DC_POWER_STATE_UNKNOWN
+ = TelephonyProtoEnums.DATA_CONNECTION_POWER_STATE_UNKNOWN; // = Integer.MAX_VALUE
private int mDcPowerState; // DC_POWER_STATE_[LOW | MEDIUM | HIGH | UNKNOWN]
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationStates.java b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
new file mode 100644
index 0000000..97e3037
--- /dev/null
+++ b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
@@ -0,0 +1,72 @@
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+
+/**
+ * Class that stores information specific to data network registration.
+ * @hide
+ */
+public class DataSpecificRegistrationStates implements Parcelable{
+ /**
+ * The maximum number of simultaneous Data Calls that
+ * must be established using setupDataCall().
+ */
+ public final int maxDataCalls;
+
+ DataSpecificRegistrationStates(int maxDataCalls) {
+ this.maxDataCalls = maxDataCalls;
+ }
+
+ private DataSpecificRegistrationStates(Parcel source) {
+ maxDataCalls = source.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(maxDataCalls);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "DataSpecificRegistrationStates {" + " mMaxDataCalls=" + maxDataCalls + "}";
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(maxDataCalls);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+
+ if (o == null || !(o instanceof DataSpecificRegistrationStates)) {
+ return false;
+ }
+
+ DataSpecificRegistrationStates other = (DataSpecificRegistrationStates) o;
+ return this.maxDataCalls == other.maxDataCalls;
+ }
+
+ public static final Parcelable.Creator<DataSpecificRegistrationStates> CREATOR =
+ new Parcelable.Creator<DataSpecificRegistrationStates>() {
+ @Override
+ public DataSpecificRegistrationStates createFromParcel(Parcel source) {
+ return new DataSpecificRegistrationStates(source);
+ }
+
+ @Override
+ public DataSpecificRegistrationStates[] newArray(int size) {
+ return new DataSpecificRegistrationStates[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index 03ce2d8..521adef 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -36,12 +36,12 @@
*/
public static final int TX_POWER_LEVELS = 5;
- private final long mTimestamp;
- private final int mSleepTimeMs;
- private final int mIdleTimeMs;
- private final int [] mTxTimeMs = new int[TX_POWER_LEVELS];
- private final int mRxTimeMs;
- private final int mEnergyUsed;
+ private long mTimestamp;
+ private int mSleepTimeMs;
+ private int mIdleTimeMs;
+ private int [] mTxTimeMs = new int[TX_POWER_LEVELS];
+ private int mRxTimeMs;
+ private int mEnergyUsed;
public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
int[] txTimeMs, int rxTimeMs, int energyUsed) {
@@ -110,6 +110,10 @@
return mTimestamp;
}
+ public void setTimestamp(long timestamp) {
+ mTimestamp = timestamp;
+ }
+
/**
* @return tx time in ms. It's an array of tx times
* with each index...
@@ -118,6 +122,10 @@
return mTxTimeMs;
}
+ public void setTxTimeMillis(int[] txTimeMs) {
+ mTxTimeMs = txTimeMs;
+ }
+
/**
* @return sleep time in ms.
*/
@@ -125,6 +133,10 @@
return mSleepTimeMs;
}
+ public void setSleepTimeMillis(int sleepTimeMillis) {
+ mSleepTimeMs = sleepTimeMillis;
+ }
+
/**
* @return idle time in ms.
*/
@@ -132,6 +144,10 @@
return mIdleTimeMs;
}
+ public void setIdleTimeMillis(int idleTimeMillis) {
+ mIdleTimeMs = idleTimeMillis;
+ }
+
/**
* @return rx time in ms.
*/
@@ -139,6 +155,10 @@
return mRxTimeMs;
}
+ public void setRxTimeMillis(int rxTimeMillis) {
+ mRxTimeMs = rxTimeMillis;
+ }
+
/**
* product of current(mA), voltage(V) and time(ms)
* @return energy used
@@ -147,6 +167,10 @@
return mEnergyUsed;
}
+ public void setEnergyUsed(int energyUsed) {
+ mEnergyUsed = energyUsed;
+ }
+
/**
* @return if the record is valid
*/
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index e051069..4f137be 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -105,6 +105,11 @@
@Nullable
private final CellIdentity mCellIdentity;
+ @Nullable
+ private VoiceSpecificRegistrationStates mVoiceSpecificStates;
+
+ @Nullable
+ private DataSpecificRegistrationStates mDataSpecificStates;
/**
* @param transportType Transport type. Must be {@link AccessNetworkConstants.TransportType}
@@ -128,6 +133,34 @@
mEmergencyOnly = emergencyOnly;
}
+ /**
+ * Constructor for voice network registration states.
+ * @hide
+ */
+ public NetworkRegistrationState(int transportType, int domain, int regState,
+ int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
+ int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
+ int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
+ this(transportType, domain, regState, accessNetworkTechnology,
+ reasonForDenial, emergencyOnly, availableServices, cellIdentity);
+
+ mVoiceSpecificStates = new VoiceSpecificRegistrationStates(cssSupported, roamingIndicator,
+ systemIsInPrl, defaultRoamingIndicator);
+ }
+
+ /**
+ * Constructor for data network registration states.
+ * @hide
+ */
+ public NetworkRegistrationState(int transportType, int domain, int regState,
+ int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
+ int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls) {
+ this(transportType, domain, regState, accessNetworkTechnology,
+ reasonForDenial, emergencyOnly, availableServices, cellIdentity);
+
+ mDataSpecificStates = new DataSpecificRegistrationStates(maxDataCalls);
+ }
+
protected NetworkRegistrationState(Parcel source) {
mTransportType = source.readInt();
mDomain = source.readInt();
@@ -137,6 +170,10 @@
mEmergencyOnly = source.readBoolean();
mAvailableServices = source.createIntArray();
mCellIdentity = source.readParcelable(CellIdentity.class.getClassLoader());
+ mVoiceSpecificStates = source.readParcelable(
+ VoiceSpecificRegistrationStates.class.getClassLoader());
+ mDataSpecificStates = source.readParcelable(
+ DataSpecificRegistrationStates.class.getClassLoader());
}
/**
@@ -173,6 +210,36 @@
return mAccessNetworkTechnology;
}
+ /**
+ * @return Reason for denial from network.
+ */
+ public int getReasonForDenial() {
+ return mReasonForDenial;
+ }
+
+ /**
+ * @return The cell information.
+ */
+ public CellIdentity getCellIdentity() {
+ return mCellIdentity;
+ }
+
+ /**
+ * @hide
+ */
+ @Nullable
+ public VoiceSpecificRegistrationStates getVoiceSpecificStates() {
+ return mVoiceSpecificStates;
+ }
+
+ /**
+ * @hide
+ */
+ @Nullable
+ public DataSpecificRegistrationStates getDataSpecificStates() {
+ return mDataSpecificStates;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -202,13 +269,16 @@
.append(" emergencyEnabled=").append(mEmergencyOnly)
.append(" supportedServices=").append(mAvailableServices)
.append(" cellIdentity=").append(mCellIdentity)
+ .append(" voiceSpecificStates=").append(mVoiceSpecificStates)
+ .append(" dataSpecificStates=").append(mDataSpecificStates)
.append("}").toString();
}
@Override
public int hashCode() {
return Objects.hash(mTransportType, mDomain, mRegState, mAccessNetworkTechnology,
- mReasonForDenial, mEmergencyOnly, mAvailableServices, mCellIdentity);
+ mReasonForDenial, mEmergencyOnly, mAvailableServices, mCellIdentity,
+ mVoiceSpecificStates, mDataSpecificStates);
}
@Override
@@ -228,7 +298,9 @@
&& mEmergencyOnly == other.mEmergencyOnly
&& (mAvailableServices == other.mAvailableServices
|| Arrays.equals(mAvailableServices, other.mAvailableServices))
- && mCellIdentity == other.mCellIdentity;
+ && mCellIdentity == other.mCellIdentity
+ && mVoiceSpecificStates == other.mVoiceSpecificStates
+ && mDataSpecificStates == other.mDataSpecificStates;
}
@Override
@@ -241,6 +313,8 @@
dest.writeBoolean(mEmergencyOnly);
dest.writeIntArray(mAvailableServices);
dest.writeParcelable(mCellIdentity, 0);
+ dest.writeParcelable(mVoiceSpecificStates, 0);
+ dest.writeParcelable(mDataSpecificStates, 0);
}
public static final Parcelable.Creator<NetworkRegistrationState> CREATOR =
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index fc2ef27..778ca77 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -35,15 +35,20 @@
private static final boolean DBG = false;
/** @hide */
- public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
+ public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN
+ = TelephonyProtoEnums.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; // = 0
/** @hide */
- public static final int SIGNAL_STRENGTH_POOR = 1;
+ public static final int SIGNAL_STRENGTH_POOR
+ = TelephonyProtoEnums.SIGNAL_STRENGTH_POOR; // = 1
/** @hide */
- public static final int SIGNAL_STRENGTH_MODERATE = 2;
+ public static final int SIGNAL_STRENGTH_MODERATE
+ = TelephonyProtoEnums.SIGNAL_STRENGTH_MODERATE; // = 2
/** @hide */
- public static final int SIGNAL_STRENGTH_GOOD = 3;
+ public static final int SIGNAL_STRENGTH_GOOD
+ = TelephonyProtoEnums.SIGNAL_STRENGTH_GOOD; // = 3
/** @hide */
- public static final int SIGNAL_STRENGTH_GREAT = 4;
+ public static final int SIGNAL_STRENGTH_GREAT
+ = TelephonyProtoEnums.SIGNAL_STRENGTH_GREAT; // = 4
/** @hide */
public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
/** @hide */
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index a6dbc06..577ea7d 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -18,8 +18,8 @@
import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
+import android.annotation.Nullable;
import android.annotation.StringDef;
-import android.app.PendingIntent;
import android.content.res.Resources;
import android.os.Binder;
import android.text.TextUtils;
@@ -544,8 +544,16 @@
/**
* Returns the originating address (sender) of this SMS message in String
- * form or null if unavailable
+ * form or null if unavailable.
+ *
+ * <p>If the address is a GSM-formatted address, it will be in a format specified by 3GPP
+ * 23.040 Sec 9.1.2.5. If it is a CDMA address, it will be a format specified by 3GPP2
+ * C.S005-D Table 2.7.1.3.2.4-2. The choice of format is carrier-specific, so callers of the
+ * should be careful to avoid assumptions about the returned content.
+ *
+ * @return a String representation of the address; null if unavailable.
*/
+ @Nullable
public String getOriginatingAddress() {
return mWrappedSmsMessage.getOriginatingAddress();
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0a6d960..5c290da 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -48,12 +48,13 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.VisualVoicemailService.VisualVoicemailTask;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.feature.ImsFeature;
import android.util.Log;
-import com.android.ims.internal.IImsMMTelFeature;
-import com.android.ims.internal.IImsRcsFeature;
-import com.android.ims.internal.IImsRegistration;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telecom.ITelecomService;
@@ -4462,7 +4463,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.iccTransmitApduBasicChannel(subId, cla,
+ return telephony.iccTransmitApduBasicChannel(subId, getOpPackageName(), cla,
instruction, p1, p2, p3, data);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -4951,28 +4952,6 @@
}
}
- /**
- * Returns the response of ISIM Authetification through RIL.
- * Returns null if the Authentification hasn't been successed or isn't present iphonesubinfo.
- * @return the response of ISIM Authetification, or null if not available
- * @hide
- * @deprecated
- * @see getIccAuthentication with appType=PhoneConstants.APPTYPE_ISIM
- */
- public String getIsimChallengeResponse(String nonce){
- try {
- IPhoneSubInfo info = getSubscriberInfo();
- if (info == null)
- return null;
- return info.getIsimChallengeResponse(nonce);
- } catch (RemoteException ex) {
- return null;
- } catch (NullPointerException ex) {
- // This could happen before phone restarts due to crashing
- return null;
- }
- }
-
// ICC SIM Application Types
/** UICC application type is SIM */
public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
@@ -5094,57 +5073,60 @@
}
}
- /** @hide */
- @IntDef({ImsFeature.EMERGENCY_MMTEL, ImsFeature.MMTEL, ImsFeature.RCS})
- @Retention(RetentionPolicy.SOURCE)
- public @interface Feature {}
-
/**
- * Returns the {@link IImsMMTelFeature} that corresponds to the given slot Id and MMTel
- * feature or {@link null} if the service is not available. If an MMTelFeature is available, the
- * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
- * @param slotIndex The SIM slot that we are requesting the {@link IImsMMTelFeature} for.
- * @param callback Listener that will send updates to ImsManager when there are updates to
- * ImsServiceController.
- * @return {@link IImsMMTelFeature} interface for the feature specified or {@code null} if
- * it is unavailable.
+ * Enables IMS for the framework. This will trigger IMS registration and ImsFeature capability
+ * status updates, if not already enabled.
* @hide
*/
- public @Nullable IImsMMTelFeature getImsMMTelFeatureAndListen(int slotIndex,
- IImsServiceFeatureCallback callback) {
+ public void enableIms(int slotId) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getMMTelFeatureAndListen(slotIndex, callback);
+ telephony.enableIms(slotId);
}
} catch (RemoteException e) {
- Rlog.e(TAG, "getImsMMTelFeatureAndListen, RemoteException: "
+ Rlog.e(TAG, "enableIms, RemoteException: "
+ e.getMessage());
}
- return null;
}
/**
- * Returns the {@link IImsMMTelFeature} that corresponds to the given slot Id and MMTel
- * feature for emergency calling or {@link null} if the service is not available. If an
- * MMTelFeature is available, the {@link IImsServiceFeatureCallback} callback is registered as a
- * listener for feature updates.
- * @param slotIndex The SIM slot that we are requesting the {@link IImsMMTelFeature} for.
+ * Disables IMS for the framework. This will trigger IMS de-registration and trigger ImsFeature
+ * status updates to disabled.
+ * @hide
+ */
+ public void disableIms(int slotId) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.disableIms(slotId);
+ }
+ } catch (RemoteException e) {
+ Rlog.e(TAG, "disableIms, RemoteException: "
+ + e.getMessage());
+ }
+ }
+
+ /**
+ * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id and MMTel
+ * feature or {@link null} if the service is not available. If an MMTelFeature is available, the
+ * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
+ * @param slotIndex The SIM slot that we are requesting the {@link IImsMmTelFeature} for.
* @param callback Listener that will send updates to ImsManager when there are updates to
* ImsServiceController.
- * @return {@link IImsMMTelFeature} interface for the feature specified or {@code null} if
+ * @return {@link IImsMmTelFeature} interface for the feature specified or {@code null} if
* it is unavailable.
* @hide
*/
- public @Nullable IImsMMTelFeature getImsEmergencyMMTelFeatureAndListen(int slotIndex,
+ public @Nullable IImsMmTelFeature getImsMmTelFeatureAndListen(int slotIndex,
IImsServiceFeatureCallback callback) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getEmergencyMMTelFeatureAndListen(slotIndex, callback);
+ return telephony.getMmTelFeatureAndListen(slotIndex, callback);
}
} catch (RemoteException e) {
- Rlog.e(TAG, "getImsEmergencyMMTelFeatureAndListen, RemoteException: "
+ Rlog.e(TAG, "getImsMmTelFeatureAndListen, RemoteException: "
+ e.getMessage());
}
return null;
@@ -5196,6 +5178,25 @@
}
/**
+ * @return the {@IImsConfig} interface that corresponds with the slot index and feature.
+ * @param slotIndex The SIM slot corresponding to the ImsService ImsConfig is active for.
+ * @param feature An integer indicating the feature that we wish to get the ImsConfig for.
+ * Corresponds to features defined in ImsFeature.
+ * @hide
+ */
+ public @Nullable IImsConfig getImsConfig(int slotIndex, int feature) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getImsConfig(slotIndex, feature);
+ }
+ } catch (RemoteException e) {
+ Rlog.e(TAG, "getImsRegistration, RemoteException: " + e.getMessage());
+ }
+ return null;
+ }
+
+ /**
* Set IMS registration state
*
* @param Registration state
diff --git a/telephony/java/android/telephony/VoiceSpecificRegistrationStates.java b/telephony/java/android/telephony/VoiceSpecificRegistrationStates.java
new file mode 100644
index 0000000..871ee4d
--- /dev/null
+++ b/telephony/java/android/telephony/VoiceSpecificRegistrationStates.java
@@ -0,0 +1,114 @@
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+
+/**
+ * Class that stores information specific to voice network registration.
+ * @hide
+ */
+public class VoiceSpecificRegistrationStates implements Parcelable{
+ /**
+ * oncurrent services support indicator. if
+ * registered on a CDMA system.
+ * false - Concurrent services not supported,
+ * true - Concurrent services supported
+ */
+ public final boolean cssSupported;
+
+ /**
+ * TSB-58 Roaming Indicator if registered
+ * on a CDMA or EVDO system or -1 if not.
+ * Valid values are 0-255.
+ */
+ public final int roamingIndicator;
+
+ /**
+ * indicates whether the current system is in the
+ * PRL if registered on a CDMA or EVDO system or -1 if
+ * not. 0=not in the PRL, 1=in the PRL
+ */
+ public final int systemIsInPrl;
+
+ /**
+ * default Roaming Indicator from the PRL,
+ * if registered on a CDMA or EVDO system or -1 if not.
+ * Valid values are 0-255.
+ */
+ public final int defaultRoamingIndicator;
+
+ VoiceSpecificRegistrationStates(boolean cssSupported, int roamingIndicator, int systemIsInPrl,
+ int defaultRoamingIndicator) {
+ this.cssSupported = cssSupported;
+ this.roamingIndicator = roamingIndicator;
+ this.systemIsInPrl = systemIsInPrl;
+ this.defaultRoamingIndicator = defaultRoamingIndicator;
+ }
+
+ private VoiceSpecificRegistrationStates(Parcel source) {
+ this.cssSupported = source.readBoolean();
+ this.roamingIndicator = source.readInt();
+ this.systemIsInPrl = source.readInt();
+ this.defaultRoamingIndicator = source.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBoolean(cssSupported);
+ dest.writeInt(roamingIndicator);
+ dest.writeInt(systemIsInPrl);
+ dest.writeInt(defaultRoamingIndicator);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "VoiceSpecificRegistrationStates {"
+ + " mCssSupported=" + cssSupported
+ + " mRoamingIndicator=" + roamingIndicator
+ + " mSystemIsInPrl=" + systemIsInPrl
+ + " mDefaultRoamingIndicator=" + defaultRoamingIndicator + "}";
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(cssSupported, roamingIndicator, systemIsInPrl,
+ defaultRoamingIndicator);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+
+ if (o == null || !(o instanceof VoiceSpecificRegistrationStates)) {
+ return false;
+ }
+
+ VoiceSpecificRegistrationStates other = (VoiceSpecificRegistrationStates) o;
+ return this.cssSupported == other.cssSupported
+ && this.roamingIndicator == other.roamingIndicator
+ && this.systemIsInPrl == other.systemIsInPrl
+ && this.defaultRoamingIndicator == other.defaultRoamingIndicator;
+ }
+
+
+ public static final Parcelable.Creator<VoiceSpecificRegistrationStates> CREATOR =
+ new Parcelable.Creator<VoiceSpecificRegistrationStates>() {
+ @Override
+ public VoiceSpecificRegistrationStates createFromParcel(Parcel source) {
+ return new VoiceSpecificRegistrationStates(source);
+ }
+
+ @Override
+ public VoiceSpecificRegistrationStates[] newArray(int size) {
+ return new VoiceSpecificRegistrationStates[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index ef3a183..25f5133 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -27,6 +27,7 @@
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Description of the response of a setup data call connection request.
@@ -220,17 +221,8 @@
@Override
public int hashCode() {
- return mStatus * 31
- + mSuggestedRetryTime * 37
- + mCid * 41
- + mActive * 43
- + mType.hashCode() * 47
- + mIfname.hashCode() * 53
- + mAddresses.hashCode() * 59
- + mDnses.hashCode() * 61
- + mGateways.hashCode() * 67
- + mPcscfs.hashCode() * 71
- + mMtu * 73;
+ return Objects.hash(mStatus, mSuggestedRetryTime, mCid, mActive, mType, mIfname, mAddresses,
+ mDnses, mGateways, mPcscfs, mMtu);
}
@Override
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index fa19ea0..63e8c3b 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -18,6 +18,8 @@
import android.annotation.CallSuper;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
@@ -30,7 +32,6 @@
import android.os.RemoteException;
import android.telephony.AccessNetworkConstants;
import android.telephony.Rlog;
-import android.telephony.SubscriptionManager;
import android.util.SparseArray;
import java.lang.annotation.Retention;
@@ -86,15 +87,17 @@
/** The reason of the data request is IWLAN handover */
public static final int REQUEST_REASON_HANDOVER = 3;
- private static final int DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE = 1;
- private static final int DATA_SERVICE_REQUEST_SETUP_DATA_CALL = 2;
- private static final int DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL = 3;
- private static final int DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN = 4;
- private static final int DATA_SERVICE_REQUEST_SET_DATA_PROFILE = 5;
- private static final int DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST = 6;
- private static final int DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED = 7;
- private static final int DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED = 8;
- private static final int DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED = 9;
+ private static final int DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER = 1;
+ private static final int DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER = 2;
+ private static final int DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS = 3;
+ private static final int DATA_SERVICE_REQUEST_SETUP_DATA_CALL = 4;
+ private static final int DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL = 5;
+ private static final int DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN = 6;
+ private static final int DATA_SERVICE_REQUEST_SET_DATA_PROFILE = 7;
+ private static final int DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST = 8;
+ private static final int DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED = 9;
+ private static final int DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED = 10;
+ private static final int DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED = 11;
private final HandlerThread mHandlerThread;
@@ -102,7 +105,7 @@
private final SparseArray<DataServiceProvider> mServiceMap = new SparseArray<>();
- private final SparseArray<IDataServiceWrapper> mBinderMap = new SparseArray<>();
+ private final IBinder mBinder = new IDataServiceWrapper();
/**
* The abstract class of the actual data service implementation. The data service provider
@@ -136,19 +139,21 @@
* the provided callback to notify the platform.
*
* @param accessNetworkType Access network type that the data call will be established on.
- * Must be one of {@link AccessNetworkConstants.AccessNetworkType}.
+ * Must be one of {@link AccessNetworkConstants.AccessNetworkType}.
* @param dataProfile Data profile used for data call setup. See {@link DataProfile}
* @param isRoaming True if the device is data roaming.
* @param allowRoaming True if data roaming is allowed by the user.
* @param reason The reason for data setup. Must be {@link #REQUEST_REASON_NORMAL} or
- * {@link #REQUEST_REASON_HANDOVER}.
+ * {@link #REQUEST_REASON_HANDOVER}.
* @param linkProperties If {@code reason} is {@link #REQUEST_REASON_HANDOVER}, this is the
- * link properties of the existing data connection, otherwise null.
- * @param callback The result callback for this request.
+ * link properties of the existing data connection, otherwise null.
+ * @param callback The result callback for this request. Null if the client does not care
+ * about the result.
*/
public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
boolean allowRoaming, @SetupDataReason int reason,
- LinkProperties linkProperties, DataServiceCallback callback) {
+ @Nullable LinkProperties linkProperties,
+ @Nullable DataServiceCallback callback) {
// The default implementation is to return unsupported.
callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
}
@@ -159,13 +164,15 @@
* provided callback to notify the platform.
*
* @param cid Call id returned in the callback of {@link DataServiceProvider#setupDataCall(
- * int, DataProfile, boolean, boolean, int, LinkProperties, DataServiceCallback)}.
+ * int, DataProfile, boolean, boolean, int, LinkProperties, DataServiceCallback)}.
* @param reason The reason for data deactivation. Must be {@link #REQUEST_REASON_NORMAL},
- * {@link #REQUEST_REASON_SHUTDOWN} or {@link #REQUEST_REASON_HANDOVER}.
- * @param callback The result callback for this request.
+ * {@link #REQUEST_REASON_SHUTDOWN} or {@link #REQUEST_REASON_HANDOVER}.
+ * @param callback The result callback for this request. Null if the client does not care
+ * about the result.
+ *
*/
public void deactivateDataCall(int cid, @DeactivateDataReason int reason,
- DataServiceCallback callback) {
+ @Nullable DataServiceCallback callback) {
// The default implementation is to return unsupported.
callback.onDeactivateDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
}
@@ -175,10 +182,11 @@
*
* @param dataProfile Data profile used for data call setup. See {@link DataProfile}.
* @param isRoaming True if the device is data roaming.
- * @param callback The result callback for this request.
+ * @param callback The result callback for this request. Null if the client does not care
+ * about the result.
*/
public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
- DataServiceCallback callback) {
+ @Nullable DataServiceCallback callback) {
// The default implementation is to return unsupported.
callback.onSetInitialAttachApnComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
}
@@ -190,10 +198,11 @@
*
* @param dps A list of data profiles.
* @param isRoaming True if the device is data roaming.
- * @param callback The result callback for this request.
+ * @param callback The result callback for this request. Null if the client does not care
+ * about the result.
*/
public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
- DataServiceCallback callback) {
+ @Nullable DataServiceCallback callback) {
// The default implementation is to return unsupported.
callback.onSetDataProfileComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
}
@@ -203,7 +212,7 @@
*
* @param callback The result callback for this request.
*/
- public void getDataCallList(DataServiceCallback callback) {
+ public void getDataCallList(@NonNull DataServiceCallback callback) {
// The default implementation is to return unsupported.
callback.onGetDataCallListComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
}
@@ -321,70 +330,89 @@
public void handleMessage(Message message) {
IDataServiceCallback callback;
final int slotId = message.arg1;
- DataServiceProvider service;
-
- synchronized (mServiceMap) {
- service = mServiceMap.get(slotId);
- }
+ DataServiceProvider serviceProvider = mServiceMap.get(slotId);
switch (message.what) {
- case DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE:
- service = createDataServiceProvider(message.arg1);
- if (service != null) {
- mServiceMap.put(slotId, service);
+ case DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER:
+ serviceProvider = createDataServiceProvider(message.arg1);
+ if (serviceProvider != null) {
+ mServiceMap.put(slotId, serviceProvider);
}
break;
+ case DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER:
+ if (serviceProvider != null) {
+ serviceProvider.onDestroy();
+ mServiceMap.remove(slotId);
+ }
+ break;
+ case DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS:
+ for (int i = 0; i < mServiceMap.size(); i++) {
+ serviceProvider = mServiceMap.get(i);
+ if (serviceProvider != null) {
+ serviceProvider.onDestroy();
+ }
+ }
+ mServiceMap.clear();
+ break;
case DATA_SERVICE_REQUEST_SETUP_DATA_CALL:
- if (service == null) break;
+ if (serviceProvider == null) break;
SetupDataCallRequest setupDataCallRequest = (SetupDataCallRequest) message.obj;
- service.setupDataCall(setupDataCallRequest.accessNetworkType,
+ serviceProvider.setupDataCall(setupDataCallRequest.accessNetworkType,
setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming,
setupDataCallRequest.allowRoaming, setupDataCallRequest.reason,
setupDataCallRequest.linkProperties,
- new DataServiceCallback(setupDataCallRequest.callback));
+ (setupDataCallRequest.callback != null)
+ ? new DataServiceCallback(setupDataCallRequest.callback)
+ : null);
break;
case DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL:
- if (service == null) break;
+ if (serviceProvider == null) break;
DeactivateDataCallRequest deactivateDataCallRequest =
(DeactivateDataCallRequest) message.obj;
- service.deactivateDataCall(deactivateDataCallRequest.cid,
+ serviceProvider.deactivateDataCall(deactivateDataCallRequest.cid,
deactivateDataCallRequest.reason,
- new DataServiceCallback(deactivateDataCallRequest.callback));
+ (deactivateDataCallRequest.callback != null)
+ ? new DataServiceCallback(deactivateDataCallRequest.callback)
+ : null);
break;
case DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN:
- if (service == null) break;
+ if (serviceProvider == null) break;
SetInitialAttachApnRequest setInitialAttachApnRequest =
(SetInitialAttachApnRequest) message.obj;
- service.setInitialAttachApn(setInitialAttachApnRequest.dataProfile,
+ serviceProvider.setInitialAttachApn(setInitialAttachApnRequest.dataProfile,
setInitialAttachApnRequest.isRoaming,
- new DataServiceCallback(setInitialAttachApnRequest.callback));
+ (setInitialAttachApnRequest.callback != null)
+ ? new DataServiceCallback(setInitialAttachApnRequest.callback)
+ : null);
break;
case DATA_SERVICE_REQUEST_SET_DATA_PROFILE:
- if (service == null) break;
+ if (serviceProvider == null) break;
SetDataProfileRequest setDataProfileRequest =
(SetDataProfileRequest) message.obj;
- service.setDataProfile(setDataProfileRequest.dps,
+ serviceProvider.setDataProfile(setDataProfileRequest.dps,
setDataProfileRequest.isRoaming,
- new DataServiceCallback(setDataProfileRequest.callback));
+ (setDataProfileRequest.callback != null)
+ ? new DataServiceCallback(setDataProfileRequest.callback)
+ : null);
break;
case DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST:
- if (service == null) break;
+ if (serviceProvider == null) break;
- service.getDataCallList(new DataServiceCallback(
+ serviceProvider.getDataCallList(new DataServiceCallback(
(IDataServiceCallback) message.obj));
break;
case DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED:
- if (service == null) break;
- service.registerForDataCallListChanged((IDataServiceCallback) message.obj);
+ if (serviceProvider == null) break;
+ serviceProvider.registerForDataCallListChanged((IDataServiceCallback) message.obj);
break;
case DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED:
- if (service == null) break;
+ if (serviceProvider == null) break;
callback = (IDataServiceCallback) message.obj;
- service.unregisterForDataCallListChanged(callback);
+ serviceProvider.unregisterForDataCallListChanged(callback);
break;
case DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED:
- if (service == null) break;
+ if (serviceProvider == null) break;
DataCallListChangedIndication indication =
(DataCallListChangedIndication) message.obj;
try {
@@ -423,67 +451,19 @@
loge("Unexpected intent " + intent);
return null;
}
-
- int slotId = intent.getIntExtra(
- DATA_SERVICE_EXTRA_SLOT_ID, SubscriptionManager.INVALID_SIM_SLOT_INDEX);
-
- if (!SubscriptionManager.isValidSlotIndex(slotId)) {
- loge("Invalid slot id " + slotId);
- return null;
- }
-
- log("onBind: slot id=" + slotId);
-
- IDataServiceWrapper binder = mBinderMap.get(slotId);
- if (binder == null) {
- Message msg = mHandler.obtainMessage(DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE);
- msg.arg1 = slotId;
- msg.sendToTarget();
-
- binder = new IDataServiceWrapper(slotId);
- mBinderMap.put(slotId, binder);
- }
-
- return binder;
+ return mBinder;
}
/** @hide */
@Override
public boolean onUnbind(Intent intent) {
- int slotId = intent.getIntExtra(DATA_SERVICE_EXTRA_SLOT_ID,
- SubscriptionManager.INVALID_SIM_SLOT_INDEX);
- if (mBinderMap.get(slotId) != null) {
- DataServiceProvider serviceImpl;
- synchronized (mServiceMap) {
- serviceImpl = mServiceMap.get(slotId);
- }
- if (serviceImpl != null) {
- serviceImpl.onDestroy();
- }
- mBinderMap.remove(slotId);
- }
-
- // If all clients unbinds, quit the handler thread
- if (mBinderMap.size() == 0) {
- mHandlerThread.quit();
- }
-
+ mHandler.obtainMessage(DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS).sendToTarget();
return false;
}
/** @hide */
@Override
public void onDestroy() {
- synchronized (mServiceMap) {
- for (int i = 0; i < mServiceMap.size(); i++) {
- DataServiceProvider serviceImpl = mServiceMap.get(i);
- if (serviceImpl != null) {
- serviceImpl.onDestroy();
- }
- }
- mServiceMap.clear();
- }
-
mHandlerThread.quit();
}
@@ -491,68 +471,78 @@
* A wrapper around IDataService that forwards calls to implementations of {@link DataService}.
*/
private class IDataServiceWrapper extends IDataService.Stub {
-
- private final int mSlotId;
-
- IDataServiceWrapper(int slotId) {
- mSlotId = slotId;
+ @Override
+ public void createDataServiceProvider(int slotId) {
+ mHandler.obtainMessage(DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER, slotId, 0)
+ .sendToTarget();
}
@Override
- public void setupDataCall(int accessNetworkType, DataProfile dataProfile,
+ public void removeDataServiceProvider(int slotId) {
+ mHandler.obtainMessage(DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER, slotId, 0)
+ .sendToTarget();
+ }
+
+ @Override
+ public void setupDataCall(int slotId, int accessNetworkType, DataProfile dataProfile,
boolean isRoaming, boolean allowRoaming, int reason,
LinkProperties linkProperties, IDataServiceCallback callback) {
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, mSlotId, 0,
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotId, 0,
new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
allowRoaming, reason, linkProperties, callback))
.sendToTarget();
}
@Override
- public void deactivateDataCall(int cid, int reason, IDataServiceCallback callback) {
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, mSlotId, 0,
+ public void deactivateDataCall(int slotId, int cid, int reason,
+ IDataServiceCallback callback) {
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, slotId, 0,
new DeactivateDataCallRequest(cid, reason, callback))
.sendToTarget();
}
@Override
- public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
+ public void setInitialAttachApn(int slotId, DataProfile dataProfile, boolean isRoaming,
IDataServiceCallback callback) {
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN, mSlotId, 0,
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN, slotId, 0,
new SetInitialAttachApnRequest(dataProfile, isRoaming, callback))
.sendToTarget();
}
@Override
- public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
+ public void setDataProfile(int slotId, List<DataProfile> dps, boolean isRoaming,
IDataServiceCallback callback) {
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_DATA_PROFILE, mSlotId, 0,
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_DATA_PROFILE, slotId, 0,
new SetDataProfileRequest(dps, isRoaming, callback)).sendToTarget();
}
@Override
- public void getDataCallList(IDataServiceCallback callback) {
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST, mSlotId, 0,
+ public void getDataCallList(int slotId, IDataServiceCallback callback) {
+ if (callback == null) {
+ loge("getDataCallList: callback is null");
+ return;
+ }
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST, slotId, 0,
callback).sendToTarget();
}
@Override
- public void registerForDataCallListChanged(IDataServiceCallback callback) {
+ public void registerForDataCallListChanged(int slotId, IDataServiceCallback callback) {
if (callback == null) {
- loge("Callback is null");
+ loge("registerForDataCallListChanged: callback is null");
return;
}
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED, mSlotId,
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED, slotId,
0, callback).sendToTarget();
}
@Override
- public void unregisterForDataCallListChanged(IDataServiceCallback callback) {
+ public void unregisterForDataCallListChanged(int slotId, IDataServiceCallback callback) {
if (callback == null) {
- loge("Callback is null");
+ loge("unregisterForDataCallListChanged: callback is null");
return;
}
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED, mSlotId,
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED, slotId,
0, callback).sendToTarget();
}
}
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index b6a81f9..4af31b5 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.SystemApi;
+import android.net.LinkProperties;
import android.os.RemoteException;
import android.telephony.Rlog;
import android.telephony.data.DataService.DataServiceProvider;
@@ -37,7 +38,7 @@
@SystemApi
public class DataServiceCallback {
- private static final String mTag = DataServiceCallback.class.getSimpleName();
+ private static final String TAG = DataServiceCallback.class.getSimpleName();
/**
* Result of data requests
@@ -46,7 +47,7 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef({RESULT_SUCCESS, RESULT_ERROR_UNSUPPORTED, RESULT_ERROR_INVALID_ARG, RESULT_ERROR_BUSY,
RESULT_ERROR_ILLEGAL_STATE})
- public @interface Result {}
+ public @interface ResultCode {}
/** Request is completed successfully */
public static final int RESULT_SUCCESS = 0;
@@ -68,35 +69,35 @@
/**
* Called to indicate result for the request {@link DataServiceProvider#setupDataCall(int,
- * DataProfile, boolean, boolean, boolean, DataServiceCallback)}.
+ * DataProfile, boolean, boolean, int, LinkProperties, DataServiceCallback)} .
*
- * @param result The result code. Must be one of the {@link Result}.
+ * @param result The result code. Must be one of the {@link ResultCode}.
* @param response Setup data call response.
*/
- public void onSetupDataCallComplete(@Result int result, DataCallResponse response) {
+ public void onSetupDataCallComplete(@ResultCode int result, DataCallResponse response) {
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
callback.onSetupDataCallComplete(result, response);
} catch (RemoteException e) {
- Rlog.e(mTag, "Failed to onSetupDataCallComplete on the remote");
+ Rlog.e(TAG, "Failed to onSetupDataCallComplete on the remote");
}
}
}
/**
* Called to indicate result for the request {@link DataServiceProvider#deactivateDataCall(int,
- * boolean, boolean, DataServiceCallback)}.
+ * int, DataServiceCallback)}
*
- * @param result The result code. Must be one of the {@link Result}.
+ * @param result The result code. Must be one of the {@link ResultCode}.
*/
- public void onDeactivateDataCallComplete(@Result int result) {
+ public void onDeactivateDataCallComplete(@ResultCode int result) {
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
callback.onDeactivateDataCallComplete(result);
} catch (RemoteException e) {
- Rlog.e(mTag, "Failed to onDeactivateDataCallComplete on the remote");
+ Rlog.e(TAG, "Failed to onDeactivateDataCallComplete on the remote");
}
}
}
@@ -105,15 +106,15 @@
* Called to indicate result for the request {@link DataServiceProvider#setInitialAttachApn(
* DataProfile, boolean, DataServiceCallback)}.
*
- * @param result The result code. Must be one of the {@link Result}.
+ * @param result The result code. Must be one of the {@link ResultCode}.
*/
- public void onSetInitialAttachApnComplete(@Result int result) {
+ public void onSetInitialAttachApnComplete(@ResultCode int result) {
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
callback.onSetInitialAttachApnComplete(result);
} catch (RemoteException e) {
- Rlog.e(mTag, "Failed to onSetInitialAttachApnComplete on the remote");
+ Rlog.e(TAG, "Failed to onSetInitialAttachApnComplete on the remote");
}
}
}
@@ -122,16 +123,16 @@
* Called to indicate result for the request {@link DataServiceProvider#setDataProfile(List,
* boolean, DataServiceCallback)}.
*
- * @param result The result code. Must be one of the {@link Result}.
+ * @param result The result code. Must be one of the {@link ResultCode}.
*/
@SystemApi
- public void onSetDataProfileComplete(@Result int result) {
+ public void onSetDataProfileComplete(@ResultCode int result) {
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
callback.onSetDataProfileComplete(result);
} catch (RemoteException e) {
- Rlog.e(mTag, "Failed to onSetDataProfileComplete on the remote");
+ Rlog.e(TAG, "Failed to onSetDataProfileComplete on the remote");
}
}
}
@@ -140,16 +141,17 @@
* Called to indicate result for the request {@link DataServiceProvider#getDataCallList(
* DataServiceCallback)}.
*
- * @param result The result code. Must be one of the {@link Result}.
+ * @param result The result code. Must be one of the {@link ResultCode}.
* @param dataCallList List of the current active data connection.
*/
- public void onGetDataCallListComplete(@Result int result, List<DataCallResponse> dataCallList) {
+ public void onGetDataCallListComplete(@ResultCode int result,
+ List<DataCallResponse> dataCallList) {
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
callback.onGetDataCallListComplete(result, dataCallList);
} catch (RemoteException e) {
- Rlog.e(mTag, "Failed to onGetDataCallListComplete on the remote");
+ Rlog.e(TAG, "Failed to onGetDataCallListComplete on the remote");
}
}
}
@@ -165,7 +167,7 @@
try {
callback.onDataCallListChanged(dataCallList);
} catch (RemoteException e) {
- Rlog.e(mTag, "Failed to onDataCallListChanged on the remote");
+ Rlog.e(TAG, "Failed to onDataCallListChanged on the remote");
}
}
}
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index 07720b6..d4d9be8 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -25,14 +25,17 @@
*/
oneway interface IDataService
{
- void setupDataCall(int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
+ void createDataServiceProvider(int slotId);
+ void removeDataServiceProvider(int slotId);
+ void setupDataCall(int slotId, int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
boolean allowRoaming, int reason, in LinkProperties linkProperties,
IDataServiceCallback callback);
- void deactivateDataCall(int cid, int reason, IDataServiceCallback callback);
- void setInitialAttachApn(in DataProfile dataProfile, boolean isRoaming,
+ void deactivateDataCall(int slotId, int cid, int reason, IDataServiceCallback callback);
+ void setInitialAttachApn(int slotId, in DataProfile dataProfile, boolean isRoaming,
IDataServiceCallback callback);
- void setDataProfile(in List<DataProfile> dps, boolean isRoaming, IDataServiceCallback callback);
- void getDataCallList(IDataServiceCallback callback);
- void registerForDataCallListChanged(IDataServiceCallback callback);
- void unregisterForDataCallListChanged(IDataServiceCallback callback);
+ void setDataProfile(int slotId, in List<DataProfile> dps, boolean isRoaming,
+ IDataServiceCallback callback);
+ void getDataCallList(int slotId, IDataServiceCallback callback);
+ void registerForDataCallListChanged(int slotId, IDataServiceCallback callback);
+ void unregisterForDataCallListChanged(int slotId, IDataServiceCallback callback);
}
diff --git a/telephony/java/com/android/ims/ImsCallForwardInfo.aidl b/telephony/java/android/telephony/ims/ImsCallForwardInfo.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsCallForwardInfo.aidl
rename to telephony/java/android/telephony/ims/ImsCallForwardInfo.aidl
index a7c3f9a..b322b39 100644
--- a/telephony/java/com/android/ims/ImsCallForwardInfo.aidl
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.telephony.ims;
parcelable ImsCallForwardInfo;
diff --git a/telephony/java/com/android/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
similarity index 77%
rename from telephony/java/com/android/ims/ImsCallForwardInfo.java
rename to telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index eeee0fc..6d72181 100644
--- a/telephony/java/com/android/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -11,11 +11,12 @@
* 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.
+ * limitations under the License
*/
-package com.android.ims;
+package android.telephony.ims;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -24,23 +25,32 @@
*
* @hide
*/
-public class ImsCallForwardInfo implements Parcelable {
+@SystemApi
+public final class ImsCallForwardInfo implements Parcelable {
// Refer to ImsUtInterface#CDIV_CF_XXX
+ /** @hide */
public int mCondition;
// 0: disabled, 1: enabled
+ /** @hide */
public int mStatus;
// 0x91: International, 0x81: Unknown
+ /** @hide */
public int mToA;
// Service class
+ /** @hide */
public int mServiceClass;
// Number (it will not include the "sip" or "tel" URI scheme)
+ /** @hide */
public String mNumber;
// No reply timer for CF
+ /** @hide */
public int mTimeSeconds;
+ /** @hide */
public ImsCallForwardInfo() {
}
+ /** @hide */
public ImsCallForwardInfo(Parcel in) {
readFromParcel(in);
}
@@ -91,4 +101,28 @@
return new ImsCallForwardInfo[size];
}
};
+
+ public int getCondition() {
+ return mCondition;
+ }
+
+ public int getStatus() {
+ return mStatus;
+ }
+
+ public int getToA() {
+ return mToA;
+ }
+
+ public int getServiceClass() {
+ return mServiceClass;
+ }
+
+ public String getNumber() {
+ return mNumber;
+ }
+
+ public int getTimeSeconds() {
+ return mTimeSeconds;
+ }
}
diff --git a/telephony/java/com/android/ims/ImsCallProfile.aidl b/telephony/java/android/telephony/ims/ImsCallProfile.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsCallProfile.aidl
rename to telephony/java/android/telephony/ims/ImsCallProfile.aidl
index a356d13..e24e145 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.aidl
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.telephony.ims;
parcelable ImsCallProfile;
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
similarity index 89%
rename from telephony/java/com/android/ims/ImsCallProfile.java
rename to telephony/java/android/telephony/ims/ImsCallProfile.java
index 693aaff..27e5f94 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -11,11 +11,12 @@
* 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.
+ * limitations under the License
*/
-package com.android.ims;
+package android.telephony.ims;
+import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,7 +33,8 @@
*
* @hide
*/
-public class ImsCallProfile implements Parcelable {
+@SystemApi
+public final class ImsCallProfile implements Parcelable {
private static final String TAG = "ImsCallProfile";
/**
@@ -110,52 +112,92 @@
* the video during voice call.
* conference_avail : Indicates if the session can be extended to the conference.
*/
+ /**
+ * @hide
+ */
public static final String EXTRA_CONFERENCE = "conference";
+ /**
+ * @hide
+ */
public static final String EXTRA_E_CALL = "e_call";
+ /**
+ * @hide
+ */
public static final String EXTRA_VMS = "vms";
+ /**
+ * @hide
+ */
public static final String EXTRA_CALL_MODE_CHANGEABLE = "call_mode_changeable";
+ /**
+ * @hide
+ */
public static final String EXTRA_CONFERENCE_AVAIL = "conference_avail";
// Extra string for internal use only. OEMs should not use
// this for packing extras.
+ /**
+ * @hide
+ */
public static final String EXTRA_OEM_EXTRAS = "OemCallExtras";
/**
- * Integer extra properties
- * oir : Rule for originating identity (number) presentation, MO/MT.
+ * Rule for originating identity (number) presentation, MO/MT.
* {@link ImsCallProfile#OIR_DEFAULT}
* {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
* {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
- * cnap : Rule for calling name presentation
+ */
+ public static final String EXTRA_OIR = "oir";
+ /**
+ * Rule for calling name presentation
* {@link ImsCallProfile#OIR_DEFAULT}
* {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
* {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
- * dialstring : To identify the Ims call type, MO
- * {@link ImsCallProfile#DIALSTRING_NORMAL_CALL}
+ */
+ public static final String EXTRA_CNAP = "cnap";
+ /**
+ * To identify the Ims call type, MO
+ * {@link ImsCallProfile#DIALSTRING_NORMAL}
* {@link ImsCallProfile#DIALSTRING_SS_CONF}
* {@link ImsCallProfile#DIALSTRING_USSD}
*/
- public static final String EXTRA_OIR = "oir";
- public static final String EXTRA_CNAP = "cnap";
public static final String EXTRA_DIALSTRING = "dialstring";
/**
* Values for EXTRA_OIR / EXTRA_CNAP
*/
+ /**
+ * Default presentation for Originating Identity.
+ */
public static final int OIR_DEFAULT = 0; // "user subscription default value"
+ /**
+ * Restricted presentation for Originating Identity.
+ */
public static final int OIR_PRESENTATION_RESTRICTED = 1;
+ /**
+ * Not restricted presentation for Originating Identity.
+ */
public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2;
+ /**
+ * Presentation unknown for Originating Identity.
+ */
public static final int OIR_PRESENTATION_UNKNOWN = 3;
+ /**
+ * Payphone presentation for Originating Identity.
+ */
public static final int OIR_PRESENTATION_PAYPHONE = 4;
+ //Values for EXTRA_DIALSTRING
/**
- * Values for EXTRA_DIALSTRING
+ * A default or normal normal call.
*/
- // default (normal call)
public static final int DIALSTRING_NORMAL = 0;
- // Call for SIP-based user configuration
+ /**
+ * Call for SIP-based user configuration
+ */
public static final int DIALSTRING_SS_CONF = 1;
- // Call for USSD message
+ /**
+ * Call for USSD message
+ */
public static final int DIALSTRING_USSD = 2;
/**
@@ -215,8 +257,11 @@
*/
public static final String EXTRA_CALL_RAT_TYPE_ALT = "callRadioTech";
+ /** @hide */
public int mServiceType;
+ /** @hide */
public int mCallType;
+ /** @hide */
public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
/**
@@ -241,13 +286,17 @@
* Invalid types will be removed when the {@link ImsCallProfile} is parceled for transmit across
* a {@link android.os.Binder}.
*/
+ /** @hide */
public Bundle mCallExtras;
+ /** @hide */
public ImsStreamMediaProfile mMediaProfile;
+ /** @hide */
public ImsCallProfile(Parcel in) {
readFromParcel(in);
}
+ /** @hide */
public ImsCallProfile() {
mServiceType = SERVICE_TYPE_NORMAL;
mCallType = CALL_TYPE_VOICE_N_VIDEO;
@@ -255,6 +304,7 @@
mMediaProfile = new ImsStreamMediaProfile();
}
+ /** @hide */
public ImsCallProfile(int serviceType, int callType) {
mServiceType = serviceType;
mCallType = callType;
@@ -366,8 +416,28 @@
}
};
+ public int getServiceType() {
+ return mServiceType;
+ }
+
+ public int getCallType() {
+ return mCallType;
+ }
+
+ public int getRestrictCause() {
+ return mRestrictCause;
+ }
+
+ public Bundle getCallExtras() {
+ return mCallExtras;
+ }
+
+ public ImsStreamMediaProfile getMediaProfile() {
+ return mMediaProfile;
+ }
+
/**
- * Converts from the call types defined in {@link com.android.ims.ImsCallProfile} to the
+ * Converts from the call types defined in {@link ImsCallProfile} to the
* video state values defined in {@link VideoProfile}.
*
* @param callProfile The call profile.
@@ -434,9 +504,9 @@
}
/**
- * Translate presentation value to OIR value
- * @param presentation
- * @return OIR valuse
+ * Badly named old method, kept for compatibility.
+ * See {@link #presentationToOir(int)}.
+ * @hide
*/
public static int presentationToOIR(int presentation) {
switch (presentation) {
@@ -454,9 +524,19 @@
}
/**
+ * Translate presentation value to OIR value
+ * @param presentation
+ * @return OIR values
+ */
+ public static int presentationToOir(int presentation) {
+ return presentationToOIR(presentation);
+ }
+
+ /**
* Translate OIR value to presentation value
* @param oir value
* @return presentation value
+ * @hide
*/
public static int OIRToPresentation(int oir) {
switch(oir) {
diff --git a/telephony/java/com/android/ims/internal/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
similarity index 90%
rename from telephony/java/com/android/ims/internal/ImsCallSession.java
rename to telephony/java/android/telephony/ims/ImsCallSession.java
index 1736b80..c3d103f 100644
--- a/telephony/java/com/android/ims/internal/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -11,23 +11,26 @@
* 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.
+ * limitations under the License
*/
-package com.android.ims.internal;
+package android.telephony.ims;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Message;
import android.os.RemoteException;
+import android.telephony.ims.aidl.IImsCallSessionListener;
import java.util.Objects;
+import java.util.concurrent.Executor;
-import android.telephony.ims.stub.ImsCallSessionListenerImplBase;
+import android.telephony.ims.stub.ImsCallSessionImplBase;
import android.util.Log;
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsConferenceState;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.ImsSuppServiceNotification;
+
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsVideoCallProvider;
/**
* Provides the call initiation/termination, and media exchange between two IMS endpoints.
@@ -39,7 +42,8 @@
private static final String TAG = "ImsCallSession";
/**
- * Defines IMS call session state.
+ * Defines IMS call session state. Please use {@link ImsCallSessionImplBase.State} definition.
+ * This is kept around for capability reasons.
*/
public static class State {
public static final int IDLE = 0;
@@ -92,6 +96,7 @@
* Listener for events relating to an IMS session, such as when a session is being
* recieved ("on ringing") or a call is outgoing ("on calling").
* <p>Many of these events are also received by {@link ImsCall.Listener}.</p>
+ * @hide
*/
public static class Listener {
/**
@@ -449,6 +454,7 @@
private boolean mClosed = false;
private Listener mListener;
+ /** @hide */
public ImsCallSession(IImsCallSession iSession) {
miSession = iSession;
@@ -462,6 +468,7 @@
}
}
+ /** @hide */
public ImsCallSession(IImsCallSession iSession, Listener listener) {
this(iSession);
setListener(listener);
@@ -470,15 +477,17 @@
/**
* Closes this object. This object is not usable after being closed.
*/
- public synchronized void close() {
- if (mClosed) {
- return;
- }
+ public void close() {
+ synchronized (this) {
+ if (mClosed) {
+ return;
+ }
- try {
- miSession.close();
- mClosed = true;
- } catch (RemoteException e) {
+ try {
+ miSession.close();
+ mClosed = true;
+ } catch (RemoteException e) {
+ }
}
}
@@ -554,6 +563,7 @@
* Gets the video call provider for the session.
*
* @return The video call provider.
+ * @hide
*/
public IImsVideoCallProvider getVideoCallProvider() {
if (mClosed) {
@@ -659,6 +669,7 @@
* override the previous listener.
*
* @param listener to listen to the session events of this object
+ * @hide
*/
public void setListener(Listener listener) {
mListener = listener;
@@ -987,7 +998,6 @@
* Sends Rtt Message
*
* @param rttMessage rtt text to be sent
- * @throws ImsException if call is absent
*/
public void sendRttMessage(String rttMessage) {
if (mClosed) {
@@ -1004,7 +1014,6 @@
* Sends RTT Upgrade request
*
* @param to : expected profile
- * @throws CallStateException
*/
public void sendRttModifyRequest(ImsCallProfile to) {
if (mClosed) {
@@ -1021,7 +1030,6 @@
* Sends RTT Upgrade response
*
* @param response : response for upgrade
- * @throws CallStateException
*/
public void sendRttModifyResponse(boolean response) {
if (mClosed) {
@@ -1040,37 +1048,33 @@
* the application is notified by having one of the methods called on
* the {@link IImsCallSessionListener}.
*/
- private class IImsCallSessionListenerProxy extends ImsCallSessionListenerImplBase {
+ private class IImsCallSessionListenerProxy extends IImsCallSessionListener.Stub {
/**
* Notifies the result of the basic session operation (setup / terminate).
*/
@Override
- public void callSessionProgressing(IImsCallSession session,
- ImsStreamMediaProfile profile) {
+ public void callSessionProgressing(ImsStreamMediaProfile profile) {
if (mListener != null) {
mListener.callSessionProgressing(ImsCallSession.this, profile);
}
}
@Override
- public void callSessionStarted(IImsCallSession session,
- ImsCallProfile profile) {
+ public void callSessionInitiated(ImsCallProfile profile) {
if (mListener != null) {
mListener.callSessionStarted(ImsCallSession.this, profile);
}
}
@Override
- public void callSessionStartFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
+ public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
}
}
@Override
- public void callSessionTerminated(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
+ public void callSessionTerminated(ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
}
@@ -1080,48 +1084,42 @@
* Notifies the result of the call hold/resume operation.
*/
@Override
- public void callSessionHeld(IImsCallSession session,
- ImsCallProfile profile) {
+ public void callSessionHeld(ImsCallProfile profile) {
if (mListener != null) {
mListener.callSessionHeld(ImsCallSession.this, profile);
}
}
@Override
- public void callSessionHoldFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
+ public void callSessionHoldFailed(ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
}
}
@Override
- public void callSessionHoldReceived(IImsCallSession session,
- ImsCallProfile profile) {
+ public void callSessionHoldReceived(ImsCallProfile profile) {
if (mListener != null) {
mListener.callSessionHoldReceived(ImsCallSession.this, profile);
}
}
@Override
- public void callSessionResumed(IImsCallSession session,
- ImsCallProfile profile) {
+ public void callSessionResumed(ImsCallProfile profile) {
if (mListener != null) {
mListener.callSessionResumed(ImsCallSession.this, profile);
}
}
@Override
- public void callSessionResumeFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
+ public void callSessionResumeFailed(ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
}
}
@Override
- public void callSessionResumeReceived(IImsCallSession session,
- ImsCallProfile profile) {
+ public void callSessionResumeReceived(ImsCallProfile profile) {
if (mListener != null) {
mListener.callSessionResumeReceived(ImsCallSession.this, profile);
}
@@ -1130,13 +1128,11 @@
/**
* Notifies the start of a call merge operation.
*
- * @param session The call session.
* @param newSession The merged call session.
* @param profile The call profile.
*/
@Override
- public void callSessionMergeStarted(IImsCallSession session,
- IImsCallSession newSession, ImsCallProfile profile) {
+ public void callSessionMergeStarted(IImsCallSession newSession, ImsCallProfile profile) {
// This callback can be used for future use to add additional
// functionality that may be needed between conference start and complete
Log.d(TAG, "callSessionMergeStarted");
@@ -1173,12 +1169,10 @@
/**
* Notifies of a failure to perform a call merge operation.
*
- * @param session The call session.
* @param reasonInfo The merge failure reason.
*/
@Override
- public void callSessionMergeFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
+ public void callSessionMergeFailed(ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
}
@@ -1188,24 +1182,21 @@
* Notifies the result of call upgrade / downgrade or any other call updates.
*/
@Override
- public void callSessionUpdated(IImsCallSession session,
- ImsCallProfile profile) {
+ public void callSessionUpdated(ImsCallProfile profile) {
if (mListener != null) {
mListener.callSessionUpdated(ImsCallSession.this, profile);
}
}
@Override
- public void callSessionUpdateFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
+ public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
}
}
@Override
- public void callSessionUpdateReceived(IImsCallSession session,
- ImsCallProfile profile) {
+ public void callSessionUpdateReceived(ImsCallProfile profile) {
if (mListener != null) {
mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
}
@@ -1215,8 +1206,8 @@
* Notifies the result of conference extension.
*/
@Override
- public void callSessionConferenceExtended(IImsCallSession session,
- IImsCallSession newSession, ImsCallProfile profile) {
+ public void callSessionConferenceExtended(IImsCallSession newSession,
+ ImsCallProfile profile) {
if (mListener != null) {
mListener.callSessionConferenceExtended(ImsCallSession.this,
new ImsCallSession(newSession), profile);
@@ -1224,16 +1215,15 @@
}
@Override
- public void callSessionConferenceExtendFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
+ public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo);
}
}
@Override
- public void callSessionConferenceExtendReceived(IImsCallSession session,
- IImsCallSession newSession, ImsCallProfile profile) {
+ public void callSessionConferenceExtendReceived(IImsCallSession newSession,
+ ImsCallProfile profile) {
if (mListener != null) {
mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
new ImsCallSession(newSession), profile);
@@ -1245,15 +1235,14 @@
* the conference session.
*/
@Override
- public void callSessionInviteParticipantsRequestDelivered(IImsCallSession session) {
+ public void callSessionInviteParticipantsRequestDelivered() {
if (mListener != null) {
mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this);
}
}
@Override
- public void callSessionInviteParticipantsRequestFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
+ public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
reasonInfo);
@@ -1261,15 +1250,14 @@
}
@Override
- public void callSessionRemoveParticipantsRequestDelivered(IImsCallSession session) {
+ public void callSessionRemoveParticipantsRequestDelivered() {
if (mListener != null) {
mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
}
}
@Override
- public void callSessionRemoveParticipantsRequestFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
+ public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
reasonInfo);
@@ -1280,8 +1268,7 @@
* Notifies the changes of the conference info. in the conference session.
*/
@Override
- public void callSessionConferenceStateUpdated(IImsCallSession session,
- ImsConferenceState state) {
+ public void callSessionConferenceStateUpdated(ImsConferenceState state) {
if (mListener != null) {
mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
}
@@ -1291,17 +1278,15 @@
* Notifies the incoming USSD message.
*/
@Override
- public void callSessionUssdMessageReceived(IImsCallSession session,
- int mode, String ussdMessage) {
+ public void callSessionUssdMessageReceived(int mode, String ussdMessage) {
if (mListener != null) {
mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage);
}
}
/**
- * Notifies of a case where a {@link com.android.ims.internal.ImsCallSession} may
+ * Notifies of a case where a {@link ImsCallSession} may
* potentially handover from one radio technology to another.
- * @param session
* @param srcAccessTech The source radio access technology; one of the access technology
* constants defined in {@link android.telephony.ServiceState}. For
* example
@@ -1312,8 +1297,7 @@
* {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
*/
@Override
- public void callSessionMayHandover(IImsCallSession session,
- int srcAccessTech, int targetAccessTech) {
+ public void callSessionMayHandover(int srcAccessTech, int targetAccessTech) {
if (mListener != null) {
mListener.callSessionMayHandover(ImsCallSession.this, srcAccessTech,
targetAccessTech);
@@ -1324,9 +1308,8 @@
* Notifies of handover information for this call
*/
@Override
- public void callSessionHandover(IImsCallSession session,
- int srcAccessTech, int targetAccessTech,
- ImsReasonInfo reasonInfo) {
+ public void callSessionHandover(int srcAccessTech, int targetAccessTech,
+ ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionHandover(ImsCallSession.this, srcAccessTech,
targetAccessTech, reasonInfo);
@@ -1337,9 +1320,8 @@
* Notifies of handover failure info for this call
*/
@Override
- public void callSessionHandoverFailed(IImsCallSession session,
- int srcAccessTech, int targetAccessTech,
- ImsReasonInfo reasonInfo) {
+ public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
+ ImsReasonInfo reasonInfo) {
if (mListener != null) {
mListener.callSessionHandoverFailed(ImsCallSession.this, srcAccessTech,
targetAccessTech, reasonInfo);
@@ -1350,8 +1332,7 @@
* Notifies the TTY mode received from remote party.
*/
@Override
- public void callSessionTtyModeReceived(IImsCallSession session,
- int mode) {
+ public void callSessionTtyModeReceived(int mode) {
if (mListener != null) {
mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
}
@@ -1360,21 +1341,17 @@
/**
* Notifies of a change to the multiparty state for this {@code ImsCallSession}.
*
- * @param session The call session.
* @param isMultiParty {@code true} if the session became multiparty, {@code false}
* otherwise.
*/
- public void callSessionMultipartyStateChanged(IImsCallSession session,
- boolean isMultiParty) {
-
+ public void callSessionMultipartyStateChanged(boolean isMultiParty) {
if (mListener != null) {
mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty);
}
}
@Override
- public void callSessionSuppServiceReceived(IImsCallSession session,
- ImsSuppServiceNotification suppServiceInfo ) {
+ public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppServiceInfo ) {
if (mListener != null) {
mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo);
}
@@ -1384,8 +1361,7 @@
* Received RTT modify request from remote party
*/
@Override
- public void callSessionRttModifyRequestReceived(IImsCallSession session,
- ImsCallProfile callProfile) {
+ public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile) {
if (mListener != null) {
mListener.callSessionRttModifyRequestReceived(ImsCallSession.this, callProfile);
}
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
new file mode 100644
index 0000000..a7f124a
--- /dev/null
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -0,0 +1,603 @@
+/*
+ * 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.telephony.ims;
+
+import android.annotation.SystemApi;
+import android.os.RemoteException;
+import android.telephony.ims.aidl.IImsCallSessionListener;
+import android.telephony.ims.stub.ImsCallSessionImplBase;
+
+import com.android.ims.internal.IImsCallSession;
+
+/**
+ * Listener interface for notifying the Framework's {@link ImsCallSession} for updates to an ongoing
+ * IMS call.
+ *
+ * @hide
+ */
+// DO NOT remove or change the existing APIs, only add new ones to this implementation or you
+// will break other implementations of ImsCallSessionListener maintained by other ImsServices.
+// TODO: APIs in here do not conform to API guidelines yet. This can be changed if
+// ImsCallSessionListenerConverter is also changed.
+@SystemApi
+public class ImsCallSessionListener {
+
+ private final IImsCallSessionListener mListener;
+
+ /** @hide */
+ public ImsCallSessionListener(IImsCallSessionListener l) {
+ mListener = l;
+ }
+
+ /**
+ * A request has been sent out to initiate a new IMS call session and a 1xx response has been
+ * received from the network.
+ */
+ public void callSessionProgressing(ImsStreamMediaProfile profile) {
+ try {
+ mListener.callSessionProgressing(profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session has been initiated.
+ *
+ * @param profile the associated {@link ImsCallProfile}.
+ */
+ public void callSessionInitiated(ImsCallProfile profile) {
+ try {
+ mListener.callSessionInitiated(profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session establishment has failed.
+ *
+ * @param reasonInfo {@link ImsReasonInfo} detailing the reason of the IMS call session
+ * establishment failure.
+ */
+ public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) {
+ try {
+ mListener.callSessionInitiatedFailed(reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session has been terminated.
+ *
+ * @param reasonInfo {@link ImsReasonInfo} detailing the reason of the session termination.
+ */
+ public void callSessionTerminated(ImsReasonInfo reasonInfo) {
+ try {
+ mListener.callSessionTerminated(reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session has started the process of holding the call. If it fails,
+ * {@link #callSessionHoldFailed(ImsReasonInfo)} should be called.
+ *
+ * If the IMS call session is resumed, call {@link #callSessionResumed(ImsCallProfile)}.
+ *
+ * @param profile The associated {@link ImsCallProfile} of the call session that has been put
+ * on hold.
+ */
+ public void callSessionHeld(ImsCallProfile profile) {
+ try {
+ mListener.callSessionHeld(profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session has failed to be held.
+ *
+ * @param reasonInfo {@link ImsReasonInfo} detailing the reason of the session hold failure.
+ */
+ public void callSessionHoldFailed(ImsReasonInfo reasonInfo) {
+ try {
+ mListener.callSessionHoldFailed(reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * This IMS Call session has been put on hold by the remote party.
+ *
+ * @param profile The {@link ImsCallProfile} associated with this IMS call session.
+ */
+ public void callSessionHoldReceived(ImsCallProfile profile) {
+ try {
+ mListener.callSessionHoldReceived(profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session has started the process of resuming the call. If the process of resuming
+ * the call fails, call {@link #callSessionResumeFailed(ImsReasonInfo)}.
+ *
+ * @param profile The {@link ImsCallProfile} associated with this IMS call session.
+ */
+ public void callSessionResumed(ImsCallProfile profile) {
+ try {
+ mListener.callSessionResumed(profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session resume has failed.
+ *
+ * @param reasonInfo {@link ImsReasonInfo} containing the detailed reason of the session resume
+ * failure.
+ */
+ public void callSessionResumeFailed(ImsReasonInfo reasonInfo) {
+ try {
+ mListener.callSessionResumeFailed(reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The remote party has resumed this IMS call session.
+ *
+ * @param profile {@link ImsCallProfile} associated with the IMS call session.
+ */
+ public void callSessionResumeReceived(ImsCallProfile profile) {
+ try {
+ mListener.callSessionResumeReceived(profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session merge has been started. At this point, the {@code newSession}
+ * represents the IMS call session which represents the new merged conference and has been
+ * initiated to the IMS conference server.
+ *
+ * @param newSession the {@link ImsCallSessionImplBase} that represents the merged active & held
+ * sessions.
+ * @param profile The {@link ImsCallProfile} associated with this IMS call session.
+ */
+ public void callSessionMergeStarted(ImsCallSessionImplBase newSession, ImsCallProfile profile)
+ {
+ try {
+ mListener.callSessionMergeStarted(newSession != null ?
+ newSession.getServiceImpl() : null, profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Compatibility method for older implementations.
+ * See {@link #callSessionMergeStarted(ImsCallSessionImplBase, ImsCallProfile)}.
+ *
+ * @hide
+ */
+ public void callSessionMergeStarted(IImsCallSession newSession, ImsCallProfile profile)
+ {
+ try {
+ mListener.callSessionMergeStarted(newSession, profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The session merge is successful and the merged {@link ImsCallSession} is active.
+ *
+ * @param newSession the new {@link ImsCallSessionImplBase}
+ * that represents the conference IMS call
+ * session.
+ */
+ public void callSessionMergeComplete(ImsCallSessionImplBase newSession) {
+ try {
+ mListener.callSessionMergeComplete(newSession != null ?
+ newSession.getServiceImpl() : null);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Compatibility method for older implementations of ImsService.
+ *
+ * See {@link #callSessionMergeComplete(ImsCallSessionImplBase)}}.
+ *
+ * @hide
+ */
+ public void callSessionMergeComplete(IImsCallSession newSession) {
+ try {
+ mListener.callSessionMergeComplete(newSession);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session merge has failed.
+ *
+ * @param reasonInfo {@link ImsReasonInfo} contining the reason for the call merge failure.
+ */
+ public void callSessionMergeFailed(ImsReasonInfo reasonInfo) {
+ try {
+ mListener.callSessionMergeFailed(reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session profile has been updated. Does not include holding or resuming a call.
+ *
+ * @param profile The {@link ImsCallProfile} associated with the updated IMS call session.
+ */
+ public void callSessionUpdated(ImsCallProfile profile) {
+ try {
+ mListener.callSessionUpdated(profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session profile update has failed.
+ *
+ * @param reasonInfo {@link ImsReasonInfo} containing a reason for the session update failure.
+ */
+ public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) {
+ try {
+ mListener.callSessionUpdateFailed(reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session profile has received an update from the remote user.
+ *
+ * @param profile The new {@link ImsCallProfile} associated with the update.
+ */
+ public void callSessionUpdateReceived(ImsCallProfile profile) {
+ try {
+ mListener.callSessionUpdateReceived(profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Called when the session has been extended to a conference session.
+ *
+ * If the conference extension fails, call
+ * {@link #callSessionConferenceExtendFailed(ImsReasonInfo)}.
+ *
+ * @param newSession the session object that is extended to the conference from the active
+ * IMS Call session.
+ * @param profile The {@link ImsCallProfile} associated with the IMS call session.
+ */
+ public void callSessionConferenceExtended(ImsCallSessionImplBase newSession,
+ ImsCallProfile profile) {
+ try {
+ mListener.callSessionConferenceExtended(
+ newSession != null ? newSession.getServiceImpl() : null, profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Compatibility method to interface with older versions of ImsService.
+ * See {@link #callSessionConferenceExtended(ImsCallSessionImplBase, ImsCallProfile)}.
+ *
+ * @hide
+ */
+ public void callSessionConferenceExtended(IImsCallSession newSession, ImsCallProfile profile) {
+ try {
+ mListener.callSessionConferenceExtended(newSession, profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The previous conference extension has failed.
+ *
+ * @param reasonInfo {@link ImsReasonInfo} containing the detailed reason of the conference
+ * extension failure.
+ */
+ public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) {
+ try {
+ mListener.callSessionConferenceExtendFailed(reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * A conference extension has been received received from the remote party.
+ *
+ * @param newSession An {@link ImsCallSessionImplBase}
+ * representing the extended IMS call session.
+ * @param profile The {@link ImsCallProfile} associated with the new IMS call session.
+ */
+ public void callSessionConferenceExtendReceived(ImsCallSessionImplBase newSession,
+ ImsCallProfile profile) {
+ try {
+ mListener.callSessionConferenceExtendReceived(newSession != null
+ ? newSession.getServiceImpl() : null, profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Compatibility method to interface with older versions of ImsService.
+ * See {@link #callSessionConferenceExtendReceived(ImsCallSessionImplBase, ImsCallProfile)}.
+ *
+ * @hide
+ */
+ public void callSessionConferenceExtendReceived(IImsCallSession newSession,
+ ImsCallProfile profile) {
+ try {
+ mListener.callSessionConferenceExtendReceived(newSession, profile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The request to invite participants to the conference has been delivered to the conference
+ * server.
+ */
+ public void callSessionInviteParticipantsRequestDelivered() {
+ try {
+ mListener.callSessionInviteParticipantsRequestDelivered();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The previous request to invite participants to the conference (see
+ * {@link #callSessionInviteParticipantsRequestDelivered()}) has failed.
+ *
+ * @param reasonInfo {@link ImsReasonInfo} detailing the reason forthe conference invitation
+ * failure.
+ */
+ public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo)
+ {
+ try {
+ mListener.callSessionInviteParticipantsRequestFailed(reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The request to remove participants from the conference has been delivered to the conference
+ * server.
+ */
+ public void callSessionRemoveParticipantsRequestDelivered() {
+ try {
+ mListener.callSessionRemoveParticipantsRequestDelivered();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The previous request to remove participants from the conference (see
+ * {@link #callSessionRemoveParticipantsRequestDelivered()}) has failed.
+ *
+ * @param reasonInfo {@link ImsReasonInfo} detailing the reason for the conference removal
+ * failure.
+ */
+ public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo)
+ {
+ try {
+ mListener.callSessionInviteParticipantsRequestFailed(reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session's conference state has changed.
+ *
+ * @param state The new {@link ImsConferenceState} associated with the conference.
+ */
+ public void callSessionConferenceStateUpdated(ImsConferenceState state) {
+ try {
+ mListener.callSessionConferenceStateUpdated(state);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session has received a Ussd message.
+ *
+ * @param mode The mode of the USSD message, either
+ * {@link ImsCallSessionImplBase#USSD_MODE_NOTIFY} or
+ * {@link ImsCallSessionImplBase#USSD_MODE_REQUEST}.
+ * @param ussdMessage The USSD message.
+ */
+ public void callSessionUssdMessageReceived(int mode, String ussdMessage)
+ {
+ try {
+ mListener.callSessionUssdMessageReceived(mode, ussdMessage);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * An {@link ImsCallSession} may potentially handover from one radio
+ * technology to another.
+ *
+ * @param srcAccessTech The source radio access technology; one of the access technology
+ * constants defined in {@link android.telephony.ServiceState}. For example
+ * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
+ * @param targetAccessTech The target radio access technology; one of the access technology
+ * constants defined in {@link android.telephony.ServiceState}. For example
+ * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
+ */
+ public void callSessionMayHandover(int srcAccessTech, int targetAccessTech)
+ {
+ try {
+ mListener.callSessionMayHandover(srcAccessTech, targetAccessTech);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session's access technology has changed.
+ *
+ * @param srcAccessTech original access technology, defined in
+ * {@link android.telephony.ServiceState}.
+ * @param targetAccessTech new access technology, defined in
+ * {@link android.telephony.ServiceState}.
+ * @param reasonInfo The {@link ImsReasonInfo} associated with this handover.
+ */
+ public void callSessionHandover(int srcAccessTech, int targetAccessTech,
+ ImsReasonInfo reasonInfo) {
+ try {
+ mListener.callSessionHandover(srcAccessTech, targetAccessTech, reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The IMS call session's access technology change has failed..
+ *
+ * @param srcAccessTech original access technology
+ * @param targetAccessTech new access technology
+ * @param reasonInfo An {@link ImsReasonInfo} detailing the reason for the failure.
+ */
+ public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
+ ImsReasonInfo reasonInfo) {
+ try {
+ mListener.callSessionHandoverFailed(srcAccessTech, targetAccessTech, reasonInfo);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The TTY mode has been changed by the remote party.
+ *
+ * @param mode one of the following: -
+ * {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} -
+ * {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} -
+ * {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} -
+ * {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
+ */
+ public void callSessionTtyModeReceived(int mode) {
+ try {
+ mListener.callSessionTtyModeReceived(mode);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * The multiparty state has been changed for this {@code ImsCallSession}.
+ *
+ * @param isMultiParty {@code true} if the session became multiparty, {@code false} otherwise.
+ */
+ public void callSessionMultipartyStateChanged(boolean isMultiParty) {
+ try {
+ mListener.callSessionMultipartyStateChanged(isMultiParty);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Supplementary service information has been received for the current IMS call session.
+ *
+ * @param suppSrvNotification The {@link ImsSuppServiceNotification} containing the change.
+ */
+ public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppSrvNotification)
+ {
+ try {
+ mListener.callSessionSuppServiceReceived(suppSrvNotification);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * An RTT modify request has been received from the remote party.
+ *
+ * @param callProfile An {@link ImsCallProfile} with the updated attributes
+ */
+ public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile)
+ {
+ try {
+ mListener.callSessionRttModifyRequestReceived(callProfile);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * An RTT modify response has been received.
+ *
+ * @param status the received response for RTT modify request.
+ */
+ public void callSessionRttModifyResponseReceived(int status) {
+ try {
+ mListener.callSessionRttModifyResponseReceived(status);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * An RTT message has been received from the remote party.
+ *
+ * @param rttMessage The RTT message that has been received.
+ */
+ public void callSessionRttMessageReceived(String rttMessage) {
+ try {
+ mListener.callSessionRttMessageReceived(rttMessage);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
+
diff --git a/telephony/java/com/android/ims/ImsConferenceState.aidl b/telephony/java/android/telephony/ims/ImsConferenceState.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsConferenceState.aidl
rename to telephony/java/android/telephony/ims/ImsConferenceState.aidl
index 2fc029f..e2b371c 100644
--- a/telephony/java/com/android/ims/ImsConferenceState.aidl
+++ b/telephony/java/android/telephony/ims/ImsConferenceState.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.telephony.ims;
parcelable ImsConferenceState;
diff --git a/telephony/java/com/android/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java
similarity index 95%
rename from telephony/java/com/android/ims/ImsConferenceState.java
rename to telephony/java/android/telephony/ims/ImsConferenceState.java
index 0afde88..66d2f8d 100644
--- a/telephony/java/com/android/ims/ImsConferenceState.java
+++ b/telephony/java/android/telephony/ims/ImsConferenceState.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -11,16 +11,17 @@
* 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.
+ * limitations under the License
*/
-package com.android.ims;
+package android.telephony.ims;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
+import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,7 +33,8 @@
*
* @hide
*/
-public class ImsConferenceState implements Parcelable {
+@SystemApi
+public final class ImsConferenceState implements Parcelable {
/**
* conference-info : user
*/
@@ -87,12 +89,13 @@
*/
public static final String SIP_STATUS_CODE = "sipstatuscode";
- public HashMap<String, Bundle> mParticipants = new HashMap<String, Bundle>();
+ public final HashMap<String, Bundle> mParticipants = new HashMap<String, Bundle>();
+ /** @hide */
public ImsConferenceState() {
}
- public ImsConferenceState(Parcel in) {
+ private ImsConferenceState(Parcel in) {
readFromParcel(in);
}
diff --git a/telephony/java/com/android/ims/ImsExternalCallState.aidl b/telephony/java/android/telephony/ims/ImsExternalCallState.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsExternalCallState.aidl
rename to telephony/java/android/telephony/ims/ImsExternalCallState.aidl
index c208702..99d2935 100644
--- a/telephony/java/com/android/ims/ImsExternalCallState.aidl
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.telephony.ims;
parcelable ImsExternalCallState;
diff --git a/telephony/java/com/android/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
similarity index 92%
rename from telephony/java/com/android/ims/ImsExternalCallState.java
rename to telephony/java/android/telephony/ims/ImsExternalCallState.java
index da26073..e82c115 100644
--- a/telephony/java/com/android/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016 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.
@@ -11,11 +11,12 @@
* 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.
+ * limitations under the License
*/
-package com.android.ims;
+package android.telephony.ims;
+import android.annotation.SystemApi;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,7 +33,8 @@
* Parcelable object to handle MultiEndpoint Dialog Information
* @hide
*/
-public class ImsExternalCallState implements Parcelable {
+@SystemApi
+public final class ImsExternalCallState implements Parcelable {
private static final String TAG = "ImsExternalCallState";
@@ -50,9 +52,11 @@
private int mCallType;
private boolean mIsHeld;
+ /** @hide */
public ImsExternalCallState() {
}
+ /** @hide */
public ImsExternalCallState(int callId, Uri address, boolean isPullable, int callState,
int callType, boolean isCallheld) {
mCallId = callId;
@@ -64,6 +68,7 @@
Rlog.d(TAG, "ImsExternalCallState = " + this);
}
+ /** @hide */
public ImsExternalCallState(Parcel in) {
mCallId = in.readInt();
ClassLoader classLoader = ImsExternalCallState.class.getClassLoader();
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.aidl b/telephony/java/android/telephony/ims/ImsReasonInfo.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsReasonInfo.aidl
rename to telephony/java/android/telephony/ims/ImsReasonInfo.aidl
index 17e6d3a..604b323 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.aidl
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.telephony.ims;
parcelable ImsReasonInfo;
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
similarity index 97%
rename from telephony/java/com/android/ims/ImsReasonInfo.java
rename to telephony/java/android/telephony/ims/ImsReasonInfo.java
index 83d9bd9..7b77491 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -11,11 +11,12 @@
* 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.
+ * limitations under the License
*/
-package com.android.ims;
+package android.telephony.ims;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -24,7 +25,8 @@
*
* @hide
*/
-public class ImsReasonInfo implements Parcelable {
+@SystemApi
+public final class ImsReasonInfo implements Parcelable {
/**
* Specific code of each types
@@ -418,27 +420,36 @@
// For main reason code
+ /** @hide */
public int mCode;
// For the extra code value; it depends on the code value.
+ /** @hide */
public int mExtraCode;
// For the additional message of the reason info.
+ /** @hide */
public String mExtraMessage;
+
+ /** @hide */
public ImsReasonInfo() {
mCode = CODE_UNSPECIFIED;
mExtraCode = CODE_UNSPECIFIED;
mExtraMessage = null;
}
- public ImsReasonInfo(Parcel in) {
- readFromParcel(in);
+ private ImsReasonInfo(Parcel in) {
+ mCode = in.readInt();
+ mExtraCode = in.readInt();
+ mExtraMessage = in.readString();
}
+ /** @hide */
public ImsReasonInfo(int code, int extraCode) {
mCode = code;
mExtraCode = extraCode;
mExtraMessage = null;
}
+ /** @hide */
public ImsReasonInfo(int code, int extraCode, String extraMessage) {
mCode = code;
mExtraCode = extraCode;
@@ -487,12 +498,6 @@
out.writeString(mExtraMessage);
}
- private void readFromParcel(Parcel in) {
- mCode = in.readInt();
- mExtraCode = in.readInt();
- mExtraMessage = in.readString();
- }
-
public static final Creator<ImsReasonInfo> CREATOR = new Creator<ImsReasonInfo>() {
@Override
public ImsReasonInfo createFromParcel(Parcel in) {
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index aaa0f08..2748cb5 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -16,25 +16,28 @@
package android.telephony.ims;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.CarrierConfigManager;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.IImsServiceController;
+import android.telephony.ims.aidl.IImsServiceControllerListener;
import android.telephony.ims.feature.ImsFeature;
-import android.telephony.ims.feature.MMTelFeature;
+import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.feature.RcsFeature;
+import android.telephony.ims.stub.ImsConfigImplBase;
+import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;
import android.util.SparseArray;
import com.android.ims.internal.IImsFeatureStatusCallback;
-import com.android.ims.internal.IImsMMTelFeature;
-import com.android.ims.internal.IImsRcsFeature;
-import com.android.ims.internal.IImsRegistration;
-import com.android.ims.internal.IImsServiceController;
import com.android.internal.annotations.VisibleForTesting;
import static android.Manifest.permission.MODIFY_PHONE_STATE;
@@ -48,9 +51,7 @@
* ...
* <service android:name=".EgImsService"
* android:permission="android.permission.BIND_IMS_SERVICE" >
- * <!-- Apps must declare which features they support as metadata. The different categories are
- * defined below. In this example, the RCS_FEATURE feature is supported. -->
- * <meta-data android:name="android.telephony.ims.RCS_FEATURE" android:value="true" />
+ * ...
* <intent-filter>
* <action android:name="android.telephony.ims.ImsService" />
* </intent-filter>
@@ -64,13 +65,31 @@
* 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using
* {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}.
*
+ * There are two ways to define to the platform which {@link ImsFeature}s this {@link ImsService}
+ * supports, dynamic or static definitions.
+ *
+ * In the static definition, the {@link ImsFeature}s that are supported are defined in the service
+ * definition of the AndroidManifest.xml file as metadata:
+ * <!-- Apps must declare which features they support as metadata. The different categories are
+ * defined below. In this example, the MMTEL_FEATURE feature is supported. -->
+ * <meta-data android:name="android.telephony.ims.MMTEL_FEATURE" android:value="true" />
+ *
* The features that are currently supported in an ImsService are:
* - RCS_FEATURE: This ImsService implements the RcsFeature class.
- * - MMTEL_FEATURE: This ImsService implements the MMTelFeature class.
- * - EMERGENCY_MMTEL_FEATURE: This ImsService implements the MMTelFeature class and will be
- * available to place emergency calls at all times. This MUST be implemented by the default
- * ImsService provided in the device overlay.
- * @hide
+ * - MMTEL_FEATURE: This ImsService implements the MmTelFeature class.
+ * - EMERGENCY_MMTEL_FEATURE: This ImsService supports Emergency Calling for MMTEL, must be
+ * declared along with the MMTEL_FEATURE. If this is not specified, the framework will use
+ * circuit switch for emergency calling.
+ *
+ * In the dynamic definition, the supported features are not specified in the service definition
+ * of the AndroidManifest. Instead, the framework binds to this service and calls
+ * {@link #querySupportedImsFeatures()}. The {@link ImsService} then returns an
+ * {@link ImsFeatureConfiguration}, which the framework uses to initialize the supported
+ * {@link ImsFeature}s. If at any time, the list of supported {@link ImsFeature}s changes,
+ * {@link #onUpdateSupportedImsFeatures(ImsFeatureConfiguration)} can be called to tell the
+ * framework of the changes.
+ *
+ * @hide
*/
@SystemApi
public class ImsService extends Service {
@@ -89,20 +108,36 @@
// call ImsFeature#onFeatureRemoved.
private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
+ private IImsServiceControllerListener mListener;
+
+
+ /**
+ * Listener that notifies the framework of ImsService changes.
+ * @hide
+ */
+ public static class Listener extends IImsServiceControllerListener.Stub {
+ /**
+ * The IMS features that this ImsService supports has changed.
+ * @param c a new {@link ImsFeatureConfiguration} containing {@link ImsFeature.FeatureType}s
+ * that this ImsService supports. This may trigger the addition/removal of feature
+ * in this service.
+ */
+ public void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c) {
+ }
+ }
+
/**
* @hide
*/
protected final IBinder mImsServiceController = new IImsServiceController.Stub() {
-
@Override
- public IImsMMTelFeature createEmergencyMMTelFeature(int slotId,
- IImsFeatureStatusCallback c) {
- return createEmergencyMMTelFeatureInternal(slotId, c);
+ public void setListener(IImsServiceControllerListener l) {
+ mListener = l;
}
@Override
- public IImsMMTelFeature createMMTelFeature(int slotId, IImsFeatureStatusCallback c) {
- return createMMTelFeatureInternal(slotId, c);
+ public IImsMmTelFeature createMmTelFeature(int slotId, IImsFeatureStatusCallback c) {
+ return createMmTelFeatureInternal(slotId, c);
}
@Override
@@ -111,16 +146,46 @@
}
@Override
- public void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
- throws RemoteException {
+ public void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c) {
ImsService.this.removeImsFeature(slotId, featureType, c);
}
@Override
- public IImsRegistration getRegistration(int slotId) throws RemoteException {
+ public ImsFeatureConfiguration querySupportedImsFeatures() {
+ return ImsService.this.querySupportedImsFeatures();
+ }
+
+ @Override
+ public void notifyImsServiceReadyForFeatureCreation() {
+ ImsService.this.readyForFeatureCreation();
+ }
+
+ @Override
+ public void notifyImsFeatureReady(int slotId, int featureType) {
+ ImsService.this.notifyImsFeatureReady(slotId, featureType);
+ }
+
+ @Override
+ public IImsConfig getConfig(int slotId) {
+ ImsConfigImplBase c = ImsService.this.getConfig(slotId);
+ return c != null ? c.getIImsConfig() : null;
+ }
+
+ @Override
+ public IImsRegistration getRegistration(int slotId) {
ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId);
return r != null ? r.getBinder() : null;
}
+
+ @Override
+ public void enableIms(int slotId) {
+ ImsService.this.enableIms(slotId);
+ }
+
+ @Override
+ public void disableIms(int slotId) {
+ ImsService.this.disableIms(slotId);
+ }
};
/**
@@ -143,47 +208,35 @@
return mFeaturesBySlot.get(slotId);
}
- private IImsMMTelFeature createEmergencyMMTelFeatureInternal(int slotId,
+ private IImsMmTelFeature createMmTelFeatureInternal(int slotId,
IImsFeatureStatusCallback c) {
- MMTelFeature f = onCreateEmergencyMMTelImsFeature(slotId);
+ MmTelFeature f = createMmTelFeature(slotId);
if (f != null) {
- setupFeature(f, slotId, ImsFeature.EMERGENCY_MMTEL, c);
+ setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL, c);
return f.getBinder();
} else {
- return null;
- }
- }
-
- private IImsMMTelFeature createMMTelFeatureInternal(int slotId,
- IImsFeatureStatusCallback c) {
- MMTelFeature f = onCreateMMTelImsFeature(slotId);
- if (f != null) {
- setupFeature(f, slotId, ImsFeature.MMTEL, c);
- return f.getBinder();
- } else {
+ Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned.");
return null;
}
}
private IImsRcsFeature createRcsFeatureInternal(int slotId,
IImsFeatureStatusCallback c) {
- RcsFeature f = onCreateRcsFeature(slotId);
+ RcsFeature f = createRcsFeature(slotId);
if (f != null) {
- setupFeature(f, slotId, ImsFeature.RCS, c);
+ setupFeature(f, slotId, ImsFeature.FEATURE_RCS, c);
return f.getBinder();
} else {
+ Log.e(LOG_TAG, "createRcsFeatureInternal: null feature returned.");
return null;
}
}
private void setupFeature(ImsFeature f, int slotId, int featureType,
IImsFeatureStatusCallback c) {
- f.setContext(this);
- f.setSlotId(slotId);
f.addImsFeatureStatusCallback(c);
+ f.initialize(this, slotId);
addImsFeature(slotId, featureType, f);
- // TODO: Remove once new onFeatureReady AIDL is merged in.
- f.onFeatureReady();
}
private void addImsFeature(int slotId, int featureType, ImsFeature f) {
@@ -221,38 +274,122 @@
}
}
+ private void notifyImsFeatureReady(int slotId, int featureType) {
+ synchronized (mFeaturesBySlot) {
+ // get ImsFeature associated with the slot/feature
+ SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
+ if (features == null) {
+ Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " +
+ "slot " + slotId);
+ return;
+ }
+ ImsFeature f = features.get(featureType);
+ if (f == null) {
+ Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type "
+ + featureType + " exists on slot " + slotId);
+ return;
+ }
+ f.onFeatureReady();
+ }
+ }
+
/**
- * @return An implementation of MMTelFeature that will be used by the system for MMTel
- * functionality. Must be able to handle emergency calls at any time as well.
- * @hide
+ * When called, provide the {@link ImsFeatureConfiguration} that this {@link ImsService}
+ * currently supports. This will trigger the framework to set up the {@link ImsFeature}s that
+ * correspond to the {@link ImsFeature}s configured here.
+ *
+ * Use {@link #onUpdateSupportedImsFeatures(ImsFeatureConfiguration)} to change the supported
+ * {@link ImsFeature}s.
+ *
+ * @return an {@link ImsFeatureConfiguration} containing Features this ImsService supports.
*/
- public @Nullable MMTelFeature onCreateEmergencyMMTelImsFeature(int slotId) {
+ public ImsFeatureConfiguration querySupportedImsFeatures() {
+ // Return empty for base implementation
+ return new ImsFeatureConfiguration();
+ }
+
+ /**
+ * Updates the framework with a new {@link ImsFeatureConfiguration} containing the updated
+ * features, that this {@link ImsService} supports. This may trigger the framework to add/remove
+ * new ImsFeatures, depending on the configuration.
+ */
+ public final void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c)
+ throws RemoteException {
+ if (mListener == null) {
+ throw new IllegalStateException("Framework is not ready");
+ }
+ mListener.onUpdateSupportedImsFeatures(c);
+ }
+
+ /**
+ * The ImsService has been bound and is ready for ImsFeature creation based on the Features that
+ * the ImsService has registered for with the framework, either in the manifest or via
+ * {@link #querySupportedImsFeatures()}.
+ *
+ * The ImsService should use this signal instead of onCreate/onBind or similar to perform
+ * feature initialization because the framework may bind to this service multiple times to
+ * query the ImsService's {@link ImsFeatureConfiguration} via
+ * {@link #querySupportedImsFeatures()}before creating features.
+ */
+ public void readyForFeatureCreation() {
+ }
+
+ /**
+ * The framework has enabled IMS for the slot specified, the ImsService should register for IMS
+ * and perform all appropriate initialization to bring up all ImsFeatures.
+ */
+ public void enableIms(int slotId) {
+ }
+
+ /**
+ * The framework has disabled IMS for the slot specified. The ImsService must deregister for IMS
+ * and set capability status to false for all ImsFeatures.
+ */
+ public void disableIms(int slotId) {
+ }
+
+ /**
+ * When called, the framework is requesting that a new {@link MmTelFeature} is created for the
+ * specified slot.
+ *
+ * @param slotId The slot ID that the MMTEL Feature is being created for.
+ * @return The newly created {@link MmTelFeature} associated with the slot or null if the
+ * feature is not supported.
+ */
+ public MmTelFeature createMmTelFeature(int slotId) {
return null;
}
/**
- * @return An implementation of MMTelFeature that will be used by the system for MMTel
- * functionality.
- * @hide
+ * When called, the framework is requesting that a new {@link RcsFeature} is created for the
+ * specified slot.
+ *
+ * @param slotId The slot ID that the RCS Feature is being created for.
+ * @return The newly created {@link RcsFeature} associated with the slot or null if the feature
+ * is not supported.
*/
- public @Nullable MMTelFeature onCreateMMTelImsFeature(int slotId) {
+ public RcsFeature createRcsFeature(int slotId) {
return null;
}
/**
- * @return An implementation of RcsFeature that will be used by the system for RCS.
- * @hide
+ * Return the {@link ImsConfigImplBase} implementation associated with the provided slot. This
+ * will be used by the platform to get/set specific IMS related configurations.
+ *
+ * @param slotId The slot that the IMS configuration is associated with.
+ * @return ImsConfig implementation that is associated with the specified slot.
*/
- public @Nullable RcsFeature onCreateRcsFeature(int slotId) {
- return null;
+ public ImsConfigImplBase getConfig(int slotId) {
+ return new ImsConfigImplBase();
}
/**
+ * Return the {@link ImsRegistrationImplBase} implementation associated with the provided slot.
+ *
* @param slotId The slot that is associated with the IMS Registration.
* @return the ImsRegistration implementation associated with the slot.
- * @hide
*/
public ImsRegistrationImplBase getRegistration(int slotId) {
return new ImsRegistrationImplBase();
}
-}
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/ims/ImsSsData.aidl b/telephony/java/android/telephony/ims/ImsSsData.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsSsData.aidl
rename to telephony/java/android/telephony/ims/ImsSsData.aidl
index 33f8306..eff3a6b 100644
--- a/telephony/java/com/android/ims/ImsSsData.aidl
+++ b/telephony/java/android/telephony/ims/ImsSsData.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.telephony.ims;
parcelable ImsSsData;
diff --git a/telephony/java/com/android/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
similarity index 89%
rename from telephony/java/com/android/ims/ImsSsData.java
rename to telephony/java/android/telephony/ims/ImsSsData.java
index 7336c13..1ddf199 100644
--- a/telephony/java/com/android/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 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.
@@ -11,21 +11,21 @@
* 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.
+ * limitations under the License
*/
-package com.android.ims;
+package android.telephony.ims;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.ArrayList;
-
/**
* Provided STK Call Control Suplementary Service information
*
* {@hide}
*/
-public class ImsSsData implements Parcelable {
+@SystemApi
+public final class ImsSsData implements Parcelable {
//ServiceType
public static final int SS_CFU = 0;
@@ -68,30 +68,38 @@
public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5;
// Refer to ServiceType
+ /** @hide */
public int serviceType;
// Refere to SSRequestType
+ /** @hide */
public int requestType;
// Refer to TeleserviceType
+ /** @hide */
public int teleserviceType;
// Service Class
+ /** @hide */
public int serviceClass;
// Error information
+ /** @hide */
public int result;
+ /** @hide */
public int[] ssInfo; /* Valid for all supplementary services.
This field will be empty for RequestType SS_INTERROGATION
and ServiceType SS_CF_*, SS_INCOMING_BARRING_DN,
SS_INCOMING_BARRING_ANONYMOUS.*/
+ /** @hide */
public ImsCallForwardInfo[] cfInfo; /* Valid only for supplementary services
ServiceType SS_CF_* and RequestType SS_INTERROGATION */
+ /** @hide */
public ImsSsInfo[] imsSsInfo; /* Valid only for ServiceType SS_INCOMING_BARRING_DN and
ServiceType SS_INCOMING_BARRING_ANONYMOUS */
public ImsSsData() {}
- public ImsSsData(Parcel in) {
+ private ImsSsData(Parcel in) {
readFromParcel(in);
}
@@ -133,20 +141,36 @@
return 0;
}
+ /**
+ * Old method, kept for compatibility. See {@link #isTypeCf()}
+ * @hide
+ */
public boolean isTypeCF() {
return (serviceType == SS_CFU || serviceType == SS_CF_BUSY ||
serviceType == SS_CF_NO_REPLY || serviceType == SS_CF_NOT_REACHABLE ||
serviceType == SS_CF_ALL || serviceType == SS_CF_ALL_CONDITIONAL);
}
+ public boolean isTypeCf() {
+ return isTypeCF();
+ }
+
public boolean isTypeUnConditional() {
return (serviceType == SS_CFU || serviceType == SS_CF_ALL);
}
+ /**
+ * Old method, kept for compatibility. See {@link #isTypeCf()}
+ * @hide
+ */
public boolean isTypeCW() {
return (serviceType == SS_WAIT);
}
+ public boolean isTypeCw() {
+ return isTypeCW();
+ }
+
public boolean isTypeClip() {
return (serviceType == SS_CLIP);
}
diff --git a/telephony/java/com/android/ims/ImsSsInfo.aidl b/telephony/java/android/telephony/ims/ImsSsInfo.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsSsInfo.aidl
rename to telephony/java/android/telephony/ims/ImsSsInfo.aidl
index 0ac598b..66d4950 100644
--- a/telephony/java/com/android/ims/ImsSsInfo.aidl
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.telephony.ims;
parcelable ImsSsInfo;
diff --git a/telephony/java/com/android/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
similarity index 81%
rename from telephony/java/com/android/ims/ImsSsInfo.java
rename to telephony/java/android/telephony/ims/ImsSsInfo.java
index 7acc3bf..1d1292f 100644
--- a/telephony/java/com/android/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -11,11 +11,12 @@
* 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.
+ * limitations under the License
*/
-package com.android.ims;
+package android.telephony.ims;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -24,7 +25,8 @@
*
* @hide
*/
-public class ImsSsInfo implements Parcelable {
+@SystemApi
+public final class ImsSsInfo implements Parcelable {
/**
* For the status of service registration or activation/deactivation.
*/
@@ -33,13 +35,15 @@
public static final int ENABLED = 1;
// 0: disabled, 1: enabled
+ /** @hide */
public int mStatus;
+ /** @hide */
public String mIcbNum;
public ImsSsInfo() {
}
- public ImsSsInfo(Parcel in) {
+ private ImsSsInfo(Parcel in) {
readFromParcel(in);
}
@@ -76,4 +80,12 @@
return new ImsSsInfo[size];
}
};
+
+ public int getStatus() {
+ return mStatus;
+ }
+
+ public String getIcbNum() {
+ return mIcbNum;
+ }
}
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
rename to telephony/java/android/telephony/ims/ImsStreamMediaProfile.aidl
index d648a35..ee321ae 100644
--- a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package com.android.ims;
+package android.telephony.ims;
parcelable ImsStreamMediaProfile;
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
similarity index 88%
rename from telephony/java/com/android/ims/ImsStreamMediaProfile.java
rename to telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index cfe37b5..243352b 100644
--- a/telephony/java/com/android/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 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.
@@ -11,11 +11,12 @@
* 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.
+ * limitations under the License
*/
-package com.android.ims;
+package android.telephony.ims;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -25,7 +26,8 @@
*
* @hide
*/
-public class ImsStreamMediaProfile implements Parcelable {
+@SystemApi
+public final class ImsStreamMediaProfile implements Parcelable {
private static final String TAG = "ImsStreamMediaProfile";
/**
@@ -79,18 +81,25 @@
public static final int RTT_MODE_FULL = 1;
// Audio related information
+ /** @hide */
public int mAudioQuality;
+ /** @hide */
public int mAudioDirection;
// Video related information
+ /** @hide */
public int mVideoQuality;
+ /** @hide */
public int mVideoDirection;
// Rtt related information
+ /** @hide */
public int mRttMode;
+ /** @hide */
public ImsStreamMediaProfile(Parcel in) {
readFromParcel(in);
}
+ /** @hide */
public ImsStreamMediaProfile() {
mAudioQuality = AUDIO_QUALITY_NONE;
mAudioDirection = DIRECTION_SEND_RECEIVE;
@@ -99,6 +108,7 @@
mRttMode = RTT_MODE_DISABLED;
}
+ /** @hide */
public ImsStreamMediaProfile(int audioQuality, int audioDirection,
int videoQuality, int videoDirection) {
mAudioQuality = audioQuality;
@@ -107,6 +117,7 @@
mVideoDirection = videoDirection;
}
+ /** @hide */
public ImsStreamMediaProfile(int rttMode) {
mRttMode = rttMode;
}
@@ -178,4 +189,23 @@
mRttMode = rttMode;
}
+ public int getAudioQuality() {
+ return mAudioQuality;
+ }
+
+ public int getAudioDirection() {
+ return mAudioDirection;
+ }
+
+ public int getVideoQuality() {
+ return mVideoQuality;
+ }
+
+ public int getVideoDirection() {
+ return mVideoDirection;
+ }
+
+ public int getRttMode() {
+ return mRttMode;
+ }
}
diff --git a/telephony/java/com/android/ims/ImsSuppServiceNotification.aidl b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.aidl
similarity index 95%
rename from telephony/java/com/android/ims/ImsSuppServiceNotification.aidl
rename to telephony/java/android/telephony/ims/ImsSuppServiceNotification.aidl
index 6b4479f..0552780 100644
--- a/telephony/java/com/android/ims/ImsSuppServiceNotification.aidl
+++ b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.aidl
@@ -15,6 +15,6 @@
*/
-package com.android.ims;
+package android.telephony.ims;
parcelable ImsSuppServiceNotification;
diff --git a/telephony/java/com/android/ims/ImsSuppServiceNotification.java b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
similarity index 76%
rename from telephony/java/com/android/ims/ImsSuppServiceNotification.java
rename to telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
index faf7499..efaade8 100644
--- a/telephony/java/com/android/ims/ImsSuppServiceNotification.java
+++ b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
@@ -1,5 +1,5 @@
/*
- * 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.
@@ -11,12 +11,13 @@
* 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.
+ * limitations under the License
*/
-package com.android.ims;
+package android.telephony.ims;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -28,27 +29,42 @@
*
* @hide
*/
-public class ImsSuppServiceNotification implements Parcelable {
+@SystemApi
+public final class ImsSuppServiceNotification implements Parcelable {
private static final String TAG = "ImsSuppServiceNotification";
/** Type of notification: 0 = MO; 1 = MT */
- public int notificationType;
+ public final int notificationType;
/** TS 27.007 7.17 "code1" or "code2" */
- public int code;
+ public final int code;
/** TS 27.007 7.17 "index" - Not used currently*/
- public int index;
+ public final int index;
/** TS 27.007 7.17 "type" (MT only) - Not used currently */
- public int type;
+ public final int type;
/** TS 27.007 7.17 "number" (MT only) */
- public String number;
+ public final String number;
/** List of forwarded numbers, if any */
- public String[] history;
+ public final String[] history;
- public ImsSuppServiceNotification() {
+
+ public ImsSuppServiceNotification(int notificationType, int code, int index, int type,
+ String number, String[] history) {
+ this.notificationType = notificationType;
+ this.code = code;
+ this.index = index;
+ this.type = type;
+ this.number = number;
+ this.history = history;
}
+ /** @hide */
public ImsSuppServiceNotification(Parcel in) {
- readFromParcel(in);
+ notificationType = in.readInt();
+ code = in.readInt();
+ index = in.readInt();
+ type = in.readInt();
+ number = in.readString();
+ history = in.createStringArray();
}
@Override
@@ -77,15 +93,6 @@
out.writeStringArray(history);
}
- private void readFromParcel(Parcel in) {
- notificationType = in.readInt();
- code = in.readInt();
- index = in.readInt();
- type = in.readInt();
- number = in.readString();
- history = in.createStringArray();
- }
-
public static final Creator<ImsSuppServiceNotification> CREATOR =
new Creator<ImsSuppServiceNotification>() {
@Override
diff --git a/telephony/java/android/telephony/ims/ImsUtListener.java b/telephony/java/android/telephony/ims/ImsUtListener.java
new file mode 100644
index 0000000..d50a0f7
--- /dev/null
+++ b/telephony/java/android/telephony/ims/ImsUtListener.java
@@ -0,0 +1,108 @@
+/*
+ * 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.telephony.ims;
+
+import android.annotation.SystemApi;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.ims.internal.IImsUtListener;
+
+/**
+ * Base implementation of the IMS UT listener interface, which implements stubs.
+ * Override these methods to implement functionality.
+ * @hide
+ */
+// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+// will break other implementations of ImsUt maintained by other ImsServices.
+@SystemApi
+public class ImsUtListener {
+ private IImsUtListener mServiceInterface;
+ private static final String LOG_TAG = "ImsUtListener";
+
+ public void onUtConfigurationUpdated(int id) {
+ try {
+ mServiceInterface.utConfigurationUpdated(null, id);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "utConfigurationUpdated: remote exception");
+ }
+ }
+
+ public void onUtConfigurationUpdateFailed(int id, ImsReasonInfo error) {
+ try {
+ mServiceInterface.utConfigurationUpdateFailed(null, id, error);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "utConfigurationUpdateFailed: remote exception");
+ }
+ }
+
+ public void onUtConfigurationQueried(int id, Bundle ssInfo) {
+ try {
+ mServiceInterface.utConfigurationQueried(null, id, ssInfo);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "utConfigurationQueried: remote exception");
+ }
+ }
+
+ public void onUtConfigurationQueryFailed(int id, ImsReasonInfo error) {
+ try {
+ mServiceInterface.utConfigurationQueryFailed(null, id, error);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "utConfigurationQueryFailed: remote exception");
+ }
+ }
+
+ public void onUtConfigurationCallBarringQueried(int id, ImsSsInfo[] cbInfo) {
+ try {
+ mServiceInterface.utConfigurationCallBarringQueried(null, id, cbInfo);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "utConfigurationCallBarringQueried: remote exception");
+ }
+ }
+
+ public void onUtConfigurationCallForwardQueried(int id, ImsCallForwardInfo[] cfInfo) {
+ try {
+ mServiceInterface.utConfigurationCallForwardQueried(null, id, cfInfo);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "utConfigurationCallForwardQueried: remote exception");
+ }
+ }
+
+ public void onUtConfigurationCallWaitingQueried(int id, ImsSsInfo[] cwInfo) {
+ try {
+ mServiceInterface.utConfigurationCallWaitingQueried(null, id, cwInfo);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "utConfigurationCallWaitingQueried: remote exception");
+ }
+ }
+
+ public void onSupplementaryServiceIndication(ImsSsData ssData) {
+ try {
+ mServiceInterface.onSupplementaryServiceIndication(ssData);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "onSupplementaryServiceIndication: remote exception");
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public ImsUtListener(IImsUtListener serviceInterface) {
+ mServiceInterface = serviceInterface;
+ }
+}
diff --git a/telephony/java/com/android/ims/internal/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
similarity index 97%
rename from telephony/java/com/android/ims/internal/ImsVideoCallProvider.java
rename to telephony/java/android/telephony/ims/ImsVideoCallProvider.java
index 432dc39..b4f60b9 100644
--- a/telephony/java/com/android/ims/internal/ImsVideoCallProvider.java
+++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 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.
@@ -14,8 +14,9 @@
* limitations under the License
*/
-package com.android.ims.internal;
+package android.telephony.ims;
+import android.annotation.SystemApi;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
@@ -26,11 +27,14 @@
import android.telecom.VideoProfile.CameraCapabilities;
import android.view.Surface;
+import com.android.ims.internal.IImsVideoCallCallback;
+import com.android.ims.internal.IImsVideoCallProvider;
import com.android.internal.os.SomeArgs;
/**
* @hide
*/
+@SystemApi
public abstract class ImsVideoCallProvider {
private static final int MSG_SET_CALLBACK = 1;
private static final int MSG_SET_CAMERA = 2;
@@ -173,6 +177,7 @@
/**
* Returns binder object which can be used across IPC methods.
+ * @hide
*/
public final IImsVideoCallProvider getInterface() {
return mBinder;
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
similarity index 94%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
index 2fb6744..f25b4b1 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsConferenceState;
+import android.telephony.ims.ImsStreamMediaProfile;
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsConferenceState;
import com.android.ims.internal.IImsCallSession;
-import com.android.ims.ImsSuppServiceNotification;
+import android.telephony.ims.ImsSuppServiceNotification;
/**
* A listener type for receiving notification on IMS call session events.
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl
similarity index 95%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl
index fd2eb24..c755703 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
/**
* See ImsFeature#CapabilityCallback for more information.
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
similarity index 91%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
index 3d424a3..4433c1c 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
@@ -15,9 +15,9 @@
*/
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
-import android.telephony.ims.internal.aidl.IImsConfigCallback;
+import android.telephony.ims.aidl.IImsConfigCallback;
import com.android.ims.ImsConfigListener;
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl
similarity index 94%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl
index 52efd23..2b3f1ca 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsConfigCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl
@@ -15,7 +15,7 @@
*/
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
/**
* Provides callback interface for ImsConfig when a value has changed.
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
similarity index 66%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
index e226ada..b9a6b3c 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
import android.os.Message;
-import android.telephony.ims.internal.aidl.IImsMmTelListener;
-import android.telephony.ims.internal.aidl.IImsCapabilityCallback;
-import android.telephony.ims.internal.aidl.IImsCallSessionListener;
-import android.telephony.ims.internal.feature.CapabilityChangeRequest;
+import android.telephony.ims.aidl.IImsMmTelListener;
+import android.telephony.ims.aidl.IImsSmsListener;
+import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.feature.CapabilityChangeRequest;
-import com.android.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallProfile;
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsEcbm;
import com.android.ims.internal.IImsMultiEndpoint;
@@ -30,14 +30,15 @@
import com.android.ims.internal.IImsUt;
/**
- * See SmsImplBase for more information.
+ * See MmTelFeature for more information.
* {@hide}
*/
interface IImsMmTelFeature {
void setListener(IImsMmTelListener l);
int getFeatureState();
ImsCallProfile createCallProfile(int callSessionType, int callType);
- IImsCallSession createCallSession(in ImsCallProfile profile, IImsCallSessionListener listener);
+ IImsCallSession createCallSession(in ImsCallProfile profile);
+ int shouldProcessCall(in String[] uris);
IImsUt getUtInterface();
IImsEcbm getEcbmInterface();
void setUiTtyMode(int uiTtyMode, in Message onCompleteMessage);
@@ -49,4 +50,12 @@
IImsCapabilityCallback c);
oneway void queryCapabilityConfiguration(int capability, int radioTech,
IImsCapabilityCallback c);
+ // SMS APIs
+ void setSmsListener(IImsSmsListener l);
+ oneway void sendSms(in int token, int messageRef, String format, String smsc, boolean retry,
+ in byte[] pdu);
+ oneway void acknowledgeSms(int token, int messageRef, int result);
+ oneway void acknowledgeSmsReport(int token, int messageRef, int result);
+ String getSmsFormat();
+ oneway void onSmsReady();
}
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl
similarity index 86%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl
index 43f5098..904e7ca 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
+
+import android.os.Bundle;
import com.android.ims.internal.IImsCallSession;
@@ -23,6 +25,6 @@
* {@hide}
*/
oneway interface IImsMmTelListener {
- void onIncomingCall(IImsCallSession c);
+ void onIncomingCall(IImsCallSession c, in Bundle extras);
void onVoiceMessageCountUpdate(int count);
}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
similarity index 94%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
index f6005b6..691cfba 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
/**
* See RcsFeature for more information.
diff --git a/telephony/java/com/android/ims/internal/IImsRegistration.aidl b/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
similarity index 90%
rename from telephony/java/com/android/ims/internal/IImsRegistration.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
index 6de264e..4ae0a75 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistration.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
@@ -15,9 +15,9 @@
*/
-package com.android.ims.internal;
+package android.telephony.ims.aidl;
-import com.android.ims.internal.IImsRegistrationCallback;
+import android.telephony.ims.aidl.IImsRegistrationCallback;
/**
* See ImsRegistration for more information.
diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl
similarity index 87%
rename from telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl
index 5f21167..4f37caa 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistrationCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl
@@ -15,12 +15,12 @@
*/
-package com.android.ims.internal;
+package android.telephony.ims.aidl;
import android.net.Uri;
-import android.telephony.ims.internal.stub.ImsFeatureConfiguration;
+import android.telephony.ims.stub.ImsFeatureConfiguration;
-import com.android.ims.ImsReasonInfo;
+import android.telephony.ims.ImsReasonInfo;
/**
* See ImsRegistrationImplBase.Callback for more information.
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
similarity index 77%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
index 82a8525..86f8606 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
-import android.telephony.ims.internal.aidl.IImsMmTelFeature;
-import android.telephony.ims.internal.aidl.IImsRcsFeature;
-import android.telephony.ims.internal.aidl.IImsConfig;
-import android.telephony.ims.internal.aidl.IImsServiceControllerListener;
-import android.telephony.ims.internal.stub.ImsFeatureConfiguration;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.IImsServiceControllerListener;
+import android.telephony.ims.stub.ImsFeatureConfiguration;
import com.android.ims.internal.IImsFeatureStatusCallback;
-import com.android.ims.internal.IImsRegistration;
/**
* See ImsService and MmTelFeature for more information.
@@ -41,4 +41,6 @@
void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c);
IImsConfig getConfig(int slotId);
IImsRegistration getRegistration(int slotId);
+ oneway void enableIms(int slotId);
+ oneway void disableIms(int slotId);
}
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl
similarity index 87%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl
index 01cca2db..54f6120 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package android.telephony.ims.aidl;
-import android.telephony.ims.internal.stub.ImsFeatureConfiguration;
+import android.telephony.ims.stub.ImsFeatureConfiguration;
/**
* See ImsService#Listener for more information.
diff --git a/telephony/java/com/android/ims/internal/IImsSmsListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
similarity index 92%
rename from telephony/java/com/android/ims/internal/IImsSmsListener.aidl
rename to telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
index 5a4b7e4..606df15 100644
--- a/telephony/java/com/android/ims/internal/IImsSmsListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-package com.android.ims.internal;
+package android.telephony.ims.aidl;
/**
* See SmsImplBase for more information.
* {@hide}
*/
-interface IImsSmsListener {
+oneway interface IImsSmsListener {
void onSendSmsResult(int token, int messageRef, int status, int reason);
void onSmsStatusReportReceived(int token, int messageRef, in String format,
in byte[] pdu);
diff --git a/telephony/java/android/telephony/ims/compat/ImsService.java b/telephony/java/android/telephony/ims/compat/ImsService.java
new file mode 100644
index 0000000..cf1efb3
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/ImsService.java
@@ -0,0 +1,237 @@
+/*
+ * 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.telephony.ims.compat;
+
+import android.annotation.Nullable;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.CarrierConfigManager;
+import android.telephony.ims.compat.feature.ImsFeature;
+import android.telephony.ims.compat.feature.MMTelFeature;
+import android.telephony.ims.compat.feature.RcsFeature;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.ims.internal.IImsFeatureStatusCallback;
+import com.android.ims.internal.IImsMMTelFeature;
+import com.android.ims.internal.IImsRcsFeature;
+import com.android.ims.internal.IImsServiceController;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
+ * ImsService must register the service in their AndroidManifest to be detected by the framework.
+ * First, the application must declare that they use the "android.permission.BIND_IMS_SERVICE"
+ * permission. Then, the ImsService definition in the manifest must follow the following format:
+ *
+ * ...
+ * <service android:name=".EgImsService"
+ * android:permission="android.permission.BIND_IMS_SERVICE" >
+ * <!-- Apps must declare which features they support as metadata. The different categories are
+ * defined below. In this example, the RCS_FEATURE feature is supported. -->
+ * <meta-data android:name="android.telephony.ims.RCS_FEATURE" android:value="true" />
+ * <intent-filter>
+ * <action android:name="android.telephony.ims.compat.ImsService" />
+ * </intent-filter>
+ * </service>
+ * ...
+ *
+ * The telephony framework will then bind to the ImsService you have defined in your manifest
+ * if you are either:
+ * 1) Defined as the default ImsService for the device in the device overlay using
+ * "config_ims_package".
+ * 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using
+ * {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}.
+ *
+ * The features that are currently supported in an ImsService are:
+ * - RCS_FEATURE: This ImsService implements the RcsFeature class.
+ * - MMTEL_FEATURE: This ImsService implements the MMTelFeature class.
+ * - EMERGENCY_MMTEL_FEATURE: This ImsService implements the MMTelFeature class and will be
+ * available to place emergency calls at all times. This MUST be implemented by the default
+ * ImsService provided in the device overlay.
+ * @hide
+ */
+public class ImsService extends Service {
+
+ private static final String LOG_TAG = "ImsService(Compat)";
+
+ /**
+ * The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService.
+ * @hide
+ */
+ public static final String SERVICE_INTERFACE = "android.telephony.ims.compat.ImsService";
+
+ // A map of slot Id -> map of features (indexed by ImsFeature feature id) corresponding to that
+ // slot.
+ // We keep track of this to facilitate cleanup of the IImsFeatureStatusCallback and
+ // call ImsFeature#onFeatureRemoved.
+ private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
+
+ /**
+ * @hide
+ */
+ protected final IBinder mImsServiceController = new IImsServiceController.Stub() {
+
+ @Override
+ public IImsMMTelFeature createEmergencyMMTelFeature(int slotId,
+ IImsFeatureStatusCallback c) {
+ return createEmergencyMMTelFeatureInternal(slotId, c);
+ }
+
+ @Override
+ public IImsMMTelFeature createMMTelFeature(int slotId, IImsFeatureStatusCallback c) {
+ return createMMTelFeatureInternal(slotId, c);
+ }
+
+ @Override
+ public IImsRcsFeature createRcsFeature(int slotId, IImsFeatureStatusCallback c) {
+ return createRcsFeatureInternal(slotId, c);
+ }
+
+ @Override
+ public void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
+ throws RemoteException {
+ ImsService.this.removeImsFeature(slotId, featureType, c);
+ }
+ };
+
+ /**
+ * @hide
+ */
+ @Override
+ public IBinder onBind(Intent intent) {
+ if(SERVICE_INTERFACE.equals(intent.getAction())) {
+ Log.i(LOG_TAG, "ImsService(Compat) Bound.");
+ return mImsServiceController;
+ }
+ return null;
+ }
+
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public SparseArray<ImsFeature> getFeatures(int slotId) {
+ return mFeaturesBySlot.get(slotId);
+ }
+
+ private IImsMMTelFeature createEmergencyMMTelFeatureInternal(int slotId,
+ IImsFeatureStatusCallback c) {
+ MMTelFeature f = onCreateEmergencyMMTelImsFeature(slotId);
+ if (f != null) {
+ setupFeature(f, slotId, ImsFeature.EMERGENCY_MMTEL, c);
+ return f.getBinder();
+ } else {
+ return null;
+ }
+ }
+
+ private IImsMMTelFeature createMMTelFeatureInternal(int slotId,
+ IImsFeatureStatusCallback c) {
+ MMTelFeature f = onCreateMMTelImsFeature(slotId);
+ if (f != null) {
+ setupFeature(f, slotId, ImsFeature.MMTEL, c);
+ return f.getBinder();
+ } else {
+ return null;
+ }
+ }
+
+ private IImsRcsFeature createRcsFeatureInternal(int slotId,
+ IImsFeatureStatusCallback c) {
+ RcsFeature f = onCreateRcsFeature(slotId);
+ if (f != null) {
+ setupFeature(f, slotId, ImsFeature.RCS, c);
+ return f.getBinder();
+ } else {
+ return null;
+ }
+ }
+
+ private void setupFeature(ImsFeature f, int slotId, int featureType,
+ IImsFeatureStatusCallback c) {
+ f.setContext(this);
+ f.setSlotId(slotId);
+ f.addImsFeatureStatusCallback(c);
+ addImsFeature(slotId, featureType, f);
+ // TODO: Remove once new onFeatureReady AIDL is merged in.
+ f.onFeatureReady();
+ }
+
+ private void addImsFeature(int slotId, int featureType, ImsFeature f) {
+ synchronized (mFeaturesBySlot) {
+ // Get SparseArray for Features, by querying slot Id
+ SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
+ if (features == null) {
+ // Populate new SparseArray of features if it doesn't exist for this slot yet.
+ features = new SparseArray<>();
+ mFeaturesBySlot.put(slotId, features);
+ }
+ features.put(featureType, f);
+ }
+ }
+
+ private void removeImsFeature(int slotId, int featureType,
+ IImsFeatureStatusCallback c) {
+ synchronized (mFeaturesBySlot) {
+ // get ImsFeature associated with the slot/feature
+ SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
+ if (features == null) {
+ Log.w(LOG_TAG, "Can not remove ImsFeature. No ImsFeatures exist on slot "
+ + slotId);
+ return;
+ }
+ ImsFeature f = features.get(featureType);
+ if (f == null) {
+ Log.w(LOG_TAG, "Can not remove ImsFeature. No feature with type "
+ + featureType + " exists on slot " + slotId);
+ return;
+ }
+ f.removeImsFeatureStatusCallback(c);
+ f.onFeatureRemoved();
+ features.remove(featureType);
+ }
+ }
+
+ /**
+ * @return An implementation of MMTelFeature that will be used by the system for MMTel
+ * functionality. Must be able to handle emergency calls at any time as well.
+ * @hide
+ */
+ public @Nullable MMTelFeature onCreateEmergencyMMTelImsFeature(int slotId) {
+ return null;
+ }
+
+ /**
+ * @return An implementation of MMTelFeature that will be used by the system for MMTel
+ * functionality.
+ * @hide
+ */
+ public @Nullable MMTelFeature onCreateMMTelImsFeature(int slotId) {
+ return null;
+ }
+
+ /**
+ * @return An implementation of RcsFeature that will be used by the system for RCS.
+ * @hide
+ */
+ public @Nullable RcsFeature onCreateRcsFeature(int slotId) {
+ return null;
+ }
+}
diff --git a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
new file mode 100644
index 0000000..0a12cae
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
@@ -0,0 +1,202 @@
+/*
+ * 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.telephony.ims.compat.feature;
+
+import android.annotation.IntDef;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.telephony.SubscriptionManager;
+import android.util.Log;
+
+import com.android.ims.internal.IImsFeatureStatusCallback;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * Base class for all IMS features that are supported by the framework.
+ * @hide
+ */
+public abstract class ImsFeature {
+
+ private static final String LOG_TAG = "ImsFeature";
+
+ /**
+ * Action to broadcast when ImsService is up.
+ * Internal use only.
+ * Only defined here separately compatibility purposes with the old ImsService.
+ * @hide
+ */
+ public static final String ACTION_IMS_SERVICE_UP =
+ "com.android.ims.IMS_SERVICE_UP";
+
+ /**
+ * Action to broadcast when ImsService is down.
+ * Internal use only.
+ * Only defined here separately for compatibility purposes with the old ImsService.
+ * @hide
+ */
+ public static final String ACTION_IMS_SERVICE_DOWN =
+ "com.android.ims.IMS_SERVICE_DOWN";
+
+ /**
+ * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
+ * A long value; the phone ID corresponding to the IMS service coming up or down.
+ * Only defined here separately for compatibility purposes with the old ImsService.
+ * @hide
+ */
+ public static final String EXTRA_PHONE_ID = "android:phone_id";
+
+ // Invalid feature value
+ public static final int INVALID = -1;
+ // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
+ // defined values in ImsServiceClass for compatibility purposes.
+ public static final int EMERGENCY_MMTEL = 0;
+ public static final int MMTEL = 1;
+ public static final int RCS = 2;
+ // Total number of features defined
+ public static final int MAX = 3;
+
+ // Integer values defining the state of the ImsFeature at any time.
+ @IntDef(flag = true,
+ value = {
+ STATE_NOT_AVAILABLE,
+ STATE_INITIALIZING,
+ STATE_READY,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ImsState {}
+ public static final int STATE_NOT_AVAILABLE = 0;
+ public static final int STATE_INITIALIZING = 1;
+ public static final int STATE_READY = 2;
+
+ private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap(
+ new WeakHashMap<IImsFeatureStatusCallback, Boolean>());
+ private @ImsState int mState = STATE_NOT_AVAILABLE;
+ private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+ protected Context mContext;
+
+ public void setContext(Context context) {
+ mContext = context;
+ }
+
+ public void setSlotId(int slotId) {
+ mSlotId = slotId;
+ }
+
+ public int getFeatureState() {
+ return mState;
+ }
+
+ protected final void setFeatureState(@ImsState int state) {
+ if (mState != state) {
+ mState = state;
+ notifyFeatureState(state);
+ }
+ }
+
+ public void addImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
+ if (c == null) {
+ return;
+ }
+ try {
+ // If we have just connected, send queued status.
+ c.notifyImsFeatureStatus(mState);
+ // Add the callback if the callback completes successfully without a RemoteException.
+ synchronized (mStatusCallbacks) {
+ mStatusCallbacks.add(c);
+ }
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
+ }
+ }
+
+ public void removeImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
+ if (c == null) {
+ return;
+ }
+ synchronized (mStatusCallbacks) {
+ mStatusCallbacks.remove(c);
+ }
+ }
+
+ /**
+ * Internal method called by ImsFeature when setFeatureState has changed.
+ * @param state
+ */
+ private void notifyFeatureState(@ImsState int state) {
+ synchronized (mStatusCallbacks) {
+ for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator();
+ iter.hasNext(); ) {
+ IImsFeatureStatusCallback callback = iter.next();
+ try {
+ Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
+ callback.notifyImsFeatureStatus(state);
+ } catch (RemoteException e) {
+ // remove if the callback is no longer alive.
+ iter.remove();
+ Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
+ }
+ }
+ }
+ sendImsServiceIntent(state);
+ }
+
+ /**
+ * Provide backwards compatibility using deprecated service UP/DOWN intents.
+ */
+ private void sendImsServiceIntent(@ImsState int state) {
+ if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ return;
+ }
+ Intent intent;
+ switch (state) {
+ case ImsFeature.STATE_NOT_AVAILABLE:
+ case ImsFeature.STATE_INITIALIZING:
+ intent = new Intent(ACTION_IMS_SERVICE_DOWN);
+ break;
+ case ImsFeature.STATE_READY:
+ intent = new Intent(ACTION_IMS_SERVICE_UP);
+ break;
+ default:
+ intent = new Intent(ACTION_IMS_SERVICE_DOWN);
+ }
+ intent.putExtra(EXTRA_PHONE_ID, mSlotId);
+ mContext.sendBroadcast(intent);
+ }
+
+ /**
+ * Called when the feature is ready to use.
+ */
+ public abstract void onFeatureReady();
+
+ /**
+ * Called when the feature is being removed and must be cleaned up.
+ */
+ public abstract void onFeatureRemoved();
+
+ /**
+ * @return Binder instance
+ */
+ public abstract IInterface getBinder();
+}
diff --git a/telephony/java/android/telephony/ims/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
similarity index 77%
rename from telephony/java/android/telephony/ims/feature/MMTelFeature.java
rename to telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
index 93c316f..d3d17f4 100644
--- a/telephony/java/android/telephony/ims/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 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.
@@ -14,14 +14,13 @@
* limitations under the License
*/
-package android.telephony.ims.feature;
+package android.telephony.ims.compat.feature;
import android.app.PendingIntent;
import android.os.Message;
import android.os.RemoteException;
-import android.telephony.ims.internal.stub.SmsImplBase;
-import com.android.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallProfile;
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsCallSessionListener;
import com.android.ims.internal.IImsConfig;
@@ -29,9 +28,12 @@
import com.android.ims.internal.IImsMMTelFeature;
import com.android.ims.internal.IImsMultiEndpoint;
import com.android.ims.internal.IImsRegistrationListener;
-import com.android.ims.internal.IImsSmsListener;
import com.android.ims.internal.IImsUt;
-import com.android.ims.internal.ImsCallSession;
+import android.telephony.ims.ImsCallSession;
+import android.telephony.ims.compat.stub.ImsCallSessionImplBase;
+import android.telephony.ims.stub.ImsEcbmImplBase;
+import android.telephony.ims.stub.ImsMultiEndpointImplBase;
+import android.telephony.ims.stub.ImsUtImplBase;
/**
* Base implementation for MMTel.
@@ -110,10 +112,10 @@
}
@Override
- public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile,
- IImsCallSessionListener listener) throws RemoteException {
+ public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile)
+ throws RemoteException {
synchronized (mLock) {
- return MMTelFeature.this.createCallSession(sessionId, profile, listener);
+ return MMTelFeature.this.createCallSession(sessionId, profile, null);
}
}
@@ -128,7 +130,8 @@
@Override
public IImsUt getUtInterface() throws RemoteException {
synchronized (mLock) {
- return MMTelFeature.this.getUtInterface();
+ ImsUtImplBase implBase = MMTelFeature.this.getUtInterface();
+ return implBase != null ? implBase.getInterface() : null;
}
}
@@ -156,7 +159,8 @@
@Override
public IImsEcbm getEcbmInterface() throws RemoteException {
synchronized (mLock) {
- return MMTelFeature.this.getEcbmInterface();
+ ImsEcbmImplBase implBase = MMTelFeature.this.getEcbmInterface();
+ return implBase != null ? implBase.getImsEcbm() : null;
}
}
@@ -170,50 +174,8 @@
@Override
public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
synchronized (mLock) {
- return MMTelFeature.this.getMultiEndpointInterface();
- }
- }
-
- @Override
- public void setSmsListener(IImsSmsListener l) throws RemoteException {
- synchronized (mLock) {
- MMTelFeature.this.setSmsListener(l);
- }
- }
-
- @Override
- public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
- byte[] pdu) {
- synchronized (mLock) {
- MMTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
- }
- }
-
- @Override
- public void acknowledgeSms(int token, int messageRef, int result) {
- synchronized (mLock) {
- MMTelFeature.this.acknowledgeSms(token, messageRef, result);
- }
- }
-
- @Override
- public void acknowledgeSmsReport(int token, int messageRef, int result) {
- synchronized (mLock) {
- MMTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
- }
- }
-
- @Override
- public String getSmsFormat() {
- synchronized (mLock) {
- return MMTelFeature.this.getSmsFormat();
- }
- }
-
- @Override
- public void onSmsReady() {
- synchronized (mLock) {
- MMTelFeature.this.onSmsReady();
+ ImsMultiEndpointImplBase implBase = MMTelFeature.this.getMultiEndpointInterface();
+ return implBase != null ? implBase.getIImsMultiEndpoint() : null;
}
}
};
@@ -326,7 +288,6 @@
*
* @param sessionId a session id which is obtained from {@link #startSession}
* @param profile a call profile to make the call
- * @param listener An implementation of IImsCallSessionListener.
*/
public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile,
IImsCallSessionListener listener) {
@@ -346,7 +307,7 @@
/**
* @return The Ut interface for the supplementary service configuration.
*/
- public IImsUt getUtInterface() {
+ public ImsUtImplBase getUtInterface() {
return null;
}
@@ -372,7 +333,7 @@
/**
* @return The Emergency call-back mode interface for emergency VoLTE calls that support it.
*/
- public IImsEcbm getEcbmInterface() {
+ public ImsEcbmImplBase getEcbmInterface() {
return null;
}
@@ -387,47 +348,10 @@
/**
* @return MultiEndpoint interface for DEP notifications
*/
- public IImsMultiEndpoint getMultiEndpointInterface() {
+ public ImsMultiEndpointImplBase getMultiEndpointInterface() {
return null;
}
- private void setSmsListener(IImsSmsListener listener) {
- getSmsImplementation().registerSmsListener(listener);
- }
-
- private void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
- byte[] pdu) {
- getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu);
- }
-
- private void acknowledgeSms(int token, int messageRef,
- @SmsImplBase.DeliverStatusResult int result) {
- getSmsImplementation().acknowledgeSms(token, messageRef, result);
- }
-
- private void acknowledgeSmsReport(int token, int messageRef,
- @SmsImplBase.StatusReportResult int result) {
- getSmsImplementation().acknowledgeSmsReport(token, messageRef, result);
- }
-
- private void onSmsReady() {
- getSmsImplementation().onReady();
- }
-
- /**
- * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default
- * non-functional implementation is returned.
- *
- * @return an instance of {@link SmsImplBase} which should be implemented by the IMS Provider.
- */
- protected SmsImplBase getSmsImplementation() {
- return new SmsImplBase();
- }
-
- public String getSmsFormat() {
- return getSmsImplementation().getSmsFormat();
- }
-
@Override
public void onFeatureReady() {
diff --git a/telephony/java/android/telephony/ims/internal/feature/RcsFeature.java b/telephony/java/android/telephony/ims/compat/feature/RcsFeature.java
similarity index 76%
rename from telephony/java/android/telephony/ims/internal/feature/RcsFeature.java
rename to telephony/java/android/telephony/ims/compat/feature/RcsFeature.java
index 8d1bd9d..228b330 100644
--- a/telephony/java/android/telephony/ims/internal/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/RcsFeature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 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.
@@ -14,9 +14,10 @@
* limitations under the License
*/
-package android.telephony.ims.internal.feature;
+package android.telephony.ims.compat.feature;
-import android.telephony.ims.internal.aidl.IImsRcsFeature;
+
+import com.android.ims.internal.IImsRcsFeature;
/**
* Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend
@@ -36,9 +37,8 @@
}
@Override
- public void changeEnabledCapabilities(CapabilityChangeRequest request,
- CapabilityCallbackProxy c) {
- // Do nothing for base implementation.
+ public void onFeatureReady() {
+
}
@Override
@@ -46,12 +46,6 @@
}
- /**{@inheritDoc}*/
- @Override
- public void onFeatureReady() {
-
- }
-
@Override
public final IImsRcsFeature getBinder() {
return mImsRcsBinder;
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
new file mode 100644
index 0000000..00cb1e2
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
@@ -0,0 +1,585 @@
+/*
+ * 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.telephony.ims.compat.stub;
+
+import android.os.Message;
+import android.os.RemoteException;
+
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsConferenceState;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsStreamMediaProfile;
+import android.telephony.ims.ImsSuppServiceNotification;
+import android.telephony.ims.aidl.IImsCallSessionListener;
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsVideoCallProvider;
+
+import android.telephony.ims.ImsCallSession;
+
+/**
+ * Compat implementation of ImsCallSessionImplBase for older implementations.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsCallSession maintained by other ImsServices.
+ *
+ * @hide
+ */
+
+public class ImsCallSessionImplBase extends IImsCallSession.Stub {
+
+ @Override
+ // convert to old implementation of listener
+ public final void setListener(IImsCallSessionListener listener)
+ throws RemoteException {
+ setListener(new ImsCallSessionListenerConverter(listener));
+ }
+
+ /**
+ * Sets the listener to listen to the session events. An {@link ImsCallSession}
+ * can only hold one listener at a time. Subsequent calls to this method
+ * override the previous listener.
+ *
+ * @param listener to listen to the session events of this object
+ */
+ public void setListener(com.android.ims.internal.IImsCallSessionListener listener) {
+
+ }
+
+ /**
+ * Closes the object. This {@link ImsCallSessionImplBase} is not usable after being closed.
+ */
+ @Override
+ public void close() {
+
+ }
+
+ /**
+ * @return A String containing the unique call ID of this {@link ImsCallSessionImplBase}.
+ */
+ @Override
+ public String getCallId() {
+ return null;
+ }
+
+ /**
+ * @return The {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is associated
+ * with.
+ */
+ @Override
+ public ImsCallProfile getCallProfile() {
+ return null;
+ }
+
+ /**
+ * @return The local {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is
+ * associated with.
+ */
+ @Override
+ public ImsCallProfile getLocalCallProfile() {
+ return null;
+ }
+
+ /**
+ * @return The remote {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is
+ * associated with.
+ */
+ @Override
+ public ImsCallProfile getRemoteCallProfile() {
+ return null;
+ }
+
+ /**
+ * @param name The String extra key.
+ * @return The string extra value associated with the specified property.
+ */
+ @Override
+ public String getProperty(String name) {
+ return null;
+ }
+
+ /**
+ * @return The {@link ImsCallSessionImplBase} state.
+ */
+ @Override
+ public int getState() {
+ return -1;
+ }
+
+ /**
+ * @return true if the {@link ImsCallSessionImplBase} is in a call, false otherwise.
+ */
+ @Override
+ public boolean isInCall() {
+ return false;
+ }
+
+ /**
+ * Mutes or unmutes the mic for the active call.
+ *
+ * @param muted true if the call should be muted, false otherwise.
+ */
+ @Override
+ public void setMute(boolean muted) {
+ }
+
+ /**
+ * Initiates an IMS call with the specified number and call profile.
+ * The session listener set in {@link #setListener(IImsCallSessionListener)} is called back upon
+ * defined session events.
+ * Only valid to call when the session state is in
+ * {@link ImsCallSession.State#IDLE}.
+ *
+ * @param callee dialed string to make the call to
+ * @param profile call profile to make the call with the specified service type,
+ * call type and media information
+ * @see {@link ImsCallSession.Listener#callSessionStarted},
+ * {@link ImsCallSession.Listener#callSessionStartFailed}
+ */
+ @Override
+ public void start(String callee, ImsCallProfile profile) {
+ }
+
+ /**
+ * Initiates an IMS call with the specified participants and call profile.
+ * The session listener set in {@link #setListener(IImsCallSessionListener)} is called back upon
+ * defined session events.
+ * The method is only valid to call when the session state is in
+ * {@link ImsCallSession.State#IDLE}.
+ *
+ * @param participants participant list to initiate an IMS conference call
+ * @param profile call profile to make the call with the specified service type,
+ * call type and media information
+ * @see {@link ImsCallSession.Listener#callSessionStarted},
+ * {@link ImsCallSession.Listener#callSessionStartFailed}
+ */
+ @Override
+ public void startConference(String[] participants, ImsCallProfile profile) {
+ }
+
+ /**
+ * Accepts an incoming call or session update.
+ *
+ * @param callType call type specified in {@link ImsCallProfile} to be answered
+ * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered
+ * @see {@link ImsCallSession.Listener#callSessionStarted}
+ */
+ @Override
+ public void accept(int callType, ImsStreamMediaProfile profile) {
+ }
+
+ /**
+ * Rejects an incoming call or session update.
+ *
+ * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
+ * {@link ImsCallSession.Listener#callSessionStartFailed}
+ */
+ @Override
+ public void reject(int reason) {
+ }
+
+ /**
+ * Terminates a call.
+ *
+ * @param reason reason code to terminate a call, defined in {@link ImsReasonInfo}.
+ *
+ * @see {@link ImsCallSession.Listener#callSessionTerminated}
+ */
+ @Override
+ public void terminate(int reason) {
+ }
+
+ /**
+ * Puts a call on hold. When it succeeds, {@link ImsCallSession.Listener#callSessionHeld} is
+ * called.
+ *
+ * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call
+ * @see {@link ImsCallSession.Listener#callSessionHeld},
+ * {@link ImsCallSession.Listener#callSessionHoldFailed}
+ */
+ @Override
+ public void hold(ImsStreamMediaProfile profile) {
+ }
+
+ /**
+ * Continues a call that's on hold. When it succeeds,
+ * {@link ImsCallSession.Listener#callSessionResumed} is called.
+ *
+ * @param profile stream media profile with {@link ImsStreamMediaProfile} to resume the call
+ * @see {@link ImsCallSession.Listener#callSessionResumed},
+ * {@link ImsCallSession.Listener#callSessionResumeFailed}
+ */
+ @Override
+ public void resume(ImsStreamMediaProfile profile) {
+ }
+
+ /**
+ * Merges the active and held call. When the merge starts,
+ * {@link ImsCallSession.Listener#callSessionMergeStarted} is called.
+ * {@link ImsCallSession.Listener#callSessionMergeComplete} is called if the merge is
+ * successful, and {@link ImsCallSession.Listener#callSessionMergeFailed} is called if the merge
+ * fails.
+ *
+ * @see {@link ImsCallSession.Listener#callSessionMergeStarted},
+ * {@link ImsCallSession.Listener#callSessionMergeComplete},
+ * {@link ImsCallSession.Listener#callSessionMergeFailed}
+ */
+ @Override
+ public void merge() {
+ }
+
+ /**
+ * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
+ *
+ * @param callType call type specified in {@link ImsCallProfile} to be updated
+ * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated
+ * @see {@link ImsCallSession.Listener#callSessionUpdated},
+ * {@link ImsCallSession.Listener#callSessionUpdateFailed}
+ */
+ @Override
+ public void update(int callType, ImsStreamMediaProfile profile) {
+ }
+
+ /**
+ * Extends this call to the conference call with the specified recipients.
+ *
+ * @param participants participant list to be invited to the conference call after extending the
+ * call
+ * @see {@link ImsCallSession.Listener#callSessionConferenceExtended},
+ * {@link ImsCallSession.Listener#callSessionConferenceExtendFailed}
+ */
+ @Override
+ public void extendToConference(String[] participants) {
+ }
+
+ /**
+ * Requests the conference server to invite an additional participants to the conference.
+ *
+ * @param participants participant list to be invited to the conference call
+ * @see {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestDelivered},
+ * {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestFailed}
+ */
+ @Override
+ public void inviteParticipants(String[] participants) {
+ }
+
+ /**
+ * Requests the conference server to remove the specified participants from the conference.
+ *
+ * @param participants participant list to be removed from the conference call
+ * @see {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestDelivered},
+ * {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestFailed}
+ */
+ @Override
+ public void removeParticipants(String[] participants) {
+ }
+
+ /**
+ * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
+ * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
+ * and event flash to 16. Currently, event flash is not supported.
+ *
+ * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
+ */
+ @Override
+ public void sendDtmf(char c, Message result) {
+ }
+
+ /**
+ * Start a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
+ * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
+ * and event flash to 16. Currently, event flash is not supported.
+ *
+ * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
+ */
+ @Override
+ public void startDtmf(char c) {
+ }
+
+ /**
+ * Stop a DTMF code.
+ */
+ @Override
+ public void stopDtmf() {
+ }
+
+ /**
+ * Sends an USSD message.
+ *
+ * @param ussdMessage USSD message to send
+ */
+ @Override
+ public void sendUssd(String ussdMessage) {
+ }
+
+ @Override
+ public IImsVideoCallProvider getVideoCallProvider() {
+ return null;
+ }
+
+ /**
+ * Determines if the current session is multiparty.
+ * @return {@code True} if the session is multiparty.
+ */
+ @Override
+ public boolean isMultiparty() {
+ return false;
+ }
+
+ /**
+ * Device issues RTT modify request
+ * @param toProfile The profile with requested changes made
+ */
+ @Override
+ public void sendRttModifyRequest(ImsCallProfile toProfile) {
+ }
+
+ /**
+ * Device responds to Remote RTT modify request
+ * @param status true if the the request was accepted or false of the request is defined.
+ */
+ @Override
+ public void sendRttModifyResponse(boolean status) {
+ }
+
+ /**
+ * Device sends RTT message
+ * @param rttMessage RTT message to be sent
+ */
+ @Override
+ public void sendRttMessage(String rttMessage) {
+ }
+
+ /**
+ * There are two different ImsCallSessionListeners that need to reconciled here, we need to
+ * convert the "old" version of the com.android.ims.internal.IImsCallSessionListener to the
+ * "new" version of the Listener android.telephony.ims.ImsCallSessionListener when calling
+ * back to the framework.
+ */
+ private class ImsCallSessionListenerConverter
+ extends com.android.ims.internal.IImsCallSessionListener.Stub {
+
+ private final IImsCallSessionListener mNewListener;
+
+ public ImsCallSessionListenerConverter(IImsCallSessionListener listener) {
+ mNewListener = listener;
+ }
+
+ @Override
+ public void callSessionProgressing(IImsCallSession i,
+ ImsStreamMediaProfile imsStreamMediaProfile) throws RemoteException {
+ mNewListener.callSessionProgressing(imsStreamMediaProfile);
+ }
+
+ @Override
+ public void callSessionStarted(IImsCallSession i, ImsCallProfile imsCallProfile)
+ throws RemoteException {
+ mNewListener.callSessionInitiated(imsCallProfile);
+ }
+
+ @Override
+ public void callSessionStartFailed(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+ throws RemoteException {
+ mNewListener.callSessionInitiatedFailed(imsReasonInfo);
+ }
+
+ @Override
+ public void callSessionTerminated(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+ throws RemoteException {
+ mNewListener.callSessionTerminated(imsReasonInfo);
+ }
+
+ @Override
+ public void callSessionHeld(IImsCallSession i, ImsCallProfile imsCallProfile)
+ throws RemoteException {
+ mNewListener.callSessionHeld(imsCallProfile);
+ }
+
+ @Override
+ public void callSessionHoldFailed(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+ throws RemoteException {
+ mNewListener.callSessionHoldFailed(imsReasonInfo);
+ }
+
+ @Override
+ public void callSessionHoldReceived(IImsCallSession i, ImsCallProfile imsCallProfile)
+ throws RemoteException {
+ mNewListener.callSessionHoldReceived(imsCallProfile);
+ }
+
+ @Override
+ public void callSessionResumed(IImsCallSession i, ImsCallProfile imsCallProfile)
+ throws RemoteException {
+ mNewListener.callSessionResumed(imsCallProfile);
+ }
+
+ @Override
+ public void callSessionResumeFailed(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+ throws RemoteException {
+ mNewListener.callSessionResumeFailed(imsReasonInfo);
+ }
+
+ @Override
+ public void callSessionResumeReceived(IImsCallSession i, ImsCallProfile imsCallProfile)
+ throws RemoteException {
+ mNewListener.callSessionResumeReceived(imsCallProfile);
+ }
+
+ @Override
+ public void callSessionMergeStarted(IImsCallSession i, IImsCallSession newSession,
+ ImsCallProfile profile)
+ throws RemoteException {
+ mNewListener.callSessionMergeStarted(newSession, profile);
+ }
+
+ @Override
+ public void callSessionMergeComplete(IImsCallSession iImsCallSession)
+ throws RemoteException {
+ mNewListener.callSessionMergeComplete(iImsCallSession);
+ }
+
+ @Override
+ public void callSessionMergeFailed(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+ throws RemoteException {
+ mNewListener.callSessionMergeFailed(imsReasonInfo);
+ }
+
+ @Override
+ public void callSessionUpdated(IImsCallSession i, ImsCallProfile imsCallProfile)
+ throws RemoteException {
+ mNewListener.callSessionUpdated(imsCallProfile);
+ }
+
+ @Override
+ public void callSessionUpdateFailed(IImsCallSession i, ImsReasonInfo imsReasonInfo)
+ throws RemoteException {
+ mNewListener.callSessionUpdateFailed(imsReasonInfo);
+ }
+
+ @Override
+ public void callSessionUpdateReceived(IImsCallSession i, ImsCallProfile imsCallProfile)
+ throws RemoteException {
+ mNewListener.callSessionUpdateReceived(imsCallProfile);
+ }
+
+ @Override
+ public void callSessionConferenceExtended(IImsCallSession i, IImsCallSession newSession,
+ ImsCallProfile imsCallProfile) throws RemoteException {
+ mNewListener.callSessionConferenceExtended(newSession, imsCallProfile);
+ }
+
+ @Override
+ public void callSessionConferenceExtendFailed(IImsCallSession i,
+ ImsReasonInfo imsReasonInfo) throws RemoteException {
+ mNewListener.callSessionConferenceExtendFailed(imsReasonInfo);
+ }
+
+ @Override
+ public void callSessionConferenceExtendReceived(IImsCallSession i,
+ IImsCallSession newSession, ImsCallProfile imsCallProfile)
+ throws RemoteException {
+ mNewListener.callSessionConferenceExtendReceived(newSession, imsCallProfile);
+ }
+
+ @Override
+ public void callSessionInviteParticipantsRequestDelivered(IImsCallSession i)
+ throws RemoteException {
+ mNewListener.callSessionInviteParticipantsRequestDelivered();
+ }
+
+ @Override
+ public void callSessionInviteParticipantsRequestFailed(IImsCallSession i,
+ ImsReasonInfo imsReasonInfo) throws RemoteException {
+ mNewListener.callSessionInviteParticipantsRequestFailed(imsReasonInfo);
+ }
+
+ @Override
+ public void callSessionRemoveParticipantsRequestDelivered(IImsCallSession i)
+ throws RemoteException {
+ mNewListener.callSessionRemoveParticipantsRequestDelivered();
+ }
+
+ @Override
+ public void callSessionRemoveParticipantsRequestFailed(IImsCallSession i,
+ ImsReasonInfo imsReasonInfo) throws RemoteException {
+ mNewListener.callSessionRemoveParticipantsRequestFailed(imsReasonInfo);
+ }
+
+ @Override
+ public void callSessionConferenceStateUpdated(IImsCallSession i,
+ ImsConferenceState imsConferenceState) throws RemoteException {
+ mNewListener.callSessionConferenceStateUpdated(imsConferenceState);
+ }
+
+ @Override
+ public void callSessionUssdMessageReceived(IImsCallSession i, int mode, String message)
+ throws RemoteException {
+ mNewListener.callSessionUssdMessageReceived(mode, message);
+ }
+
+ @Override
+ public void callSessionHandover(IImsCallSession i, int srcAccessTech, int targetAccessTech,
+ ImsReasonInfo reasonInfo) throws RemoteException {
+ mNewListener.callSessionHandover(srcAccessTech, targetAccessTech, reasonInfo);
+ }
+
+ @Override
+ public void callSessionHandoverFailed(IImsCallSession i, int srcAccessTech,
+ int targetAccessTech, ImsReasonInfo reasonInfo) throws RemoteException {
+ mNewListener.callSessionHandoverFailed(srcAccessTech, targetAccessTech, reasonInfo);
+ }
+
+ @Override
+ public void callSessionMayHandover(IImsCallSession i, int srcAccessTech, int targetAccessTech)
+ throws RemoteException {
+ mNewListener.callSessionMayHandover(srcAccessTech, targetAccessTech);
+ }
+
+ @Override
+ public void callSessionTtyModeReceived(IImsCallSession iImsCallSession, int mode)
+ throws RemoteException {
+ mNewListener.callSessionTtyModeReceived(mode);
+ }
+
+ @Override
+ public void callSessionMultipartyStateChanged(IImsCallSession i, boolean isMultiparty)
+ throws RemoteException {
+ mNewListener.callSessionMultipartyStateChanged(isMultiparty);
+ }
+
+ @Override
+ public void callSessionSuppServiceReceived(IImsCallSession i,
+ ImsSuppServiceNotification imsSuppServiceNotification) throws RemoteException {
+ mNewListener.callSessionSuppServiceReceived(imsSuppServiceNotification);
+ }
+
+ @Override
+ public void callSessionRttModifyRequestReceived(IImsCallSession i,
+ ImsCallProfile imsCallProfile) throws RemoteException {
+ mNewListener.callSessionRttModifyRequestReceived(imsCallProfile);
+ }
+
+ @Override
+ public void callSessionRttModifyResponseReceived(int status) throws RemoteException {
+ mNewListener.callSessionRttModifyResponseReceived(status);
+ }
+
+ @Override
+ public void callSessionRttMessageReceived(String rttMessage) throws RemoteException {
+ mNewListener.callSessionRttMessageReceived(rttMessage);
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
new file mode 100644
index 0000000..2c325ba8
--- /dev/null
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.telephony.ims.compat.stub;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsConfigListener;
+import com.android.ims.internal.IImsConfig;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+
+
+/**
+ * Base implementation of ImsConfig.
+ * Override the methods that your implementation of ImsConfig supports.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsConfig maintained by other ImsServices.
+ *
+ * Provides APIs to get/set the IMS service feature/capability/parameters.
+ * The config items include:
+ * 1) Items provisioned by the operator.
+ * 2) Items configured by user. Mainly service feature class.
+ *
+ * The inner class {@link ImsConfigStub} implements methods of IImsConfig AIDL interface.
+ * The IImsConfig AIDL interface is called by ImsConfig, which may exist in many other processes.
+ * ImsConfigImpl access to the configuration parameters may be arbitrarily slow, especially in
+ * during initialization, or times when a lot of configuration parameters are being set/get
+ * (such as during boot up or SIM card change). By providing a cache in ImsConfigStub, we can speed
+ * up access to these configuration parameters, so a query to the ImsConfigImpl does not have to be
+ * performed every time.
+ * @hide
+ */
+
+public class ImsConfigImplBase {
+
+ static final private String TAG = "ImsConfigImplBase";
+
+ ImsConfigStub mImsConfigStub;
+
+ public ImsConfigImplBase(Context context) {
+ mImsConfigStub = new ImsConfigStub(this, context);
+ }
+
+ /**
+ * Gets the value for ims service/capabilities parameters from the provisioned
+ * value storage. Synchronous blocking call.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @return value in Integer format.
+ */
+ public int getProvisionedValue(int item) throws RemoteException {
+ return -1;
+ }
+
+ /**
+ * Gets the value for ims service/capabilities parameters from the provisioned
+ * value storage. Synchronous blocking call.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @return value in String format.
+ */
+ public String getProvisionedStringValue(int item) throws RemoteException {
+ return null;
+ }
+
+ /**
+ * Sets the value for IMS service/capabilities parameters by the operator device
+ * management entity. It sets the config item value in the provisioned storage
+ * from which the master value is derived. Synchronous blocking call.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in Integer format.
+ * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+ */
+ public int setProvisionedValue(int item, int value) throws RemoteException {
+ return ImsConfig.OperationStatusConstants.FAILED;
+ }
+
+ /**
+ * Sets the value for IMS service/capabilities parameters by the operator device
+ * management entity. It sets the config item value in the provisioned storage
+ * from which the master value is derived. Synchronous blocking call.
+ *
+ * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in String format.
+ * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+ */
+ public int setProvisionedStringValue(int item, String value) throws RemoteException {
+ return ImsConfig.OperationStatusConstants.FAILED;
+ }
+
+ /**
+ * Gets the value of the specified IMS feature item for specified network type.
+ * This operation gets the feature config value from the master storage (i.e. final
+ * value). Asynchronous non-blocking call.
+ *
+ * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
+ * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
+ * @param listener feature value returned asynchronously through listener.
+ */
+ public void getFeatureValue(int feature, int network, ImsConfigListener listener)
+ throws RemoteException {
+ }
+
+ /**
+ * Sets the value for IMS feature item for specified network type.
+ * This operation stores the user setting in setting db from which master db
+ * is derived.
+ *
+ * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
+ * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
+ * @param value as defined in com.android.ims.ImsConfig#FeatureValueConstants.
+ * @param listener, provided if caller needs to be notified for set result.
+ */
+ public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
+ throws RemoteException {
+ }
+
+ /**
+ * Gets the value for IMS VoLTE provisioned.
+ * This should be the same as the operator provisioned value if applies.
+ */
+ public boolean getVolteProvisioned() throws RemoteException {
+ return false;
+ }
+
+ /**
+ * Gets the value for IMS feature item video quality.
+ *
+ * @param listener Video quality value returned asynchronously through listener.
+ */
+ public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
+ }
+
+ /**
+ * Sets the value for IMS feature item video quality.
+ *
+ * @param quality, defines the value of video quality.
+ * @param listener, provided if caller needs to be notified for set result.
+ */
+ public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException {
+ }
+
+ public IImsConfig getIImsConfig() { return mImsConfigStub; }
+
+ /**
+ * Updates provisioning value and notifies the framework of the change.
+ * Doesn't call #setProvisionedValue and assumes the result succeeded.
+ * This should only be used by modem when they implicitly changed provisioned values.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in Integer format.
+ */
+ public final void notifyProvisionedValueChanged(int item, int value) {
+ mImsConfigStub.updateCachedValue(item, value, true);
+ }
+
+ /**
+ * Updates provisioning value and notifies the framework of the change.
+ * Doesn't call #setProvisionedValue and assumes the result succeeded.
+ * This should only be used by modem when they implicitly changed provisioned values.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in String format.
+ */
+ public final void notifyProvisionedValueChanged(int item, String value) {
+ mImsConfigStub.updateCachedValue(item, value, true);
+ }
+
+ /**
+ * Implements the IImsConfig AIDL interface, which is called by potentially many processes
+ * in order to get/set configuration parameters.
+ *
+ * It holds an object of ImsConfigImplBase class which is usually extended by ImsConfigImpl
+ * with actual implementations from vendors. This class caches provisioned values from
+ * ImsConfigImpl layer because queries through ImsConfigImpl can be slow. When query goes in,
+ * it first checks cache layer. If missed, it will call the vendor implementation of
+ * ImsConfigImplBase API.
+ * and cache the return value if the set succeeds.
+ *
+ * Provides APIs to get/set the IMS service feature/capability/parameters.
+ * The config items include:
+ * 1) Items provisioned by the operator.
+ * 2) Items configured by user. Mainly service feature class.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ static public class ImsConfigStub extends IImsConfig.Stub {
+ Context mContext;
+ WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
+ private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
+ private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
+
+ @VisibleForTesting
+ public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Context context) {
+ mContext = context;
+ mImsConfigImplBaseWeakReference =
+ new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
+ }
+
+ /**
+ * Gets the value for ims service/capabilities parameters. It first checks its local cache,
+ * if missed, it will call ImsConfigImplBase.getProvisionedValue.
+ * Synchronous blocking call.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @return value in Integer format.
+ */
+ @Override
+ public synchronized int getProvisionedValue(int item) throws RemoteException {
+ if (mProvisionedIntValue.containsKey(item)) {
+ return mProvisionedIntValue.get(item);
+ } else {
+ int retVal = getImsConfigImpl().getProvisionedValue(item);
+ if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
+ updateCachedValue(item, retVal, false);
+ }
+ return retVal;
+ }
+ }
+
+ /**
+ * Gets the value for ims service/capabilities parameters. It first checks its local cache,
+ * if missed, it will call #ImsConfigImplBase.getProvisionedValue.
+ * Synchronous blocking call.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @return value in String format.
+ */
+ @Override
+ public synchronized String getProvisionedStringValue(int item) throws RemoteException {
+ if (mProvisionedIntValue.containsKey(item)) {
+ return mProvisionedStringValue.get(item);
+ } else {
+ String retVal = getImsConfigImpl().getProvisionedStringValue(item);
+ if (retVal != null) {
+ updateCachedValue(item, retVal, false);
+ }
+ return retVal;
+ }
+ }
+
+ /**
+ * Sets the value for IMS service/capabilities parameters by the operator device
+ * management entity. It sets the config item value in the provisioned storage
+ * from which the master value is derived, and write it into local cache.
+ * Synchronous blocking call.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in Integer format.
+ * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+ */
+ @Override
+ public synchronized int setProvisionedValue(int item, int value) throws RemoteException {
+ mProvisionedIntValue.remove(item);
+ int retVal = getImsConfigImpl().setProvisionedValue(item, value);
+ if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+ updateCachedValue(item, value, true);
+ } else {
+ Log.d(TAG, "Set provision value of " + item +
+ " to " + value + " failed with error code " + retVal);
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Sets the value for IMS service/capabilities parameters by the operator device
+ * management entity. It sets the config item value in the provisioned storage
+ * from which the master value is derived, and write it into local cache.
+ * Synchronous blocking call.
+ *
+ * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in String format.
+ * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+ */
+ @Override
+ public synchronized int setProvisionedStringValue(int item, String value)
+ throws RemoteException {
+ mProvisionedStringValue.remove(item);
+ int retVal = getImsConfigImpl().setProvisionedStringValue(item, value);
+ if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+ updateCachedValue(item, value, true);
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Wrapper function to call ImsConfigImplBase.getFeatureValue.
+ */
+ @Override
+ public void getFeatureValue(int feature, int network, ImsConfigListener listener)
+ throws RemoteException {
+ getImsConfigImpl().getFeatureValue(feature, network, listener);
+ }
+
+ /**
+ * Wrapper function to call ImsConfigImplBase.setFeatureValue.
+ */
+ @Override
+ public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
+ throws RemoteException {
+ getImsConfigImpl().setFeatureValue(feature, network, value, listener);
+ }
+
+ /**
+ * Wrapper function to call ImsConfigImplBase.getVolteProvisioned.
+ */
+ @Override
+ public boolean getVolteProvisioned() throws RemoteException {
+ return getImsConfigImpl().getVolteProvisioned();
+ }
+
+ /**
+ * Wrapper function to call ImsConfigImplBase.getVideoQuality.
+ */
+ @Override
+ public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
+ getImsConfigImpl().getVideoQuality(listener);
+ }
+
+ /**
+ * Wrapper function to call ImsConfigImplBase.setVideoQuality.
+ */
+ @Override
+ public void setVideoQuality(int quality, ImsConfigListener listener)
+ throws RemoteException {
+ getImsConfigImpl().setVideoQuality(quality, listener);
+ }
+
+ private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
+ ImsConfigImplBase ref = mImsConfigImplBaseWeakReference.get();
+ if (ref == null) {
+ throw new RemoteException("Fail to get ImsConfigImpl");
+ } else {
+ return ref;
+ }
+ }
+
+ private void sendImsConfigChangedIntent(int item, int value) {
+ sendImsConfigChangedIntent(item, Integer.toString(value));
+ }
+
+ private void sendImsConfigChangedIntent(int item, String value) {
+ Intent configChangedIntent = new Intent(ImsConfig.ACTION_IMS_CONFIG_CHANGED);
+ configChangedIntent.putExtra(ImsConfig.EXTRA_CHANGED_ITEM, item);
+ configChangedIntent.putExtra(ImsConfig.EXTRA_NEW_VALUE, value);
+ if (mContext != null) {
+ mContext.sendBroadcast(configChangedIntent);
+ }
+ }
+
+ protected synchronized void updateCachedValue(int item, int value, boolean notifyChange) {
+ mProvisionedIntValue.put(item, value);
+ if (notifyChange) {
+ sendImsConfigChangedIntent(item, value);
+ }
+ }
+
+ protected synchronized void updateCachedValue(
+ int item, String value, boolean notifyChange) {
+ mProvisionedStringValue.put(item, value);
+ if (notifyChange) {
+ sendImsConfigChangedIntent(item, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
similarity index 90%
rename from telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java
rename to telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
index daa74c8..b2aa080 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 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.
@@ -14,15 +14,15 @@
* limitations under the License
*/
-package android.telephony.ims.stub;
+package android.telephony.ims.compat.stub;
import android.os.Bundle;
import android.os.RemoteException;
-import com.android.ims.ImsCallForwardInfo;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsSsData;
-import com.android.ims.ImsSsInfo;
+import android.telephony.ims.ImsCallForwardInfo;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsSsData;
+import android.telephony.ims.ImsSsInfo;
import com.android.ims.internal.IImsUt;
import com.android.ims.internal.IImsUtListener;
diff --git a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.aidl b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.aidl
similarity index 92%
rename from telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.aidl
rename to telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.aidl
index f4ec0eb..e789bd5 100644
--- a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.aidl
+++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.aidl
@@ -14,6 +14,6 @@
* limitations under the License
*/
-package android.telephony.ims.internal.feature;
+package android.telephony.ims.feature;
parcelable CapabilityChangeRequest;
diff --git a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
similarity index 79%
rename from telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java
rename to telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
index 5dbf077..7c793a5 100644
--- a/telephony/java/android/telephony/ims/internal/feature/CapabilityChangeRequest.java
+++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 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.
@@ -14,8 +14,9 @@
* limitations under the License
*/
-package android.telephony.ims.internal.feature;
+package android.telephony.ims.feature;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -30,17 +31,32 @@
* the request.
* {@hide}
*/
-public class CapabilityChangeRequest implements Parcelable {
+@SystemApi
+public final class CapabilityChangeRequest implements Parcelable {
+ /**
+ * Contains a feature capability, defined as
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, or
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS},
+ * along with an associated technology, defined as
+ * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or
+ * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}
+ */
public static class CapabilityPair {
private final int mCapability;
private final int radioTech;
- public CapabilityPair(int capability, int radioTech) {
+ public CapabilityPair(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
this.mCapability = capability;
this.radioTech = radioTech;
}
+ /**
+ * @hide
+ */
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -52,6 +68,9 @@
return getRadioTech() == that.getRadioTech();
}
+ /**
+ * @hide
+ */
@Override
public int hashCode() {
int result = getCapability();
@@ -59,10 +78,22 @@
return result;
}
+ /**
+ * @return The stored capability, defined as
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, or
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS}
+ */
public @MmTelFeature.MmTelCapabilities.MmTelCapability int getCapability() {
return mCapability;
}
+ /**
+ * @return the stored radio technology, defined as
+ * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or
+ * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}
+ */
public @ImsRegistrationImplBase.ImsRegistrationTech int getRadioTech() {
return radioTech;
}
@@ -73,6 +104,7 @@
// Pair contains <radio tech, mCapability>
private final Set<CapabilityPair> mCapabilitiesToDisable;
+ /** @hide */
public CapabilityChangeRequest() {
mCapabilitiesToEnable = new ArraySet<>();
mCapabilitiesToDisable = new ArraySet<>();
@@ -130,6 +162,9 @@
}
}
+ /**
+ * @hide
+ */
protected CapabilityChangeRequest(Parcel in) {
int enableSize = in.readInt();
mCapabilitiesToEnable = new ArraySet<>(enableSize);
@@ -177,17 +212,24 @@
}
}
+ /**
+ * @hide
+ */
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CapabilityChangeRequest)) return false;
- CapabilityChangeRequest that = (CapabilityChangeRequest) o;
+ CapabilityChangeRequest
+ that = (CapabilityChangeRequest) o;
if (!mCapabilitiesToEnable.equals(that.mCapabilitiesToEnable)) return false;
return mCapabilitiesToDisable.equals(that.mCapabilitiesToDisable);
}
+ /**
+ * @hide
+ */
@Override
public int hashCode() {
int result = mCapabilitiesToEnable.hashCode();
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index d47cea30..bfdd453 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 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.
@@ -17,28 +17,35 @@
package android.telephony.ims.feature;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.os.IInterface;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.telephony.SubscriptionManager;
+import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;
import com.android.ims.internal.IImsFeatureStatusCallback;
+import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
-import java.util.List;
import java.util.Set;
import java.util.WeakHashMap;
/**
- * Base class for all IMS features that are supported by the framework.
+ * Base class for all IMS features that are supported by the framework. Use a concrete subclass
+ * of {@link ImsFeature}, such as {@link MmTelFeature} or {@link RcsFeature}.
+ *
* @hide
*/
+@SystemApi
public abstract class ImsFeature {
private static final String LOG_TAG = "ImsFeature";
@@ -46,7 +53,8 @@
/**
* Action to broadcast when ImsService is up.
* Internal use only.
- * Only defined here separately compatibility purposes with the old ImsService.
+ * Only defined here separately for compatibility purposes with the old ImsService.
+ *
* @hide
*/
public static final String ACTION_IMS_SERVICE_UP =
@@ -56,6 +64,7 @@
* Action to broadcast when ImsService is down.
* Internal use only.
* Only defined here separately for compatibility purposes with the old ImsService.
+ *
* @hide
*/
public static final String ACTION_IMS_SERVICE_DOWN =
@@ -65,67 +74,329 @@
* Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
* A long value; the phone ID corresponding to the IMS service coming up or down.
* Only defined here separately for compatibility purposes with the old ImsService.
+ *
* @hide
*/
public static final String EXTRA_PHONE_ID = "android:phone_id";
- // Invalid feature value
- public static final int INVALID = -1;
+ /**
+ * Invalid feature value\
+ * @hide
+ */
+ public static final int FEATURE_INVALID = -1;
// ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
// defined values in ImsServiceClass for compatibility purposes.
- public static final int EMERGENCY_MMTEL = 0;
- public static final int MMTEL = 1;
- public static final int RCS = 2;
- // Total number of features defined
- public static final int MAX = 3;
+ /**
+ * This feature supports emergency calling over MMTEL.
+ */
+ public static final int FEATURE_EMERGENCY_MMTEL = 0;
+ /**
+ * This feature supports the MMTEL feature.
+ */
+ public static final int FEATURE_MMTEL = 1;
+ /**
+ * This feature supports the RCS feature.
+ */
+ public static final int FEATURE_RCS = 2;
+ /**
+ * Total number of features defined
+ * @hide
+ */
+ public static final int FEATURE_MAX = 3;
- // Integer values defining the state of the ImsFeature at any time.
+ /**
+ * Integer values defining IMS features that are supported in ImsFeature.
+ * @hide
+ */
@IntDef(flag = true,
value = {
- STATE_NOT_AVAILABLE,
+ FEATURE_EMERGENCY_MMTEL,
+ FEATURE_MMTEL,
+ FEATURE_RCS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FeatureType {}
+
+ /**
+ * Integer values defining the state of the ImsFeature at any time.
+ * @hide
+ */
+ @IntDef(flag = true,
+ value = {
+ STATE_UNAVAILABLE,
STATE_INITIALIZING,
STATE_READY,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ImsState {}
- public static final int STATE_NOT_AVAILABLE = 0;
+
+ /**
+ * This {@link ImsFeature}'s state is unavailable and should not be communicated with.
+ */
+ public static final int STATE_UNAVAILABLE = 0;
+ /**
+ * This {@link ImsFeature} state is initializing and should not be communicated with.
+ */
public static final int STATE_INITIALIZING = 1;
+ /**
+ * This {@link ImsFeature} is ready for communication.
+ */
public static final int STATE_READY = 2;
+ /**
+ * Integer values defining the result codes that should be returned from
+ * {@link #changeEnabledCapabilities} when the framework tries to set a feature's capability.
+ * @hide
+ */
+ @IntDef(flag = true,
+ value = {
+ CAPABILITY_ERROR_GENERIC,
+ CAPABILITY_SUCCESS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ImsCapabilityError {}
+
+ /**
+ * The capability was unable to be changed.
+ */
+ public static final int CAPABILITY_ERROR_GENERIC = -1;
+ /**
+ * The capability was able to be changed.
+ */
+ public static final int CAPABILITY_SUCCESS = 0;
+
+
+ /**
+ * The framework implements this callback in order to register for Feature Capability status
+ * updates, via {@link #onCapabilitiesStatusChanged(Capabilities)}, query Capability
+ * configurations, via {@link #onQueryCapabilityConfiguration}, as well as to receive error
+ * callbacks when the ImsService can not change the capability as requested, via
+ * {@link #onChangeCapabilityConfigurationError}.
+ *
+ * @hide
+ */
+ public static class CapabilityCallback extends IImsCapabilityCallback.Stub {
+
+ @Override
+ public final void onCapabilitiesStatusChanged(int config) throws RemoteException {
+ onCapabilitiesStatusChanged(new Capabilities(config));
+ }
+
+ /**
+ * Returns the result of a query for the capability configuration of a requested capability.
+ *
+ * @param capability The capability that was requested.
+ * @param radioTech The IMS radio technology associated with the capability.
+ * @param isEnabled true if the capability is enabled, false otherwise.
+ */
+ @Override
+ public void onQueryCapabilityConfiguration(int capability, int radioTech,
+ boolean isEnabled) {
+
+ }
+
+ /**
+ * Called when a change to the capability configuration has returned an error.
+ *
+ * @param capability The capability that was requested to be changed.
+ * @param radioTech The IMS radio technology associated with the capability.
+ * @param reason error associated with the failure to change configuration.
+ */
+ @Override
+ public void onChangeCapabilityConfigurationError(int capability, int radioTech,
+ @ImsCapabilityError int reason) {
+ }
+
+ /**
+ * The status of the feature's capabilities has changed to either available or unavailable.
+ * If unavailable, the feature is not able to support the unavailable capability at this
+ * time.
+ *
+ * @param config The new availability of the capabilities.
+ */
+ public void onCapabilitiesStatusChanged(Capabilities config) {
+ }
+ }
+
+ /**
+ * Used by the ImsFeature to call back to the CapabilityCallback that the framework has
+ * provided.
+ */
+ protected static class CapabilityCallbackProxy {
+ private final IImsCapabilityCallback mCallback;
+
+ /** @hide */
+ public CapabilityCallbackProxy(IImsCapabilityCallback c) {
+ mCallback = c;
+ }
+
+ /**
+ * This method notifies the provided framework callback that the request to change the
+ * indicated capability has failed and has not changed.
+ *
+ * @param capability The Capability that will be notified to the framework, defined as
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, or
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS}.
+ * @param radioTech The radio tech that this capability failed for, defined as
+ * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or
+ * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}.
+ * @param reason The reason this capability was unable to be changed, defined as
+ * {@link #CAPABILITY_ERROR_GENERIC} or {@link #CAPABILITY_SUCCESS}.
+ */
+ public void onChangeCapabilityConfigurationError(int capability, int radioTech,
+ @ImsCapabilityError int reason) {
+ if (mCallback == null) {
+ return;
+ }
+ try {
+ mCallback.onChangeCapabilityConfigurationError(capability, radioTech, reason);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "onChangeCapabilityConfigurationError called on dead binder.");
+ }
+ }
+ }
+
+ /**
+ * Contains the capabilities defined and supported by an ImsFeature in the form of a bit mask.
+ * @hide
+ */
+ public static class Capabilities {
+ protected int mCapabilities = 0;
+
+ public Capabilities() {
+ }
+
+ protected Capabilities(int capabilities) {
+ mCapabilities = capabilities;
+ }
+
+ /**
+ * @param capabilities Capabilities to be added to the configuration in the form of a
+ * bit mask.
+ */
+ public void addCapabilities(int capabilities) {
+ mCapabilities |= capabilities;
+ }
+
+ /**
+ * @param capabilities Capabilities to be removed to the configuration in the form of a
+ * bit mask.
+ */
+ public void removeCapabilities(int capabilities) {
+ mCapabilities &= ~capabilities;
+ }
+
+ /**
+ * @return true if all of the capabilities specified are capable.
+ */
+ public boolean isCapable(int capabilities) {
+ return (mCapabilities & capabilities) == capabilities;
+ }
+
+ /**
+ * @return a deep copy of the Capabilites.
+ */
+ public Capabilities copy() {
+ return new Capabilities(mCapabilities);
+ }
+
+ /**
+ * @return a bitmask containing the capability flags directly.
+ */
+ public int getMask() {
+ return mCapabilities;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Capabilities)) return false;
+
+ Capabilities that = (Capabilities) o;
+
+ return mCapabilities == that.mCapabilities;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public int hashCode() {
+ return mCapabilities;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public String toString() {
+ return "Capabilities: " + Integer.toBinaryString(mCapabilities);
+ }
+ }
+
private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap(
new WeakHashMap<IImsFeatureStatusCallback, Boolean>());
- private @ImsState int mState = STATE_NOT_AVAILABLE;
+ private @ImsState int mState = STATE_UNAVAILABLE;
private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+ /**
+ * @hide
+ */
protected Context mContext;
+ private final Object mLock = new Object();
+ private final RemoteCallbackList<IImsCapabilityCallback> mCapabilityCallbacks
+ = new RemoteCallbackList<>();
+ private Capabilities mCapabilityStatus = new Capabilities();
- public void setContext(Context context) {
+ /**
+ * @hide
+ */
+ public final void initialize(Context context, int slotId) {
mContext = context;
- }
-
- public void setSlotId(int slotId) {
mSlotId = slotId;
}
+ /**
+ * @return The current state of the feature, defined as {@link #STATE_UNAVAILABLE},
+ * {@link #STATE_INITIALIZING}, or {@link #STATE_READY}.
+ * @hide
+ */
public int getFeatureState() {
- return mState;
- }
-
- protected final void setFeatureState(@ImsState int state) {
- if (mState != state) {
- mState = state;
- notifyFeatureState(state);
+ synchronized (mLock) {
+ return mState;
}
}
- public void addImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
- if (c == null) {
- return;
+ /**
+ * Set the state of the ImsFeature. The state is used as a signal to the framework to start or
+ * stop communication, depending on the state sent.
+ * @param state The ImsFeature's state, defined as {@link #STATE_UNAVAILABLE},
+ * {@link #STATE_INITIALIZING}, or {@link #STATE_READY}.
+ */
+ public final void setFeatureState(@ImsState int state) {
+ synchronized (mLock) {
+ if (mState != state) {
+ mState = state;
+ notifyFeatureState(state);
+ }
}
+ }
+
+ /**
+ * Not final for testing, but shouldn't be extended!
+ * @hide
+ */
+ @VisibleForTesting
+ public void addImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) {
try {
// If we have just connected, send queued status.
- c.notifyImsFeatureStatus(mState);
+ c.notifyImsFeatureStatus(getFeatureState());
// Add the callback if the callback completes successfully without a RemoteException.
- synchronized (mStatusCallbacks) {
+ synchronized (mLock) {
mStatusCallbacks.add(c);
}
} catch (RemoteException e) {
@@ -133,23 +404,24 @@
}
}
- public void removeImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
- if (c == null) {
- return;
- }
- synchronized (mStatusCallbacks) {
+ /**
+ * Not final for testing, but shouldn't be extended!
+ * @hide
+ */
+ @VisibleForTesting
+ public void removeImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) {
+ synchronized (mLock) {
mStatusCallbacks.remove(c);
}
}
/**
* Internal method called by ImsFeature when setFeatureState has changed.
- * @param state
*/
private void notifyFeatureState(@ImsState int state) {
- synchronized (mStatusCallbacks) {
+ synchronized (mLock) {
for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator();
- iter.hasNext(); ) {
+ iter.hasNext(); ) {
IImsFeatureStatusCallback callback = iter.next();
try {
Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
@@ -168,12 +440,12 @@
* Provide backwards compatibility using deprecated service UP/DOWN intents.
*/
private void sendImsServiceIntent(@ImsState int state) {
- if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ if (mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
return;
}
Intent intent;
switch (state) {
- case ImsFeature.STATE_NOT_AVAILABLE:
+ case ImsFeature.STATE_UNAVAILABLE:
case ImsFeature.STATE_INITIALIZING:
intent = new Intent(ACTION_IMS_SERVICE_DOWN);
break;
@@ -188,17 +460,104 @@
}
/**
- * Called when the feature is ready to use.
+ * @hide
*/
- public abstract void onFeatureReady();
+ public final void addCapabilityCallback(IImsCapabilityCallback c) {
+ mCapabilityCallbacks.register(c);
+ }
/**
- * Called when the feature is being removed and must be cleaned up.
+ * @hide
+ */
+ public final void removeCapabilityCallback(IImsCapabilityCallback c) {
+ mCapabilityCallbacks.unregister(c);
+ }
+
+ /**
+ * @return the cached capabilities status for this feature.
+ * @hide
+ */
+ @VisibleForTesting
+ public Capabilities queryCapabilityStatus() {
+ synchronized (mLock) {
+ return mCapabilityStatus.copy();
+ }
+ }
+
+ /**
+ * Called internally to request the change of enabled capabilities.
+ * @hide
+ */
+ @VisibleForTesting
+ public final void requestChangeEnabledCapabilities(CapabilityChangeRequest request,
+ IImsCapabilityCallback c) {
+ if (request == null) {
+ throw new IllegalArgumentException(
+ "ImsFeature#requestChangeEnabledCapabilities called with invalid params.");
+ }
+ changeEnabledCapabilities(request, new CapabilityCallbackProxy(c));
+ }
+
+ /**
+ * Called by the ImsFeature when the capabilities status has changed.
+ *
+ * @param c A {@link Capabilities} containing the new Capabilities status.
+ *
+ * @hide
+ */
+ protected final void notifyCapabilitiesStatusChanged(Capabilities c) {
+ synchronized (mLock) {
+ mCapabilityStatus = c.copy();
+ }
+ int count = mCapabilityCallbacks.beginBroadcast();
+ try {
+ for (int i = 0; i < count; i++) {
+ try {
+ mCapabilityCallbacks.getBroadcastItem(i).onCapabilitiesStatusChanged(
+ c.mCapabilities);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, e + " " + "notifyCapabilitiesStatusChanged() - Skipping " +
+ "callback.");
+ }
+ }
+ } finally {
+ mCapabilityCallbacks.finishBroadcast();
+ }
+ }
+
+ /**
+ * Features should override this method to receive Capability preference change requests from
+ * the framework using the provided {@link CapabilityChangeRequest}. If any of the capabilities
+ * in the {@link CapabilityChangeRequest} are not able to be completed due to an error,
+ * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} should be called for
+ * each failed capability.
+ *
+ * @param request A {@link CapabilityChangeRequest} containing requested capabilities to
+ * enable/disable.
+ * @param c A {@link CapabilityCallbackProxy}, which will be used to call back to the framework
+ * setting a subset of these capabilities fail, using
+ * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError}.
+ */
+ public abstract void changeEnabledCapabilities(CapabilityChangeRequest request,
+ CapabilityCallbackProxy c);
+
+ /**
+ * Called when the framework is removing this feature and it needs to be cleaned up.
*/
public abstract void onFeatureRemoved();
/**
- * @return Binder instance
+ * Called when the feature has been initialized and communication with the framework is set up.
+ * Any attempt by this feature to access the framework before this method is called will return
+ * with an {@link IllegalStateException}.
+ * The IMS provider should use this method to trigger registration for this feature on the IMS
+ * network, if needed.
*/
- public abstract IInterface getBinder();
+ public abstract void onFeatureReady();
+
+ /**
+ * @return Binder instance that the framework will use to communicate with this feature.
+ * @hide
+ */
+ protected abstract IInterface getBinder();
}
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
new file mode 100644
index 0000000..09267fc
--- /dev/null
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -0,0 +1,672 @@
+/*
+ * 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.telephony.ims.feature;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telecom.TelecomManager;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.ims.stub.ImsCallSessionImplBase;
+import android.telephony.ims.stub.ImsSmsImplBase;
+import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsMmTelListener;
+import android.telephony.ims.aidl.IImsSmsListener;
+import android.telephony.ims.stub.ImsEcbmImplBase;
+import android.telephony.ims.stub.ImsMultiEndpointImplBase;
+import android.telephony.ims.stub.ImsUtImplBase;
+import android.util.Log;
+
+import android.telephony.ims.ImsCallProfile;
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsEcbm;
+import com.android.ims.internal.IImsMultiEndpoint;
+import com.android.ims.internal.IImsUt;
+import android.telephony.ims.ImsCallSession;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support.
+ *
+ * Any class wishing to use MmTelFeature should extend this class and implement all methods that the
+ * service supports.
+ * @hide
+ */
+@SystemApi
+public class MmTelFeature extends ImsFeature {
+
+ private static final String LOG_TAG = "MmTelFeature";
+
+ private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() {
+
+ @Override
+ public void setListener(IImsMmTelListener l) throws RemoteException {
+ synchronized (mLock) {
+ MmTelFeature.this.setListener(l);
+ }
+ }
+
+ @Override
+ public int getFeatureState() throws RemoteException {
+ synchronized (mLock) {
+ try {
+ return MmTelFeature.this.getFeatureState();
+ } catch (Exception e) {
+ throw new RemoteException(e.getMessage());
+ }
+ }
+ }
+
+
+ @Override
+ public ImsCallProfile createCallProfile(int callSessionType, int callType)
+ throws RemoteException {
+ synchronized (mLock) {
+ try {
+ return MmTelFeature.this.createCallProfile(callSessionType, callType);
+ } catch (Exception e) {
+ throw new RemoteException(e.getMessage());
+ }
+ }
+ }
+
+ @Override
+ public IImsCallSession createCallSession(ImsCallProfile profile) throws RemoteException {
+ synchronized (mLock) {
+ return createCallSessionInterface(profile);
+ }
+ }
+
+ @Override
+ public int shouldProcessCall(String[] numbers) {
+ synchronized (mLock) {
+ return MmTelFeature.this.shouldProcessCall(numbers);
+ }
+ }
+
+ @Override
+ public IImsUt getUtInterface() throws RemoteException {
+ synchronized (mLock) {
+ return MmTelFeature.this.getUtInterface();
+ }
+ }
+
+ @Override
+ public IImsEcbm getEcbmInterface() throws RemoteException {
+ synchronized (mLock) {
+ return MmTelFeature.this.getEcbmInterface();
+ }
+ }
+
+ @Override
+ public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException {
+ synchronized (mLock) {
+ try {
+ MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage);
+ } catch (Exception e) {
+ throw new RemoteException(e.getMessage());
+ }
+ }
+ }
+
+ @Override
+ public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
+ synchronized (mLock) {
+ return MmTelFeature.this.getMultiEndpointInterface();
+ }
+ }
+
+ @Override
+ public int queryCapabilityStatus() throws RemoteException {
+ return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+ }
+
+ @Override
+ public void addCapabilityCallback(IImsCapabilityCallback c) {
+ MmTelFeature.this.addCapabilityCallback(c);
+ }
+
+ @Override
+ public void removeCapabilityCallback(IImsCapabilityCallback c) {
+ MmTelFeature.this.removeCapabilityCallback(c);
+ }
+
+ @Override
+ public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
+ IImsCapabilityCallback c) throws RemoteException {
+ MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+ }
+
+ @Override
+ public void queryCapabilityConfiguration(int capability, int radioTech,
+ IImsCapabilityCallback c) {
+ queryCapabilityConfigurationInternal(capability, radioTech, c);
+ }
+
+ @Override
+ public void setSmsListener(IImsSmsListener l) throws RemoteException {
+ MmTelFeature.this.setSmsListener(l);
+ }
+
+ @Override
+ public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
+ byte[] pdu) {
+ synchronized (mLock) {
+ MmTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
+ }
+ }
+
+ @Override
+ public void acknowledgeSms(int token, int messageRef, int result) {
+ synchronized (mLock) {
+ MmTelFeature.this.acknowledgeSms(token, messageRef, result);
+ }
+ }
+
+ @Override
+ public void acknowledgeSmsReport(int token, int messageRef, int result) {
+ synchronized (mLock) {
+ MmTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
+ }
+ }
+
+ @Override
+ public String getSmsFormat() {
+ synchronized (mLock) {
+ return MmTelFeature.this.getSmsFormat();
+ }
+ }
+
+ @Override
+ public void onSmsReady() {
+ synchronized (mLock) {
+ MmTelFeature.this.onSmsReady();
+ }
+ }
+ };
+
+ /**
+ * Contains the capabilities defined and supported by a MmTelFeature in the form of a Bitmask.
+ * The capabilities that are used in MmTelFeature are defined as
+ * {@link MmTelCapabilities#CAPABILITY_TYPE_VOICE},
+ * {@link MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
+ * {@link MmTelCapabilities#CAPABILITY_TYPE_UT}, and
+ * {@link MmTelCapabilities#CAPABILITY_TYPE_SMS}.
+ *
+ * The capabilities of this MmTelFeature will be set by the framework and can be queried with
+ * {@link #queryCapabilityStatus()}.
+ *
+ * This MmTelFeature can then return the status of each of these capabilities (enabled or not)
+ * by sending a {@link #notifyCapabilitiesStatusChanged} callback to the framework. The current
+ * status can also be queried using {@link #queryCapabilityStatus()}.
+ */
+ public static class MmTelCapabilities extends Capabilities {
+
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public MmTelCapabilities() {
+ super();
+ }
+
+ public MmTelCapabilities(Capabilities c) {
+ mCapabilities = c.mCapabilities;
+ }
+
+ public MmTelCapabilities(int capabilities) {
+ mCapabilities = capabilities;
+ }
+
+ @IntDef(flag = true,
+ value = {
+ CAPABILITY_TYPE_VOICE,
+ CAPABILITY_TYPE_VIDEO,
+ CAPABILITY_TYPE_UT,
+ CAPABILITY_TYPE_SMS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MmTelCapability {}
+
+ /**
+ * This MmTelFeature supports Voice calling (IR.92)
+ */
+ public static final int CAPABILITY_TYPE_VOICE = 1 << 0;
+
+ /**
+ * This MmTelFeature supports Video (IR.94)
+ */
+ public static final int CAPABILITY_TYPE_VIDEO = 1 << 1;
+
+ /**
+ * This MmTelFeature supports XCAP over Ut for supplementary services. (IR.92)
+ */
+ public static final int CAPABILITY_TYPE_UT = 1 << 2;
+
+ /**
+ * This MmTelFeature supports SMS (IR.92)
+ */
+ public static final int CAPABILITY_TYPE_SMS = 1 << 3;
+
+ @Override
+ public final void addCapabilities(@MmTelCapability int capabilities) {
+ super.addCapabilities(capabilities);
+ }
+
+ @Override
+ public final void removeCapabilities(@MmTelCapability int capability) {
+ super.removeCapabilities(capability);
+ }
+
+ @Override
+ public final boolean isCapable(@MmTelCapability int capabilities) {
+ return super.isCapable(capabilities);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("MmTel Capabilities - [");
+ builder.append("Voice: ");
+ builder.append(isCapable(CAPABILITY_TYPE_VOICE));
+ builder.append(" Video: ");
+ builder.append(isCapable(CAPABILITY_TYPE_VIDEO));
+ builder.append(" UT: ");
+ builder.append(isCapable(CAPABILITY_TYPE_UT));
+ builder.append(" SMS: ");
+ builder.append(isCapable(CAPABILITY_TYPE_SMS));
+ builder.append("]");
+ return builder.toString();
+ }
+ }
+
+ /**
+ * Listener that the framework implements for communication from the MmTelFeature.
+ * @hide
+ */
+ public static class Listener extends IImsMmTelListener.Stub {
+
+ /**
+ * Called when the IMS provider receives an incoming call.
+ * @param c The {@link ImsCallSession} associated with the new call.
+ */
+ @Override
+ public void onIncomingCall(IImsCallSession c, Bundle extras) {
+
+ }
+
+ /**
+ * Updates the Listener when the voice message count for IMS has changed.
+ * @param count an integer representing the new message count.
+ */
+ @Override
+ public void onVoiceMessageCountUpdate(int count) {
+
+ }
+ }
+
+ /**
+ * To be returned by {@link #shouldProcessCall(String[])} when the ImsService should process the
+ * outgoing call as IMS.
+ */
+ public static final int PROCESS_CALL_IMS = 0;
+ /**
+ * To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should
+ * not process the outgoing NON_EMERGENCY call as IMS and should instead use circuit switch.
+ */
+ public static final int PROCESS_CALL_CSFB = 1;
+ /**
+ * To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should
+ * not process the outgoing EMERGENCY call as IMS and should instead use circuit switch.
+ */
+ public static final int PROCESS_CALL_EMERGENCY_CSFB = 2;
+
+ @IntDef(flag = true,
+ value = {
+ PROCESS_CALL_IMS,
+ PROCESS_CALL_CSFB,
+ PROCESS_CALL_EMERGENCY_CSFB
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ProcessCallResult {}
+
+
+ // Lock for feature synchronization
+ private final Object mLock = new Object();
+ private IImsMmTelListener mListener;
+
+ /**
+ * @param listener A {@link Listener} used when the MmTelFeature receives an incoming call and
+ * notifies the framework.
+ */
+ private void setListener(IImsMmTelListener listener) {
+ synchronized (mLock) {
+ mListener = listener;
+ }
+ if (mListener != null) {
+ onFeatureReady();
+ }
+ }
+
+ private void queryCapabilityConfigurationInternal(int capability, int radioTech,
+ IImsCapabilityCallback c) {
+ boolean enabled = queryCapabilityConfiguration(capability, radioTech);
+ try {
+ if (c != null) {
+ c.onQueryCapabilityConfiguration(capability, radioTech, enabled);
+ }
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "queryCapabilityConfigurationInternal called on dead binder!");
+ }
+ }
+
+ /**
+ * The current capability status that this MmTelFeature has defined is available. This
+ * configuration will be used by the platform to figure out which capabilities are CURRENTLY
+ * available to be used.
+ *
+ * Should be a subset of the capabilities that are enabled by the framework in
+ * {@link #changeEnabledCapabilities}.
+ * @return A copy of the current MmTelFeature capability status.
+ */
+ @Override
+ public final MmTelCapabilities queryCapabilityStatus() {
+ return new MmTelCapabilities(super.queryCapabilityStatus());
+ }
+
+ /**
+ * Notify the framework that the status of the Capabilities has changed. Even though the
+ * MmTelFeature capability may be enabled by the framework, the status may be disabled due to
+ * the feature being unavailable from the network.
+ * @param c The current capability status of the MmTelFeature. If a capability is disabled, then
+ * the status of that capability is disabled. This can happen if the network does not currently
+ * support the capability that is enabled. A capability that is disabled by the framework (via
+ * {@link #changeEnabledCapabilities}) should also show the status as disabled.
+ */
+ public final void notifyCapabilitiesStatusChanged(MmTelCapabilities c) {
+ super.notifyCapabilitiesStatusChanged(c);
+ }
+
+ /**
+ * Notify the framework of an incoming call.
+ * @param c The {@link ImsCallSessionImplBase} of the new incoming call.
+ */
+ public final void notifyIncomingCall(ImsCallSessionImplBase c, Bundle extras) {
+ synchronized (mLock) {
+ if (mListener == null) {
+ throw new IllegalStateException("Session is not available.");
+ }
+ try {
+ mListener.onIncomingCall(c.getServiceImpl(), extras);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ *
+ * @hide
+ */
+ public final void notifyIncomingCallSession(IImsCallSession c, Bundle extras) {
+ synchronized (mLock) {
+ if (mListener == null) {
+ throw new IllegalStateException("Session is not available.");
+ }
+ try {
+ mListener.onIncomingCall(c, extras);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Notify the framework of a change in the Voice Message count.
+ * @link count the new Voice Message count.
+ */
+ public final void notifyVoiceMessageCountUpdate(int count) {
+ synchronized (mLock) {
+ if (mListener == null) {
+ throw new IllegalStateException("Session is not available.");
+ }
+ try {
+ mListener.onVoiceMessageCountUpdate(count);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Provides the MmTelFeature with the ability to return the framework Capability Configuration
+ * for a provided Capability. If the framework calls {@link #changeEnabledCapabilities} and
+ * includes a capability A to enable or disable, this method should return the correct enabled
+ * status for capability A.
+ * @param capability The capability that we are querying the configuration for.
+ * @return true if the capability is enabled, false otherwise.
+ */
+ public boolean queryCapabilityConfiguration(@MmTelCapabilities.MmTelCapability int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
+ // Base implementation - Override to provide functionality
+ return false;
+ }
+
+ /**
+ * The MmTelFeature should override this method to handle the enabling/disabling of
+ * MmTel Features, defined in {@link MmTelCapabilities.MmTelCapability}. The framework assumes
+ * the {@link CapabilityChangeRequest} was processed successfully. If a subset of capabilities
+ * could not be set to their new values,
+ * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} must be called
+ * individually for each capability whose processing resulted in an error.
+ *
+ * Enabling/Disabling a capability here indicates that the capability should be registered or
+ * deregistered (depending on the capability change) and become available or unavailable to
+ * the framework.
+ */
+ @Override
+ public void changeEnabledCapabilities(CapabilityChangeRequest request,
+ CapabilityCallbackProxy c) {
+ // Base implementation, no-op
+ }
+
+ /**
+ * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
+ *
+ * @param callSessionType a service type that is specified in {@link ImsCallProfile}
+ * {@link ImsCallProfile#SERVICE_TYPE_NONE}
+ * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
+ * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
+ * @param callType a call type that is specified in {@link ImsCallProfile}
+ * {@link ImsCallProfile#CALL_TYPE_VOICE}
+ * {@link ImsCallProfile#CALL_TYPE_VT}
+ * {@link ImsCallProfile#CALL_TYPE_VT_TX}
+ * {@link ImsCallProfile#CALL_TYPE_VT_RX}
+ * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
+ * {@link ImsCallProfile#CALL_TYPE_VS}
+ * {@link ImsCallProfile#CALL_TYPE_VS_TX}
+ * {@link ImsCallProfile#CALL_TYPE_VS_RX}
+ * @return a {@link ImsCallProfile} object
+ */
+ public ImsCallProfile createCallProfile(int callSessionType, int callType) {
+ // Base Implementation - Should be overridden
+ return null;
+ }
+
+ /**
+ * @hide
+ */
+ public IImsCallSession createCallSessionInterface(ImsCallProfile profile)
+ throws RemoteException {
+ ImsCallSessionImplBase s = MmTelFeature.this.createCallSession(profile);
+ return s != null ? s.getServiceImpl() : null;
+ }
+
+ /**
+ * Creates an {@link ImsCallSession} with the specified call profile.
+ * Use other methods, if applicable, instead of interacting with
+ * {@link ImsCallSession} directly.
+ *
+ * @param profile a call profile to make the call
+ */
+ public ImsCallSessionImplBase createCallSession(ImsCallProfile profile) {
+ // Base Implementation - Should be overridden
+ return null;
+ }
+
+ /**
+ * Called by the framework to determine if the outgoing call, designated by the outgoing
+ * {@link Uri}s, should be processed as an IMS call or CSFB call.
+ * @param numbers An array of {@link String}s that will be used for placing the call. There can
+ * be multiple {@link String}s listed in the case when we want to place an outgoing
+ * call as a conference.
+ * @return a {@link ProcessCallResult} to the framework, which will be used to determine if the
+ * call wil lbe placed over IMS or via CSFB.
+ */
+ public @ProcessCallResult int shouldProcessCall(String[] numbers) {
+ return PROCESS_CALL_IMS;
+ }
+
+ /**
+ *
+ * @hide
+ */
+ protected IImsUt getUtInterface() throws RemoteException {
+ ImsUtImplBase utImpl = getUt();
+ return utImpl != null ? utImpl.getInterface() : null;
+ }
+
+ /**
+ * @hide
+ */
+ protected IImsEcbm getEcbmInterface() throws RemoteException {
+ ImsEcbmImplBase ecbmImpl = getEcbm();
+ return ecbmImpl != null ? ecbmImpl.getImsEcbm() : null;
+ }
+
+ /**
+ * @hide
+ */
+ public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
+ ImsMultiEndpointImplBase multiendpointImpl = getMultiEndpoint();
+ return multiendpointImpl != null ? multiendpointImpl.getIImsMultiEndpoint() : null;
+ }
+
+ /**
+ * @return The {@link ImsUtImplBase} Ut interface implementation for the supplementary service
+ * configuration.
+ */
+ public ImsUtImplBase getUt() {
+ // Base Implementation - Should be overridden
+ return null;
+ }
+
+ /**
+ * @return The {@link ImsEcbmImplBase} Emergency call-back mode interface for emergency VoLTE
+ * calls that support it.
+ */
+ public ImsEcbmImplBase getEcbm() {
+ // Base Implementation - Should be overridden
+ return null;
+ }
+
+ /**
+ * @return The {@link ImsMultiEndpointImplBase} implementation for implementing Dialog event
+ * package processing for multi-endpoint.
+ */
+ public ImsMultiEndpointImplBase getMultiEndpoint() {
+ // Base Implementation - Should be overridden
+ return null;
+ }
+
+ /**
+ * Sets the current UI TTY mode for the MmTelFeature.
+ * @param mode An integer containing the new UI TTY Mode, can consist of
+ * {@link TelecomManager#TTY_MODE_OFF},
+ * {@link TelecomManager#TTY_MODE_FULL},
+ * {@link TelecomManager#TTY_MODE_HCO},
+ * {@link TelecomManager#TTY_MODE_VCO}
+ * @param onCompleteMessage A {@link Message} to be used when the mode has been set.
+ */
+ public void setUiTtyMode(int mode, Message onCompleteMessage) {
+ // Base Implementation - Should be overridden
+ }
+
+ private void setSmsListener(IImsSmsListener listener) {
+ getSmsImplementation().registerSmsListener(listener);
+ }
+
+ private void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
+ byte[] pdu) {
+ getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu);
+ }
+
+ private void acknowledgeSms(int token, int messageRef,
+ @ImsSmsImplBase.DeliverStatusResult int result) {
+ getSmsImplementation().acknowledgeSms(token, messageRef, result);
+ }
+
+ private void acknowledgeSmsReport(int token, int messageRef,
+ @ImsSmsImplBase.StatusReportResult int result) {
+ getSmsImplementation().acknowledgeSmsReport(token, messageRef, result);
+ }
+
+ private void onSmsReady() {
+ getSmsImplementation().onReady();
+ }
+
+ /**
+ * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default
+ * non-functional implementation is returned.
+ *
+ * @return an instance of {@link ImsSmsImplBase} which should be implemented by the IMS
+ * Provider.
+ */
+ public ImsSmsImplBase getSmsImplementation() {
+ return new ImsSmsImplBase();
+ }
+
+ private String getSmsFormat() {
+ return getSmsImplementation().getSmsFormat();
+ }
+
+ /**{@inheritDoc}*/
+ @Override
+ public void onFeatureRemoved() {
+ // Base Implementation - Should be overridden
+ }
+
+ /**{@inheritDoc}*/
+ @Override
+ public void onFeatureReady() {
+ // Base Implementation - Should be overridden
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public final IImsMmTelFeature getBinder() {
+ return mImsMMTelBinder;
+ }
+}
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 40c5181..a637e16 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 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.
@@ -16,16 +16,18 @@
package android.telephony.ims.feature;
-import com.android.ims.internal.IImsRcsFeature;
+import android.annotation.SystemApi;
+import android.telephony.ims.aidl.IImsRcsFeature;
/**
* Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend
* this class and provide implementations of the RcsFeature methods that they support.
* @hide
*/
-
+@SystemApi
public class RcsFeature extends ImsFeature {
+ /**{@inheritDoc}*/
private final IImsRcsFeature mImsRcsBinder = new IImsRcsFeature.Stub() {
// Empty Default Implementation.
};
@@ -35,16 +37,30 @@
super();
}
+ /**
+ * {@inheritDoc}
+ */
@Override
- public void onFeatureReady() {
-
+ public void changeEnabledCapabilities(CapabilityChangeRequest request,
+ CapabilityCallbackProxy c) {
+ // Do nothing for base implementation.
}
+ /**{@inheritDoc}*/
@Override
public void onFeatureRemoved() {
}
+ /**{@inheritDoc}*/
+ @Override
+ public void onFeatureReady() {
+
+ }
+
+ /**
+ * @hide
+ */
@Override
public final IImsRcsFeature getBinder() {
return mImsRcsBinder;
diff --git a/telephony/java/android/telephony/ims/internal/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/internal/ImsCallSessionListener.java
deleted file mode 100644
index 5d16dd5..0000000
--- a/telephony/java/android/telephony/ims/internal/ImsCallSessionListener.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.telephony.ims.internal;
-
-import android.os.RemoteException;
-import android.telephony.ims.internal.aidl.IImsCallSessionListener;
-
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsConferenceState;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.ImsSuppServiceNotification;
-import com.android.ims.internal.ImsCallSession;
-
-/**
- * Proxy class for interfacing with the framework's Call session for an ongoing IMS call.
- *
- * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
- * will break other implementations of ImsCallSessionListener maintained by other ImsServices.
- *
- * @hide
- */
-public class ImsCallSessionListener {
-
- private final IImsCallSessionListener mListener;
-
- public ImsCallSessionListener(IImsCallSessionListener l) {
- mListener = l;
- }
-
- /**
- * Called when a request is sent out to initiate a new session
- * and 1xx response is received from the network.
- */
- public void callSessionProgressing(ImsStreamMediaProfile profile)
- throws RemoteException {
- mListener.callSessionProgressing(profile);
- }
-
- /**
- * Called when the session is initiated.
- *
- * @param profile the associated {@link ImsCallSession}.
- */
- public void callSessionInitiated(ImsCallProfile profile) throws RemoteException {
- mListener.callSessionInitiated(profile);
- }
-
- /**
- * Called when the session establishment has failed.
- *
- * @param reasonInfo detailed reason of the session establishment failure
- */
- public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) throws RemoteException {
- mListener.callSessionInitiatedFailed(reasonInfo);
- }
-
- /**
- * Called when the session is terminated.
- *
- * @param reasonInfo detailed reason of the session termination
- */
- public void callSessionTerminated(ImsReasonInfo reasonInfo) throws RemoteException {
- mListener.callSessionTerminated(reasonInfo);
- }
-
- /**
- * Called when the session is on hold.
- */
- public void callSessionHeld(ImsCallProfile profile) throws RemoteException {
- mListener.callSessionHeld(profile);
- }
-
- /**
- * Called when the session hold has failed.
- *
- * @param reasonInfo detailed reason of the session hold failure
- */
- public void callSessionHoldFailed(ImsReasonInfo reasonInfo) throws RemoteException {
- mListener.callSessionHoldFailed(reasonInfo);
- }
-
- /**
- * Called when the session hold is received from the remote user.
- */
- public void callSessionHoldReceived(ImsCallProfile profile) throws RemoteException {
- mListener.callSessionHoldReceived(profile);
- }
-
- /**
- * Called when the session resume is done.
- */
- public void callSessionResumed(ImsCallProfile profile) throws RemoteException {
- mListener.callSessionResumed(profile);
- }
-
- /**
- * Called when the session resume has failed.
- *
- * @param reasonInfo detailed reason of the session resume failure
- */
- public void callSessionResumeFailed(ImsReasonInfo reasonInfo) throws RemoteException {
- mListener.callSessionResumeFailed(reasonInfo);
- }
-
- /**
- * Called when the session resume is received from the remote user.
- */
- public void callSessionResumeReceived(ImsCallProfile profile) throws RemoteException {
- mListener.callSessionResumeReceived(profile);
- }
-
- /**
- * Called when the session merge has been started. At this point, the {@code newSession}
- * represents the session which has been initiated to the IMS conference server for the
- * new merged conference.
- *
- * @param newSession the session object that is merged with an active & hold session
- */
- public void callSessionMergeStarted(ImsCallSession newSession, ImsCallProfile profile)
- throws RemoteException {
- mListener.callSessionMergeStarted(newSession != null ? newSession.getSession() : null,
- profile);
- }
-
- /**
- * Called when the session merge is successful and the merged session is active.
- *
- * @param newSession the new session object that is used for the conference
- */
- public void callSessionMergeComplete(ImsCallSession newSession) throws RemoteException {
- mListener.callSessionMergeComplete(newSession != null ? newSession.getSession() : null);
- }
-
- /**
- * Called when the session merge has failed.
- *
- * @param reasonInfo detailed reason of the call merge failure
- */
- public void callSessionMergeFailed(ImsReasonInfo reasonInfo) throws RemoteException {
- mListener.callSessionMergeFailed(reasonInfo);
- }
-
- /**
- * Called when the session is updated (except for hold/unhold).
- */
- public void callSessionUpdated(ImsCallProfile profile) throws RemoteException {
- mListener.callSessionUpdated(profile);
- }
-
- /**
- * Called when the session update has failed.
- *
- * @param reasonInfo detailed reason of the session update failure
- */
- public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) throws RemoteException {
- mListener.callSessionUpdateFailed(reasonInfo);
- }
-
- /**
- * Called when the session update is received from the remote user.
- */
- public void callSessionUpdateReceived(ImsCallProfile profile) throws RemoteException {
- mListener.callSessionUpdateReceived(profile);
- }
-
- /**
- * Called when the session has been extended to a conference session.
- *
- * @param newSession the session object that is extended to the conference
- * from the active session
- */
- public void callSessionConferenceExtended(ImsCallSession newSession, ImsCallProfile profile)
- throws RemoteException {
- mListener.callSessionConferenceExtended(newSession != null ? newSession.getSession() : null,
- profile);
- }
-
- /**
- * Called when the conference extension has failed.
- *
- * @param reasonInfo detailed reason of the conference extension failure
- */
- public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) throws RemoteException {
- mListener.callSessionConferenceExtendFailed(reasonInfo);
- }
-
- /**
- * Called when the conference extension is received from the remote user.
- */
- public void callSessionConferenceExtendReceived(ImsCallSession newSession,
- ImsCallProfile profile) throws RemoteException {
- mListener.callSessionConferenceExtendReceived(newSession != null
- ? newSession.getSession() : null, profile);
- }
-
- /**
- * Called when the invitation request of the participants is delivered to the conference
- * server.
- */
- public void callSessionInviteParticipantsRequestDelivered() throws RemoteException {
- mListener.callSessionInviteParticipantsRequestDelivered();
- }
-
- /**
- * Called when the invitation request of the participants has failed.
- *
- * @param reasonInfo detailed reason of the conference invitation failure
- */
- public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo)
- throws RemoteException {
- mListener.callSessionInviteParticipantsRequestFailed(reasonInfo);
- }
-
- /**
- * Called when the removal request of the participants is delivered to the conference
- * server.
- */
- public void callSessionRemoveParticipantsRequestDelivered() throws RemoteException {
- mListener.callSessionRemoveParticipantsRequestDelivered();
- }
-
- /**
- * Called when the removal request of the participants has failed.
- *
- * @param reasonInfo detailed reason of the conference removal failure
- */
- public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo)
- throws RemoteException {
- mListener.callSessionInviteParticipantsRequestFailed(reasonInfo);
- }
-
- /**
- * Notifies the framework of the updated Call session conference state.
- *
- * @param state the new {@link ImsConferenceState} associated with the conference.
- */
- public void callSessionConferenceStateUpdated(ImsConferenceState state) throws RemoteException {
- mListener.callSessionConferenceStateUpdated(state);
- }
-
- /**
- * Notifies the incoming USSD message.
- */
- public void callSessionUssdMessageReceived(int mode, String ussdMessage)
- throws RemoteException {
- mListener.callSessionUssdMessageReceived(mode, ussdMessage);
- }
-
- /**
- * Notifies of a case where a {@link com.android.ims.internal.ImsCallSession} may potentially
- * handover from one radio technology to another.
- *
- * @param srcAccessTech The source radio access technology; one of the access technology
- * constants defined in {@link android.telephony.ServiceState}. For
- * example
- * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
- * @param targetAccessTech The target radio access technology; one of the access technology
- * constants defined in {@link android.telephony.ServiceState}. For
- * example
- * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
- */
- public void callSessionMayHandover(int srcAccessTech, int targetAccessTech)
- throws RemoteException {
- mListener.callSessionMayHandover(srcAccessTech, targetAccessTech);
- }
-
- /**
- * Called when session access technology changes.
- *
- * @param srcAccessTech original access technology
- * @param targetAccessTech new access technology
- * @param reasonInfo
- */
- public void callSessionHandover(int srcAccessTech, int targetAccessTech,
- ImsReasonInfo reasonInfo) throws RemoteException {
- mListener.callSessionHandover(srcAccessTech, targetAccessTech, reasonInfo);
- }
-
- /**
- * Called when session access technology change fails.
- *
- * @param srcAccessTech original access technology
- * @param targetAccessTech new access technology
- * @param reasonInfo handover failure reason
- */
- public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
- ImsReasonInfo reasonInfo) throws RemoteException {
- mListener.callSessionHandoverFailed(srcAccessTech, targetAccessTech, reasonInfo);
- }
-
- /**
- * Called when the TTY mode is changed by the remote party.
- *
- * @param mode one of the following: -
- * {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} -
- * {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} -
- * {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} -
- * {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
- */
- public void callSessionTtyModeReceived(int mode) throws RemoteException {
- mListener.callSessionTtyModeReceived(mode);
- }
-
- /**
- * Called when the multiparty state is changed for this {@code ImsCallSession}.
- *
- * @param isMultiParty {@code true} if the session became multiparty,
- * {@code false} otherwise.
- */
-
- public void callSessionMultipartyStateChanged(boolean isMultiParty) throws RemoteException {
- mListener.callSessionMultipartyStateChanged(isMultiParty);
- }
-
- /**
- * Called when the supplementary service information is received for the current session.
- */
- public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppSrvNotification)
- throws RemoteException {
- mListener.callSessionSuppServiceReceived(suppSrvNotification);
- }
-
- /**
- * Received RTT modify request from the remote party.
- *
- * @param callProfile ImsCallProfile with updated attributes
- */
- public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile)
- throws RemoteException {
- mListener.callSessionRttModifyRequestReceived(callProfile);
- }
-
- /**
- * @param status the received response for RTT modify request.
- */
- public void callSessionRttModifyResponseReceived(int status) throws RemoteException {
- mListener.callSessionRttModifyResponseReceived(status);
- }
-
- /**
- * Device received RTT message from Remote UE.
- *
- * @param rttMessage RTT message received
- */
- public void callSessionRttMessageReceived(String rttMessage) throws RemoteException {
- mListener.callSessionRttMessageReceived(rttMessage);
- }
-}
-
diff --git a/telephony/java/android/telephony/ims/internal/ImsService.java b/telephony/java/android/telephony/ims/internal/ImsService.java
deleted file mode 100644
index afaf332..0000000
--- a/telephony/java/android/telephony/ims/internal/ImsService.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.telephony.ims.internal;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.telephony.CarrierConfigManager;
-import android.telephony.ims.internal.aidl.IImsConfig;
-import android.telephony.ims.internal.aidl.IImsMmTelFeature;
-import android.telephony.ims.internal.aidl.IImsRcsFeature;
-import android.telephony.ims.internal.aidl.IImsServiceController;
-import android.telephony.ims.internal.aidl.IImsServiceControllerListener;
-import android.telephony.ims.internal.feature.ImsFeature;
-import android.telephony.ims.internal.feature.MmTelFeature;
-import android.telephony.ims.internal.feature.RcsFeature;
-import android.telephony.ims.internal.stub.ImsConfigImplBase;
-import android.telephony.ims.internal.stub.ImsFeatureConfiguration;
-import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.ims.internal.IImsFeatureStatusCallback;
-import com.android.ims.internal.IImsRegistration;
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
- * ImsService must register the service in their AndroidManifest to be detected by the framework.
- * First, the application must declare that they use the "android.permission.BIND_IMS_SERVICE"
- * permission. Then, the ImsService definition in the manifest must follow the following format:
- *
- * ...
- * <service android:name=".EgImsService"
- * android:permission="android.permission.BIND_IMS_SERVICE" >
- * <!-- Apps must declare which features they support as metadata. The different categories are
- * defined below. In this example, the RCS_FEATURE feature is supported. -->
- * <meta-data android:name="android.telephony.ims.RCS_FEATURE" android:value="true" />
- * <intent-filter>
- * <action android:name="android.telephony.ims.ImsService" />
- * </intent-filter>
- * </service>
- * ...
- *
- * The telephony framework will then bind to the ImsService you have defined in your manifest
- * if you are either:
- * 1) Defined as the default ImsService for the device in the device overlay using
- * "config_ims_package".
- * 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using
- * {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}.
- *
- * The features that are currently supported in an ImsService are:
- * - RCS_FEATURE: This ImsService implements the RcsFeature class.
- * - MMTEL_FEATURE: This ImsService implements the MmTelFeature class.
- * @hide
- */
-public class ImsService extends Service {
-
- private static final String LOG_TAG = "ImsService";
-
- /**
- * The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService.
- * @hide
- */
- public static final String SERVICE_INTERFACE = "android.telephony.ims.ImsService";
-
- // A map of slot Id -> map of features (indexed by ImsFeature feature id) corresponding to that
- // slot.
- // We keep track of this to facilitate cleanup of the IImsFeatureStatusCallback and
- // call ImsFeature#onFeatureRemoved.
- private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
-
- private IImsServiceControllerListener mListener;
-
-
- /**
- * Listener that notifies the framework of ImsService changes.
- */
- public static class Listener extends IImsServiceControllerListener.Stub {
- /**
- * The IMS features that this ImsService supports has changed.
- * @param c a new {@link ImsFeatureConfiguration} containing {@link ImsFeature.FeatureType}s
- * that this ImsService supports. This may trigger the addition/removal of feature
- * in this service.
- */
- public void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c) {
- }
- }
-
- /**
- * @hide
- */
- protected final IBinder mImsServiceController = new IImsServiceController.Stub() {
- @Override
- public void setListener(IImsServiceControllerListener l) {
- mListener = l;
- }
-
- @Override
- public IImsMmTelFeature createMmTelFeature(int slotId, IImsFeatureStatusCallback c) {
- return createMmTelFeatureInternal(slotId, c);
- }
-
- @Override
- public IImsRcsFeature createRcsFeature(int slotId, IImsFeatureStatusCallback c) {
- return createRcsFeatureInternal(slotId, c);
- }
-
- @Override
- public void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
- throws RemoteException {
- ImsService.this.removeImsFeature(slotId, featureType, c);
- }
-
- @Override
- public ImsFeatureConfiguration querySupportedImsFeatures() {
- return ImsService.this.querySupportedImsFeatures();
- }
-
- @Override
- public void notifyImsServiceReadyForFeatureCreation() {
- ImsService.this.readyForFeatureCreation();
- }
-
- @Override
- public void notifyImsFeatureReady(int slotId, int featureType)
- throws RemoteException {
- ImsService.this.notifyImsFeatureReady(slotId, featureType);
- }
-
- @Override
- public IImsConfig getConfig(int slotId) throws RemoteException {
- ImsConfigImplBase c = ImsService.this.getConfig(slotId);
- return c != null ? c.getBinder() : null;
- }
-
- @Override
- public IImsRegistration getRegistration(int slotId) throws RemoteException {
- ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId);
- return r != null ? r.getBinder() : null;
- }
- };
-
- /**
- * @hide
- */
- @Override
- public IBinder onBind(Intent intent) {
- if(SERVICE_INTERFACE.equals(intent.getAction())) {
- Log.i(LOG_TAG, "ImsService Bound.");
- return mImsServiceController;
- }
- return null;
- }
-
- /**
- * @hide
- */
- @VisibleForTesting
- public SparseArray<ImsFeature> getFeatures(int slotId) {
- return mFeaturesBySlot.get(slotId);
- }
-
- private IImsMmTelFeature createMmTelFeatureInternal(int slotId,
- IImsFeatureStatusCallback c) {
- MmTelFeature f = createMmTelFeature(slotId);
- if (f != null) {
- setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL, c);
- return f.getBinder();
- } else {
- Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned.");
- return null;
- }
- }
-
- private IImsRcsFeature createRcsFeatureInternal(int slotId,
- IImsFeatureStatusCallback c) {
- RcsFeature f = createRcsFeature(slotId);
- if (f != null) {
- setupFeature(f, slotId, ImsFeature.FEATURE_RCS, c);
- return f.getBinder();
- } else {
- Log.e(LOG_TAG, "createRcsFeatureInternal: null feature returned.");
- return null;
- }
- }
-
- private void setupFeature(ImsFeature f, int slotId, int featureType,
- IImsFeatureStatusCallback c) {
- f.addImsFeatureStatusCallback(c);
- f.initialize(this, slotId);
- addImsFeature(slotId, featureType, f);
- }
-
- private void addImsFeature(int slotId, int featureType, ImsFeature f) {
- synchronized (mFeaturesBySlot) {
- // Get SparseArray for Features, by querying slot Id
- SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
- if (features == null) {
- // Populate new SparseArray of features if it doesn't exist for this slot yet.
- features = new SparseArray<>();
- mFeaturesBySlot.put(slotId, features);
- }
- features.put(featureType, f);
- }
- }
-
- private void removeImsFeature(int slotId, int featureType,
- IImsFeatureStatusCallback c) {
- synchronized (mFeaturesBySlot) {
- // get ImsFeature associated with the slot/feature
- SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
- if (features == null) {
- Log.w(LOG_TAG, "Can not remove ImsFeature. No ImsFeatures exist on slot "
- + slotId);
- return;
- }
- ImsFeature f = features.get(featureType);
- if (f == null) {
- Log.w(LOG_TAG, "Can not remove ImsFeature. No feature with type "
- + featureType + " exists on slot " + slotId);
- return;
- }
- f.removeImsFeatureStatusCallback(c);
- f.onFeatureRemoved();
- features.remove(featureType);
- }
- }
-
- private void notifyImsFeatureReady(int slotId, int featureType) {
- synchronized (mFeaturesBySlot) {
- // get ImsFeature associated with the slot/feature
- SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
- if (features == null) {
- Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " +
- "slot " + slotId);
- return;
- }
- ImsFeature f = features.get(featureType);
- if (f == null) {
- Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type "
- + featureType + " exists on slot " + slotId);
- return;
- }
- f.onFeatureReady();
- }
- }
-
- /**
- * When called, provide the {@link ImsFeatureConfiguration} that this ImsService currently
- * supports. This will trigger the framework to set up the {@link ImsFeature}s that correspond
- * to the {@link ImsFeature.FeatureType}s configured here.
- * @return an {@link ImsFeatureConfiguration} containing Features this ImsService supports,
- * defined in {@link ImsFeature.FeatureType}.
- */
- public ImsFeatureConfiguration querySupportedImsFeatures() {
- // Return empty for base implementation
- return new ImsFeatureConfiguration();
- }
-
- /**
- * Updates the framework with a new {@link ImsFeatureConfiguration} containing the updated
- * features, defined in {@link ImsFeature.FeatureType} that this ImsService supports. This may
- * trigger the framework to add/remove new ImsFeatures, depending on the configuration.
- */
- public final void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c)
- throws RemoteException {
- if (mListener == null) {
- throw new IllegalStateException("Framework is not ready");
- }
- mListener.onUpdateSupportedImsFeatures(c);
- }
-
- /**
- * The ImsService has been bound and is ready for ImsFeature creation based on the Features that
- * the ImsService has registered for with the framework, either in the manifest or via
- * The ImsService should use this signal instead of onCreate/onBind or similar to perform
- * feature initialization because the framework may bind to this service multiple times to
- * query the ImsService's {@link ImsFeatureConfiguration} via
- * {@link #querySupportedImsFeatures()}before creating features.
- */
- public void readyForFeatureCreation() {
- }
-
- /**
- * When called, the framework is requesting that a new MmTelFeature is created for the specified
- * slot.
- *
- * @param slotId The slot ID that the MMTel Feature is being created for.
- * @return The newly created MmTelFeature associated with the slot or null if the feature is not
- * supported.
- */
- public MmTelFeature createMmTelFeature(int slotId) {
- return null;
- }
-
- /**
- * When called, the framework is requesting that a new RcsFeature is created for the specified
- * slot
- *
- * @param slotId The slot ID that the RCS Feature is being created for.
- * @return The newly created RcsFeature associated with the slot or null if the feature is not
- * supported.
- */
- public RcsFeature createRcsFeature(int slotId) {
- return null;
- }
-
- /**
- * @param slotId The slot that the IMS configuration is associated with.
- * @return ImsConfig implementation that is associated with the specified slot.
- */
- public ImsConfigImplBase getConfig(int slotId) {
- return new ImsConfigImplBase();
- }
-
- /**
- * @param slotId The slot that is associated with the IMS Registration.
- * @return the ImsRegistration implementation associated with the slot.
- */
- public ImsRegistrationImplBase getRegistration(int slotId) {
- return new ImsRegistrationImplBase();
- }
-}
diff --git a/telephony/java/android/telephony/ims/internal/feature/ImsFeature.java b/telephony/java/android/telephony/ims/internal/feature/ImsFeature.java
deleted file mode 100644
index 9f82ad2..0000000
--- a/telephony/java/android/telephony/ims/internal/feature/ImsFeature.java
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.telephony.ims.internal.feature;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.content.Context;
-import android.content.Intent;
-import android.os.IInterface;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.telephony.SubscriptionManager;
-import android.telephony.ims.internal.aidl.IImsCapabilityCallback;
-import android.util.Log;
-
-import com.android.ims.internal.IImsFeatureStatusCallback;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-/**
- * Base class for all IMS features that are supported by the framework.
- *
- * @hide
- */
-public abstract class ImsFeature {
-
- private static final String LOG_TAG = "ImsFeature";
-
- /**
- * Action to broadcast when ImsService is up.
- * Internal use only.
- * Only defined here separately for compatibility purposes with the old ImsService.
- *
- * @hide
- */
- public static final String ACTION_IMS_SERVICE_UP =
- "com.android.ims.IMS_SERVICE_UP";
-
- /**
- * Action to broadcast when ImsService is down.
- * Internal use only.
- * Only defined here separately for compatibility purposes with the old ImsService.
- *
- * @hide
- */
- public static final String ACTION_IMS_SERVICE_DOWN =
- "com.android.ims.IMS_SERVICE_DOWN";
-
- /**
- * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
- * A long value; the phone ID corresponding to the IMS service coming up or down.
- * Only defined here separately for compatibility purposes with the old ImsService.
- *
- * @hide
- */
- public static final String EXTRA_PHONE_ID = "android:phone_id";
-
- // Invalid feature value
- public static final int FEATURE_INVALID = -1;
- // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
- // defined values in ImsServiceClass for compatibility purposes.
- public static final int FEATURE_EMERGENCY_MMTEL = 0;
- public static final int FEATURE_MMTEL = 1;
- public static final int FEATURE_RCS = 2;
- // Total number of features defined
- public static final int FEATURE_MAX = 3;
-
- // Integer values defining IMS features that are supported in ImsFeature.
- @IntDef(flag = true,
- value = {
- FEATURE_EMERGENCY_MMTEL,
- FEATURE_MMTEL,
- FEATURE_RCS
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface FeatureType {}
-
- // Integer values defining the state of the ImsFeature at any time.
- @IntDef(flag = true,
- value = {
- STATE_UNAVAILABLE,
- STATE_INITIALIZING,
- STATE_READY,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ImsState {}
-
- public static final int STATE_UNAVAILABLE = 0;
- public static final int STATE_INITIALIZING = 1;
- public static final int STATE_READY = 2;
-
- // Integer values defining the result codes that should be returned from
- // {@link changeEnabledCapabilities} when the framework tries to set a feature's capability.
- @IntDef(flag = true,
- value = {
- CAPABILITY_ERROR_GENERIC,
- CAPABILITY_SUCCESS
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ImsCapabilityError {}
-
- public static final int CAPABILITY_ERROR_GENERIC = -1;
- public static final int CAPABILITY_SUCCESS = 0;
-
-
- /**
- * The framework implements this callback in order to register for Feature Capability status
- * updates, via {@link #onCapabilitiesStatusChanged(Capabilities)}, query Capability
- * configurations, via {@link #onQueryCapabilityConfiguration}, as well as to receive error
- * callbacks when the ImsService can not change the capability as requested, via
- * {@link #onChangeCapabilityConfigurationError}.
- */
- public static class CapabilityCallback extends IImsCapabilityCallback.Stub {
-
- @Override
- public final void onCapabilitiesStatusChanged(int config) throws RemoteException {
- onCapabilitiesStatusChanged(new Capabilities(config));
- }
-
- /**
- * Returns the result of a query for the capability configuration of a requested capability.
- *
- * @param capability The capability that was requested.
- * @param radioTech The IMS radio technology associated with the capability.
- * @param isEnabled true if the capability is enabled, false otherwise.
- */
- @Override
- public void onQueryCapabilityConfiguration(int capability, int radioTech,
- boolean isEnabled) {
-
- }
-
- /**
- * Called when a change to the capability configuration has returned an error.
- *
- * @param capability The capability that was requested to be changed.
- * @param radioTech The IMS radio technology associated with the capability.
- * @param reason error associated with the failure to change configuration.
- */
- @Override
- public void onChangeCapabilityConfigurationError(int capability, int radioTech,
- int reason) {
- }
-
- /**
- * The status of the feature's capabilities has changed to either available or unavailable.
- * If unavailable, the feature is not able to support the unavailable capability at this
- * time.
- *
- * @param config The new availability of the capabilities.
- */
- public void onCapabilitiesStatusChanged(Capabilities config) {
- }
- }
-
- /**
- * Used by the ImsFeature to call back to the CapabilityCallback that the framework has
- * provided.
- */
- protected static class CapabilityCallbackProxy {
- private final IImsCapabilityCallback mCallback;
-
- public CapabilityCallbackProxy(IImsCapabilityCallback c) {
- mCallback = c;
- }
-
- /**
- * This method notifies the provided framework callback that the request to change the
- * indicated capability has failed and has not changed.
- *
- * @param capability The Capability that will be notified to the framework.
- * @param radioTech The radio tech that this capability failed for.
- * @param reason The reason this capability was unable to be changed.
- */
- public void onChangeCapabilityConfigurationError(int capability, int radioTech,
- @ImsCapabilityError int reason) {
- try {
- mCallback.onChangeCapabilityConfigurationError(capability, radioTech, reason);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "onChangeCapabilityConfigurationError called on dead binder.");
- }
- }
-
- public void onQueryCapabilityConfiguration(int capability, int radioTech,
- boolean isEnabled) {
- try {
- mCallback.onQueryCapabilityConfiguration(capability, radioTech, isEnabled);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "onQueryCapabilityConfiguration called on dead binder.");
- }
- }
- }
-
- /**
- * Contains the capabilities defined and supported by an ImsFeature in the form of a bit mask.
- */
- public static class Capabilities {
- protected int mCapabilities = 0;
-
- public Capabilities() {
- }
-
- protected Capabilities(int capabilities) {
- mCapabilities = capabilities;
- }
-
- /**
- * @param capabilities Capabilities to be added to the configuration in the form of a
- * bit mask.
- */
- public void addCapabilities(int capabilities) {
- mCapabilities |= capabilities;
- }
-
- /**
- * @param capabilities Capabilities to be removed to the configuration in the form of a
- * bit mask.
- */
- public void removeCapabilities(int capabilities) {
- mCapabilities &= ~capabilities;
- }
-
- /**
- * @return true if all of the capabilities specified are capable.
- */
- public boolean isCapable(int capabilities) {
- return (mCapabilities & capabilities) == capabilities;
- }
-
- public Capabilities copy() {
- return new Capabilities(mCapabilities);
- }
-
- /**
- * @return a bitmask containing the capability flags directly.
- */
- public int getMask() {
- return mCapabilities;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof Capabilities)) return false;
-
- Capabilities that = (Capabilities) o;
-
- return mCapabilities == that.mCapabilities;
- }
-
- @Override
- public int hashCode() {
- return mCapabilities;
- }
- }
-
- private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap(
- new WeakHashMap<IImsFeatureStatusCallback, Boolean>());
- private @ImsState int mState = STATE_UNAVAILABLE;
- private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
- private Context mContext;
- private final Object mLock = new Object();
- private final RemoteCallbackList<IImsCapabilityCallback> mCapabilityCallbacks
- = new RemoteCallbackList<>();
- private Capabilities mCapabilityStatus = new Capabilities();
-
- public final void initialize(Context context, int slotId) {
- mContext = context;
- mSlotId = slotId;
- }
-
- public final int getFeatureState() {
- synchronized (mLock) {
- return mState;
- }
- }
-
- protected final void setFeatureState(@ImsState int state) {
- synchronized (mLock) {
- if (mState != state) {
- mState = state;
- notifyFeatureState(state);
- }
- }
- }
-
- // Not final for testing, but shouldn't be extended!
- @VisibleForTesting
- public void addImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) {
- try {
- // If we have just connected, send queued status.
- c.notifyImsFeatureStatus(getFeatureState());
- // Add the callback if the callback completes successfully without a RemoteException.
- synchronized (mLock) {
- mStatusCallbacks.add(c);
- }
- } catch (RemoteException e) {
- Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
- }
- }
-
- @VisibleForTesting
- // Not final for testing, but should not be extended!
- public void removeImsFeatureStatusCallback(@NonNull IImsFeatureStatusCallback c) {
- synchronized (mLock) {
- mStatusCallbacks.remove(c);
- }
- }
-
- /**
- * Internal method called by ImsFeature when setFeatureState has changed.
- */
- private void notifyFeatureState(@ImsState int state) {
- synchronized (mLock) {
- for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator();
- iter.hasNext(); ) {
- IImsFeatureStatusCallback callback = iter.next();
- try {
- Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
- callback.notifyImsFeatureStatus(state);
- } catch (RemoteException e) {
- // remove if the callback is no longer alive.
- iter.remove();
- Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
- }
- }
- }
- sendImsServiceIntent(state);
- }
-
- /**
- * Provide backwards compatibility using deprecated service UP/DOWN intents.
- */
- private void sendImsServiceIntent(@ImsState int state) {
- if (mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
- return;
- }
- Intent intent;
- switch (state) {
- case ImsFeature.STATE_UNAVAILABLE:
- case ImsFeature.STATE_INITIALIZING:
- intent = new Intent(ACTION_IMS_SERVICE_DOWN);
- break;
- case ImsFeature.STATE_READY:
- intent = new Intent(ACTION_IMS_SERVICE_UP);
- break;
- default:
- intent = new Intent(ACTION_IMS_SERVICE_DOWN);
- }
- intent.putExtra(EXTRA_PHONE_ID, mSlotId);
- mContext.sendBroadcast(intent);
- }
-
- public final void addCapabilityCallback(IImsCapabilityCallback c) {
- mCapabilityCallbacks.register(c);
- }
-
- public final void removeCapabilityCallback(IImsCapabilityCallback c) {
- mCapabilityCallbacks.unregister(c);
- }
-
- /**
- * @return the cached capabilities status for this feature.
- */
- @VisibleForTesting
- public Capabilities queryCapabilityStatus() {
- synchronized (mLock) {
- return mCapabilityStatus.copy();
- }
- }
-
- // Called internally to request the change of enabled capabilities.
- @VisibleForTesting
- public final void requestChangeEnabledCapabilities(CapabilityChangeRequest request,
- IImsCapabilityCallback c) throws RemoteException {
- if (request == null) {
- throw new IllegalArgumentException(
- "ImsFeature#requestChangeEnabledCapabilities called with invalid params.");
- }
- changeEnabledCapabilities(request, new CapabilityCallbackProxy(c));
- }
-
- /**
- * Called by the ImsFeature when the capabilities status has changed.
- *
- * @param c A {@link Capabilities} containing the new Capabilities status.
- */
- protected final void notifyCapabilitiesStatusChanged(Capabilities c) {
- synchronized (mLock) {
- mCapabilityStatus = c.copy();
- }
- int count = mCapabilityCallbacks.beginBroadcast();
- try {
- for (int i = 0; i < count; i++) {
- try {
- mCapabilityCallbacks.getBroadcastItem(i).onCapabilitiesStatusChanged(
- c.mCapabilities);
- } catch (RemoteException e) {
- Log.w(LOG_TAG, e + " " + "notifyCapabilitiesStatusChanged() - Skipping " +
- "callback.");
- }
- }
- } finally {
- mCapabilityCallbacks.finishBroadcast();
- }
- }
-
- /**
- * Features should override this method to receive Capability preference change requests from
- * the framework using the provided {@link CapabilityChangeRequest}. If any of the capabilities
- * in the {@link CapabilityChangeRequest} are not able to be completed due to an error,
- * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} should be called for
- * each failed capability.
- *
- * @param request A {@link CapabilityChangeRequest} containing requested capabilities to
- * enable/disable.
- * @param c A {@link CapabilityCallbackProxy}, which will be used to call back to the framework
- * setting a subset of these capabilities fail, using
- * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError}.
- */
- public abstract void changeEnabledCapabilities(CapabilityChangeRequest request,
- CapabilityCallbackProxy c);
-
- /**
- * Called when the framework is removing this feature and it needs to be cleaned up.
- */
- public abstract void onFeatureRemoved();
-
- /**
- * Called when the feature has been initialized and communication with the framework is set up.
- * Any attempt by this feature to access the framework before this method is called will return
- * with an {@link IllegalStateException}.
- * The IMS provider should use this method to trigger registration for this feature on the IMS
- * network, if needed.
- */
- public abstract void onFeatureReady();
-
- /**
- * @return Binder instance that the framework will use to communicate with this feature.
- */
- protected abstract IInterface getBinder();
-}
diff --git a/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java
deleted file mode 100644
index 9b576c7..0000000
--- a/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.telephony.ims.internal.feature;
-
-import android.annotation.IntDef;
-import android.os.Message;
-import android.os.RemoteException;
-import android.telecom.TelecomManager;
-import android.telephony.ims.internal.ImsCallSessionListener;
-import android.telephony.ims.internal.aidl.IImsCallSessionListener;
-import android.telephony.ims.internal.aidl.IImsCapabilityCallback;
-import android.telephony.ims.internal.aidl.IImsMmTelFeature;
-import android.telephony.ims.internal.aidl.IImsMmTelListener;
-import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.telephony.ims.stub.ImsEcbmImplBase;
-import android.telephony.ims.stub.ImsMultiEndpointImplBase;
-import android.telephony.ims.stub.ImsUtImplBase;
-import android.util.Log;
-
-import com.android.ims.ImsCallProfile;
-import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsEcbm;
-import com.android.ims.internal.IImsMultiEndpoint;
-import com.android.ims.internal.IImsUt;
-import com.android.ims.internal.ImsCallSession;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support.
- *
- * Any class wishing to use MmTelFeature should extend this class and implement all methods that the
- * service supports.
- * @hide
- */
-
-public class MmTelFeature extends ImsFeature {
-
- private static final String LOG_TAG = "MmTelFeature";
-
- private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() {
-
- @Override
- public void setListener(IImsMmTelListener l) throws RemoteException {
- synchronized (mLock) {
- MmTelFeature.this.setListener(l);
- }
- }
-
- @Override
- public int getFeatureState() throws RemoteException {
- synchronized (mLock) {
- return MmTelFeature.this.getFeatureState();
- }
- }
-
-
- @Override
- public ImsCallProfile createCallProfile(int callSessionType, int callType)
- throws RemoteException {
- synchronized (mLock) {
- return MmTelFeature.this.createCallProfile(callSessionType, callType);
- }
- }
-
- @Override
- public IImsCallSession createCallSession(ImsCallProfile profile,
- IImsCallSessionListener listener) throws RemoteException {
- synchronized (mLock) {
- ImsCallSession s = MmTelFeature.this.createCallSession(profile,
- new ImsCallSessionListener(listener));
- return s != null ? s.getSession() : null;
- }
- }
-
- @Override
- public IImsUt getUtInterface() throws RemoteException {
- synchronized (mLock) {
- return MmTelFeature.this.getUt();
- }
- }
-
- @Override
- public IImsEcbm getEcbmInterface() throws RemoteException {
- synchronized (mLock) {
- return MmTelFeature.this.getEcbm();
- }
- }
-
- @Override
- public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException {
- synchronized (mLock) {
- MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage);
- }
- }
-
- @Override
- public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
- synchronized (mLock) {
- return MmTelFeature.this.getMultiEndpoint();
- }
- }
-
- @Override
- public int queryCapabilityStatus() throws RemoteException {
- return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
- }
-
- @Override
- public void addCapabilityCallback(IImsCapabilityCallback c) {
- MmTelFeature.this.addCapabilityCallback(c);
- }
-
- @Override
- public void removeCapabilityCallback(IImsCapabilityCallback c) {
- MmTelFeature.this.removeCapabilityCallback(c);
- }
-
- @Override
- public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
- IImsCapabilityCallback c) throws RemoteException {
- MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
- }
-
- @Override
- public void queryCapabilityConfiguration(int capability, int radioTech,
- IImsCapabilityCallback c) {
- queryCapabilityConfigurationInternal(capability, radioTech, c);
- }
- };
-
- /**
- * Contains the capabilities defined and supported by a MmTelFeature in the form of a Bitmask.
- * The capabilities that are used in MmTelFeature are defined by {@link MmTelCapability}.
- *
- * The capabilities of this MmTelFeature will be set by the framework and can be queried with
- * {@link #queryCapabilityStatus()}.
- *
- * This MmTelFeature can then return the status of each of these capabilities (enabled or not)
- * by sending a {@link #notifyCapabilitiesStatusChanged} callback to the framework. The current
- * status can also be queried using {@link #queryCapabilityStatus()}.
- */
- public static class MmTelCapabilities extends Capabilities {
-
- @VisibleForTesting
- public MmTelCapabilities() {
- super();
- }
-
- public MmTelCapabilities(Capabilities c) {
- mCapabilities = c.mCapabilities;
- }
-
- @IntDef(flag = true,
- value = {
- CAPABILITY_TYPE_VOICE,
- CAPABILITY_TYPE_VIDEO,
- CAPABILITY_TYPE_UT,
- CAPABILITY_TYPE_SMS
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface MmTelCapability {}
-
- /**
- * This MmTelFeature supports Voice calling (IR.92)
- */
- public static final int CAPABILITY_TYPE_VOICE = 1 << 0;
-
- /**
- * This MmTelFeature supports Video (IR.94)
- */
- public static final int CAPABILITY_TYPE_VIDEO = 1 << 1;
-
- /**
- * This MmTelFeature supports XCAP over Ut for supplementary services. (IR.92)
- */
- public static final int CAPABILITY_TYPE_UT = 1 << 2;
-
- /**
- * This MmTelFeature supports SMS (IR.92)
- */
- public static final int CAPABILITY_TYPE_SMS = 1 << 3;
-
- @Override
- public final void addCapabilities(@MmTelCapability int capabilities) {
- super.addCapabilities(capabilities);
- }
-
- @Override
- public final void removeCapabilities(@MmTelCapability int capability) {
- super.removeCapabilities(capability);
- }
-
- @Override
- public final boolean isCapable(@MmTelCapability int capabilities) {
- return super.isCapable(capabilities);
- }
- }
-
- /**
- * Listener that the framework implements for communication from the MmTelFeature.
- */
- public static class Listener extends IImsMmTelListener.Stub {
-
- @Override
- public final void onIncomingCall(IImsCallSession c) {
- onIncomingCall(new ImsCallSession(c));
- }
-
- /**
- * Updates the Listener when the voice message count for IMS has changed.
- * @param count an integer representing the new message count.
- */
- @Override
- public void onVoiceMessageCountUpdate(int count) {
-
- }
-
- /**
- * Called when the IMS provider receives an incoming call.
- * @param c The {@link ImsCallSession} associated with the new call.
- */
- public void onIncomingCall(ImsCallSession c) {
- }
- }
-
- // Lock for feature synchronization
- private final Object mLock = new Object();
- private IImsMmTelListener mListener;
-
- /**
- * @param listener A {@link Listener} used when the MmTelFeature receives an incoming call and
- * notifies the framework.
- */
- private void setListener(IImsMmTelListener listener) {
- synchronized (mLock) {
- mListener = listener;
- }
- }
-
- private void queryCapabilityConfigurationInternal(int capability, int radioTech,
- IImsCapabilityCallback c) {
- boolean enabled = queryCapabilityConfiguration(capability, radioTech);
- try {
- if (c != null) {
- c.onQueryCapabilityConfiguration(capability, radioTech, enabled);
- }
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "queryCapabilityConfigurationInternal called on dead binder!");
- }
- }
-
- /**
- * The current capability status that this MmTelFeature has defined is available. This
- * configuration will be used by the platform to figure out which capabilities are CURRENTLY
- * available to be used.
- *
- * Should be a subset of the capabilities that are enabled by the framework in
- * {@link #changeEnabledCapabilities}.
- * @return A copy of the current MmTelFeature capability status.
- */
- @Override
- public final MmTelCapabilities queryCapabilityStatus() {
- return new MmTelCapabilities(super.queryCapabilityStatus());
- }
-
- /**
- * Notify the framework that the status of the Capabilities has changed. Even though the
- * MmTelFeature capability may be enabled by the framework, the status may be disabled due to
- * the feature being unavailable from the network.
- * @param c The current capability status of the MmTelFeature. If a capability is disabled, then
- * the status of that capability is disabled. This can happen if the network does not currently
- * support the capability that is enabled. A capability that is disabled by the framework (via
- * {@link #changeEnabledCapabilities}) should also show the status as disabled.
- */
- protected final void notifyCapabilitiesStatusChanged(MmTelCapabilities c) {
- super.notifyCapabilitiesStatusChanged(c);
- }
-
- /**
- * Notify the framework of an incoming call.
- * @param c The {@link ImsCallSession} of the new incoming call.
- *
- * @throws RemoteException if the connection to the framework is not available. If this happens,
- * the call should be no longer considered active and should be cleaned up.
- * */
- protected final void notifyIncomingCall(ImsCallSession c) throws RemoteException {
- synchronized (mLock) {
- if (mListener == null) {
- throw new IllegalStateException("Session is not available.");
- }
- mListener.onIncomingCall(c.getSession());
- }
- }
-
- /**
- * Provides the MmTelFeature with the ability to return the framework Capability Configuration
- * for a provided Capability. If the framework calls {@link #changeEnabledCapabilities} and
- * includes a capability A to enable or disable, this method should return the correct enabled
- * status for capability A.
- * @param capability The capability that we are querying the configuration for.
- * @return true if the capability is enabled, false otherwise.
- */
- public boolean queryCapabilityConfiguration(@MmTelCapabilities.MmTelCapability int capability,
- @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
- // Base implementation - Override to provide functionality
- return false;
- }
-
- /**
- * The MmTelFeature should override this method to handle the enabling/disabling of
- * MmTel Features, defined in {@link MmTelCapabilities.MmTelCapability}. The framework assumes
- * the {@link CapabilityChangeRequest} was processed successfully. If a subset of capabilities
- * could not be set to their new values,
- * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError} must be called
- * individually for each capability whose processing resulted in an error.
- *
- * Enabling/Disabling a capability here indicates that the capability should be registered or
- * deregistered (depending on the capability change) and become available or unavailable to
- * the framework.
- */
- @Override
- public void changeEnabledCapabilities(CapabilityChangeRequest request,
- CapabilityCallbackProxy c) {
- // Base implementation, no-op
- }
-
- /**
- * Creates a {@link ImsCallProfile} from the service capabilities & IMS registration state.
- *
- * @param callSessionType a service type that is specified in {@link ImsCallProfile}
- * {@link ImsCallProfile#SERVICE_TYPE_NONE}
- * {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
- * {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
- * @param callType a call type that is specified in {@link ImsCallProfile}
- * {@link ImsCallProfile#CALL_TYPE_VOICE}
- * {@link ImsCallProfile#CALL_TYPE_VT}
- * {@link ImsCallProfile#CALL_TYPE_VT_TX}
- * {@link ImsCallProfile#CALL_TYPE_VT_RX}
- * {@link ImsCallProfile#CALL_TYPE_VT_NODIR}
- * {@link ImsCallProfile#CALL_TYPE_VS}
- * {@link ImsCallProfile#CALL_TYPE_VS_TX}
- * {@link ImsCallProfile#CALL_TYPE_VS_RX}
- * @return a {@link ImsCallProfile} object
- */
- public ImsCallProfile createCallProfile(int callSessionType, int callType) {
- // Base Implementation - Should be overridden
- return null;
- }
-
- /**
- * Creates an {@link ImsCallSession} with the specified call profile.
- * Use other methods, if applicable, instead of interacting with
- * {@link ImsCallSession} directly.
- *
- * @param profile a call profile to make the call
- * @param listener An implementation of IImsCallSessionListener.
- */
- public ImsCallSession createCallSession(ImsCallProfile profile,
- ImsCallSessionListener listener) {
- // Base Implementation - Should be overridden
- return null;
- }
-
- /**
- * @return The Ut interface for the supplementary service configuration.
- */
- public ImsUtImplBase getUt() {
- // Base Implementation - Should be overridden
- return null;
- }
-
- /**
- * @return The Emergency call-back mode interface for emergency VoLTE calls that support it.
- */
- public ImsEcbmImplBase getEcbm() {
- // Base Implementation - Should be overridden
- return null;
- }
-
- /**
- * @return The Emergency call-back mode interface for emergency VoLTE calls that support it.
- */
- public ImsMultiEndpointImplBase getMultiEndpoint() {
- // Base Implementation - Should be overridden
- return null;
- }
-
- /**
- * Sets the current UI TTY mode for the MmTelFeature.
- * @param mode An integer containing the new UI TTY Mode, can consist of
- * {@link TelecomManager#TTY_MODE_OFF},
- * {@link TelecomManager#TTY_MODE_FULL},
- * {@link TelecomManager#TTY_MODE_HCO},
- * {@link TelecomManager#TTY_MODE_VCO}
- * @param onCompleteMessage A {@link Message} to be used when the mode has been set.
- */
- void setUiTtyMode(int mode, Message onCompleteMessage) {
- // Base Implementation - Should be overridden
- }
-
- /**{@inheritDoc}*/
- @Override
- public void onFeatureRemoved() {
- // Base Implementation - Should be overridden
- }
-
- /**{@inheritDoc}*/
- @Override
- public void onFeatureReady() {
- // Base Implementation - Should be overridden
- }
-
- /**
- * @hide
- */
- @Override
- public final IImsMmTelFeature getBinder() {
- return mImsMMTelBinder;
- }
-}
diff --git a/telephony/java/android/telephony/ims/internal/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/internal/stub/ImsConfigImplBase.java
deleted file mode 100644
index 33aec5d..0000000
--- a/telephony/java/android/telephony/ims/internal/stub/ImsConfigImplBase.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.telephony.ims.internal.stub;
-
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.telephony.ims.internal.aidl.IImsConfig;
-import android.telephony.ims.internal.aidl.IImsConfigCallback;
-
-import com.android.ims.ImsConfig;
-
-/**
- * Controls the modification of IMS specific configurations. For more information on the supported
- * IMS configuration constants, see {@link ImsConfig}.
- *
- * @hide
- */
-
-public class ImsConfigImplBase {
-
- //TODO: Implement the Binder logic to call base APIs. Need to finish other ImsService Config
- // work first.
- private final IImsConfig mBinder = new IImsConfig.Stub() {
-
- @Override
- public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException {
- ImsConfigImplBase.this.addImsConfigCallback(c);
- }
-
- @Override
- public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException {
- ImsConfigImplBase.this.removeImsConfigCallback(c);
- }
-
- @Override
- public int getConfigInt(int item) throws RemoteException {
- return Integer.MIN_VALUE;
- }
-
- @Override
- public String getConfigString(int item) throws RemoteException {
- return null;
- }
-
- @Override
- public int setConfigInt(int item, int value) throws RemoteException {
- return Integer.MIN_VALUE;
- }
-
- @Override
- public int setConfigString(int item, String value) throws RemoteException {
- return Integer.MIN_VALUE;
- }
- };
-
- public class Callback extends IImsConfigCallback.Stub {
-
- @Override
- public final void onIntConfigChanged(int item, int value) throws RemoteException {
- onConfigChanged(item, value);
- }
-
- @Override
- public final void onStringConfigChanged(int item, String value) throws RemoteException {
- onConfigChanged(item, value);
- }
-
- /**
- * Called when the IMS configuration has changed.
- * @param item the IMS configuration key constant, as defined in ImsConfig.
- * @param value the new integer value of the IMS configuration constant.
- */
- public void onConfigChanged(int item, int value) {
- // Base Implementation
- }
-
- /**
- * Called when the IMS configuration has changed.
- * @param item the IMS configuration key constant, as defined in ImsConfig.
- * @param value the new String value of the IMS configuration constant.
- */
- public void onConfigChanged(int item, String value) {
- // Base Implementation
- }
- }
-
- private final RemoteCallbackList<IImsConfigCallback> mCallbacks = new RemoteCallbackList<>();
-
- /**
- * Adds a {@link Callback} to the list of callbacks notified when a value in the configuration
- * changes.
- * @param c callback to add.
- */
- private void addImsConfigCallback(IImsConfigCallback c) {
- mCallbacks.register(c);
- }
- /**
- * Removes a {@link Callback} to the list of callbacks notified when a value in the
- * configuration changes.
- *
- * @param c callback to remove.
- */
- private void removeImsConfigCallback(IImsConfigCallback c) {
- mCallbacks.unregister(c);
- }
-
- public final IImsConfig getBinder() {
- return mBinder;
- }
-
- /**
- * Sets the value for IMS service/capabilities parameters by the operator device
- * management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived.
- *
- * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @param value in Integer format.
- * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
- */
- public int setConfig(int item, int value) {
- // Base Implementation - To be overridden.
- return ImsConfig.OperationStatusConstants.FAILED;
- }
-
- /**
- * Sets the value for IMS service/capabilities parameters by the operator device
- * management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived.
- *
- * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @param value in String format.
- * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
- */
- public int setConfig(int item, String value) {
- return ImsConfig.OperationStatusConstants.FAILED;
- }
-
- /**
- * Gets the value for ims service/capabilities parameters from the provisioned
- * value storage.
- *
- * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @return value in Integer format.
- */
- public int getConfigInt(int item) {
- return ImsConfig.OperationStatusConstants.FAILED;
- }
-
- /**
- * Gets the value for ims service/capabilities parameters from the provisioned
- * value storage.
- *
- * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @return value in String format.
- */
- public String getConfigString(int item) {
- return null;
- }
-}
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index 80b2f78..c6ca6fd 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -16,105 +16,259 @@
package android.telephony.ims.stub;
+import android.annotation.SystemApi;
import android.os.Message;
import android.os.RemoteException;
+import android.telephony.ims.ImsCallSessionListener;
+import android.telephony.ims.aidl.IImsCallSessionListener;
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.internal.ImsCallSession;
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsStreamMediaProfile;
+import android.telephony.ims.ImsCallSession;
import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsCallSessionListener;
import com.android.ims.internal.IImsVideoCallProvider;
+import android.telephony.ims.ImsVideoCallProvider;
+
+import dalvik.system.CloseGuard;
/**
- * Base implementation of IImsCallSession, which implements stub versions of the methods in the
- * IImsCallSession AIDL. Override the methods that your implementation of ImsCallSession supports.
+ * Base implementation of IImsCallSession, which implements stub versions of the methods available.
*
- * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
- * will break other implementations of ImsCallSession maintained by other ImsServices.
+ * Override the methods that your implementation of ImsCallSession supports.
*
* @hide
*/
-
-public class ImsCallSessionImplBase extends IImsCallSession.Stub {
+@SystemApi
+// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+// will break other implementations of ImsCallSession maintained by other ImsServices.
+public class ImsCallSessionImplBase implements AutoCloseable {
+ /**
+ * Notify USSD Mode.
+ */
+ public static final int USSD_MODE_NOTIFY = 0;
+ /**
+ * Request USSD Mode
+ */
+ public static final int USSD_MODE_REQUEST = 1;
/**
- * Closes the object. This object is not usable after being closed.
+ * Defines IMS call session state.
*/
- @Override
- public void close() throws RemoteException {
+ public static class State {
+ public static final int IDLE = 0;
+ public static final int INITIATED = 1;
+ public static final int NEGOTIATING = 2;
+ public static final int ESTABLISHING = 3;
+ public static final int ESTABLISHED = 4;
+ public static final int RENEGOTIATING = 5;
+ public static final int REESTABLISHING = 6;
+
+ public static final int TERMINATING = 7;
+ public static final int TERMINATED = 8;
+
+ public static final int INVALID = (-1);
+
+ /**
+ * Converts the state to string.
+ */
+ public static String toString(int state) {
+ switch (state) {
+ case IDLE:
+ return "IDLE";
+ case INITIATED:
+ return "INITIATED";
+ case NEGOTIATING:
+ return "NEGOTIATING";
+ case ESTABLISHING:
+ return "ESTABLISHING";
+ case ESTABLISHED:
+ return "ESTABLISHED";
+ case RENEGOTIATING:
+ return "RENEGOTIATING";
+ case REESTABLISHING:
+ return "REESTABLISHING";
+ case TERMINATING:
+ return "TERMINATING";
+ case TERMINATED:
+ return "TERMINATED";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ /**
+ * @hide
+ */
+ private State() {
+ }
}
- /**
- * Gets the call ID of the session.
- *
- * @return the call ID
- */
- @Override
- public String getCallId() throws RemoteException {
- return null;
- }
+ // Non-final for injection by tests
+ private IImsCallSession mServiceImpl = new IImsCallSession.Stub() {
+ @Override
+ public void close() {
+ ImsCallSessionImplBase.this.close();
+ }
+
+ @Override
+ public String getCallId() {
+ return ImsCallSessionImplBase.this.getCallId();
+ }
+
+ @Override
+ public ImsCallProfile getCallProfile() {
+ return ImsCallSessionImplBase.this.getCallProfile();
+ }
+
+ @Override
+ public ImsCallProfile getLocalCallProfile() {
+ return ImsCallSessionImplBase.this.getLocalCallProfile();
+ }
+
+ @Override
+ public ImsCallProfile getRemoteCallProfile() {
+ return ImsCallSessionImplBase.this.getRemoteCallProfile();
+ }
+
+ @Override
+ public String getProperty(String name) {
+ return ImsCallSessionImplBase.this.getProperty(name);
+ }
+
+ @Override
+ public int getState() {
+ return ImsCallSessionImplBase.this.getState();
+ }
+
+ @Override
+ public boolean isInCall() {
+ return ImsCallSessionImplBase.this.isInCall();
+ }
+
+ @Override
+ public void setListener(IImsCallSessionListener listener) {
+ ImsCallSessionImplBase.this.setListener(new ImsCallSessionListener(listener));
+ }
+
+ @Override
+ public void setMute(boolean muted) {
+ ImsCallSessionImplBase.this.setMute(muted);
+ }
+
+ @Override
+ public void start(String callee, ImsCallProfile profile) {
+ ImsCallSessionImplBase.this.start(callee, profile);
+ }
+
+ @Override
+ public void startConference(String[] participants, ImsCallProfile profile) throws
+ RemoteException {
+ ImsCallSessionImplBase.this.startConference(participants, profile);
+ }
+
+ @Override
+ public void accept(int callType, ImsStreamMediaProfile profile) {
+ ImsCallSessionImplBase.this.accept(callType, profile);
+ }
+
+ @Override
+ public void reject(int reason) {
+ ImsCallSessionImplBase.this.reject(reason);
+ }
+
+ @Override
+ public void terminate(int reason) {
+ ImsCallSessionImplBase.this.terminate(reason);
+ }
+
+ @Override
+ public void hold(ImsStreamMediaProfile profile) {
+ ImsCallSessionImplBase.this.hold(profile);
+ }
+
+ @Override
+ public void resume(ImsStreamMediaProfile profile) {
+ ImsCallSessionImplBase.this.resume(profile);
+ }
+
+ @Override
+ public void merge() {
+ ImsCallSessionImplBase.this.merge();
+ }
+
+ @Override
+ public void update(int callType, ImsStreamMediaProfile profile) {
+ ImsCallSessionImplBase.this.update(callType, profile);
+ }
+
+ @Override
+ public void extendToConference(String[] participants) {
+ ImsCallSessionImplBase.this.extendToConference(participants);
+ }
+
+ @Override
+ public void inviteParticipants(String[] participants) {
+ ImsCallSessionImplBase.this.inviteParticipants(participants);
+ }
+
+ @Override
+ public void removeParticipants(String[] participants) {
+ ImsCallSessionImplBase.this.removeParticipants(participants);
+ }
+
+ @Override
+ public void sendDtmf(char c, Message result) {
+ ImsCallSessionImplBase.this.sendDtmf(c, result);
+ }
+
+ @Override
+ public void startDtmf(char c) {
+ ImsCallSessionImplBase.this.startDtmf(c);
+ }
+
+ @Override
+ public void stopDtmf() {
+ ImsCallSessionImplBase.this.stopDtmf();
+ }
+
+ @Override
+ public void sendUssd(String ussdMessage) {
+ ImsCallSessionImplBase.this.sendUssd(ussdMessage);
+ }
+
+ @Override
+ public IImsVideoCallProvider getVideoCallProvider() {
+ return ImsCallSessionImplBase.this.getVideoCallProvider();
+ }
+
+ @Override
+ public boolean isMultiparty() {
+ return ImsCallSessionImplBase.this.isMultiparty();
+ }
+
+ @Override
+ public void sendRttModifyRequest(ImsCallProfile toProfile) {
+ ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile);
+ }
+
+ @Override
+ public void sendRttModifyResponse(boolean status) {
+ ImsCallSessionImplBase.this.sendRttModifyResponse(status);
+ }
+
+ @Override
+ public void sendRttMessage(String rttMessage) {
+ ImsCallSessionImplBase.this.sendRttMessage(rttMessage);
+ }
+ };
/**
- * Gets the call profile that this session is associated with
- *
- * @return the {@link ImsCallProfile} that this session is associated with
+ * @hide
*/
- @Override
- public ImsCallProfile getCallProfile() throws RemoteException {
- return null;
- }
-
- /**
- * Gets the local call profile that this session is associated with
- *
- * @return the local {@link ImsCallProfile} that this session is associated with
- */
- @Override
- public ImsCallProfile getLocalCallProfile() throws RemoteException {
- return null;
- }
-
- /**
- * Gets the remote call profile that this session is associated with
- *
- * @return the remote {@link ImsCallProfile} that this session is associated with
- */
- @Override
- public ImsCallProfile getRemoteCallProfile() throws RemoteException {
- return null;
- }
-
- /**
- * Gets the value associated with the specified property of this session.
- *
- * @return the string value associated with the specified property
- */
- @Override
- public String getProperty(String name) throws RemoteException {
- return null;
- }
-
- /**
- * Gets the session state.
- * The value returned must be one of the states in {@link ImsCallSession.State}.
- *
- * @return the session state
- */
- @Override
- public int getState() throws RemoteException {
- return ImsCallSession.State.INVALID;
- }
-
- /**
- * Checks if the session is in call.
- *
- * @return true if the session is in call, false otherwise
- */
- @Override
- public boolean isInCall() throws RemoteException {
- return false;
+ public final void setListener(IImsCallSessionListener listener) throws RemoteException {
+ setListener(new ImsCallSessionListener(listener));
}
/**
@@ -122,25 +276,87 @@
* can only hold one listener at a time. Subsequent calls to this method
* override the previous listener.
*
- * @param listener to listen to the session events of this object
+ * @param listener {@link ImsCallSessionListener} used to notify the framework of updates
+ * to the ImsCallSession
+ */
+ public void setListener(ImsCallSessionListener listener) {
+ }
+
+ /**
+ * Closes the object. This {@link ImsCallSessionImplBase} is not usable after being closed.
*/
@Override
- public void setListener(IImsCallSessionListener listener) throws RemoteException {
+ public void close() {
+
+ }
+
+ /**
+ * @return A String containing the unique call ID of this {@link ImsCallSessionImplBase}.
+ */
+ public String getCallId() {
+ return null;
+ }
+
+ /**
+ * @return The {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is associated
+ * with.
+ */
+ public ImsCallProfile getCallProfile() {
+ return null;
+ }
+
+ /**
+ * @return The local {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is
+ * associated with.
+ */
+ public ImsCallProfile getLocalCallProfile() {
+ return null;
+ }
+
+ /**
+ * @return The remote {@link ImsCallProfile} that this {@link ImsCallSessionImplBase} is
+ * associated with.
+ */
+ public ImsCallProfile getRemoteCallProfile() {
+ return null;
+ }
+
+ /**
+ * @param name The String extra key.
+ * @return The string extra value associated with the specified property.
+ */
+ public String getProperty(String name) {
+ return null;
+ }
+
+ /**
+ * @return The {@link ImsCallSessionImplBase} state, defined in
+ * {@link ImsCallSessionImplBase.State}.
+ */
+ public int getState() {
+ return ImsCallSessionImplBase.State.INVALID;
+ }
+
+ /**
+ * @return true if the {@link ImsCallSessionImplBase} is in a call, false otherwise.
+ */
+ public boolean isInCall() {
+ return false;
}
/**
* Mutes or unmutes the mic for the active call.
*
- * @param muted true if the call is muted, false otherwise
+ * @param muted true if the call should be muted, false otherwise.
*/
- @Override
- public void setMute(boolean muted) throws RemoteException {
+ public void setMute(boolean muted) {
}
/**
- * Initiates an IMS call with the specified target and call profile.
- * The session listener set in {@link #setListener} is called back upon defined session events.
- * The method is only valid to call when the session state is in
+ * Initiates an IMS call with the specified number and call profile.
+ * The session listener set in {@link #setListener(ImsCallSessionListener)} is called back upon
+ * defined session events.
+ * Only valid to call when the session state is in
* {@link ImsCallSession.State#IDLE}.
*
* @param callee dialed string to make the call to
@@ -149,13 +365,13 @@
* @see {@link ImsCallSession.Listener#callSessionStarted},
* {@link ImsCallSession.Listener#callSessionStartFailed}
*/
- @Override
- public void start(String callee, ImsCallProfile profile) throws RemoteException {
+ public void start(String callee, ImsCallProfile profile) {
}
/**
* Initiates an IMS call with the specified participants and call profile.
- * The session listener set in {@link #setListener} is called back upon defined session events.
+ * The session listener set in {@link #setListener(ImsCallSessionListener)} is called back upon
+ * defined session events.
* The method is only valid to call when the session state is in
* {@link ImsCallSession.State#IDLE}.
*
@@ -165,9 +381,7 @@
* @see {@link ImsCallSession.Listener#callSessionStarted},
* {@link ImsCallSession.Listener#callSessionStartFailed}
*/
- @Override
- public void startConference(String[] participants, ImsCallProfile profile)
- throws RemoteException {
+ public void startConference(String[] participants, ImsCallProfile profile) {
}
/**
@@ -177,31 +391,26 @@
* @param profile stream media profile {@link ImsStreamMediaProfile} to be answered
* @see {@link ImsCallSession.Listener#callSessionStarted}
*/
- @Override
- public void accept(int callType, ImsStreamMediaProfile profile) throws RemoteException {
+ public void accept(int callType, ImsStreamMediaProfile profile) {
}
/**
* Rejects an incoming call or session update.
*
- * @param reason reason code to reject an incoming call, defined in
- * com.android.ims.ImsReasonInfo
+ * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
* {@link ImsCallSession.Listener#callSessionStartFailed}
*/
- @Override
- public void reject(int reason) throws RemoteException {
+ public void reject(int reason) {
}
/**
* Terminates a call.
*
- * @param reason reason code to terminate a call, defined in
- * com.android.ims.ImsReasonInfo
+ * @param reason reason code to terminate a call, defined in {@link ImsReasonInfo}.
*
* @see {@link ImsCallSession.Listener#callSessionTerminated}
*/
- @Override
- public void terminate(int reason) throws RemoteException {
+ public void terminate(int reason) {
}
/**
@@ -212,8 +421,7 @@
* @see {@link ImsCallSession.Listener#callSessionHeld},
* {@link ImsCallSession.Listener#callSessionHoldFailed}
*/
- @Override
- public void hold(ImsStreamMediaProfile profile) throws RemoteException {
+ public void hold(ImsStreamMediaProfile profile) {
}
/**
@@ -224,12 +432,11 @@
* @see {@link ImsCallSession.Listener#callSessionResumed},
* {@link ImsCallSession.Listener#callSessionResumeFailed}
*/
- @Override
- public void resume(ImsStreamMediaProfile profile) throws RemoteException {
+ public void resume(ImsStreamMediaProfile profile) {
}
/**
- * Merges the active & hold call. When the merge starts,
+ * Merges the active and held call. When the merge starts,
* {@link ImsCallSession.Listener#callSessionMergeStarted} is called.
* {@link ImsCallSession.Listener#callSessionMergeComplete} is called if the merge is
* successful, and {@link ImsCallSession.Listener#callSessionMergeFailed} is called if the merge
@@ -239,8 +446,7 @@
* {@link ImsCallSession.Listener#callSessionMergeComplete},
* {@link ImsCallSession.Listener#callSessionMergeFailed}
*/
- @Override
- public void merge() throws RemoteException {
+ public void merge() {
}
/**
@@ -251,8 +457,7 @@
* @see {@link ImsCallSession.Listener#callSessionUpdated},
* {@link ImsCallSession.Listener#callSessionUpdateFailed}
*/
- @Override
- public void update(int callType, ImsStreamMediaProfile profile) throws RemoteException {
+ public void update(int callType, ImsStreamMediaProfile profile) {
}
/**
@@ -263,8 +468,7 @@
* @see {@link ImsCallSession.Listener#callSessionConferenceExtended},
* {@link ImsCallSession.Listener#callSessionConferenceExtendFailed}
*/
- @Override
- public void extendToConference(String[] participants) throws RemoteException {
+ public void extendToConference(String[] participants) {
}
/**
@@ -274,8 +478,7 @@
* @see {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestDelivered},
* {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestFailed}
*/
- @Override
- public void inviteParticipants(String[] participants) throws RemoteException {
+ public void inviteParticipants(String[] participants) {
}
/**
@@ -285,8 +488,7 @@
* @see {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestDelivered},
* {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestFailed}
*/
- @Override
- public void removeParticipants(String[] participants) throws RemoteException {
+ public void removeParticipants(String[] participants) {
}
/**
@@ -296,8 +498,7 @@
*
* @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
*/
- @Override
- public void sendDtmf(char c, Message result) throws RemoteException {
+ public void sendDtmf(char c, Message result) {
}
/**
@@ -307,15 +508,13 @@
*
* @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
*/
- @Override
- public void startDtmf(char c) throws RemoteException {
+ public void startDtmf(char c) {
}
/**
* Stop a DTMF code.
*/
- @Override
- public void stopDtmf() throws RemoteException {
+ public void stopDtmf() {
}
/**
@@ -323,17 +522,23 @@
*
* @param ussdMessage USSD message to send
*/
- @Override
- public void sendUssd(String ussdMessage) throws RemoteException {
+ public void sendUssd(String ussdMessage) {
}
/**
- * Returns a binder for the video call provider implementation contained within the IMS service
- * process. This binder is used by the VideoCallProvider subclass in Telephony which
- * intermediates between the propriety implementation and Telecomm/InCall.
+ * See {@link #getImsVideoCallProvider()}, used directly in older ImsService implementations.
+ * @hide
*/
- @Override
- public IImsVideoCallProvider getVideoCallProvider() throws RemoteException {
+ public IImsVideoCallProvider getVideoCallProvider() {
+ ImsVideoCallProvider provider = getImsVideoCallProvider();
+ return provider != null ? provider.getInterface() : null;
+ }
+
+ /**
+ * @return The {@link ImsVideoCallProvider} implementation contained within the IMS service
+ * process.
+ */
+ public ImsVideoCallProvider getImsVideoCallProvider() {
return null;
}
@@ -341,8 +546,7 @@
* Determines if the current session is multiparty.
* @return {@code True} if the session is multiparty.
*/
- @Override
- public boolean isMultiparty() throws RemoteException {
+ public boolean isMultiparty() {
return false;
}
@@ -350,16 +554,13 @@
* Device issues RTT modify request
* @param toProfile The profile with requested changes made
*/
- @Override
public void sendRttModifyRequest(ImsCallProfile toProfile) {
}
/**
* Device responds to Remote RTT modify request
- * @param status true Accepted the request
- * false Declined the request
+ * @param status true if the the request was accepted or false of the request is defined.
*/
- @Override
public void sendRttModifyResponse(boolean status) {
}
@@ -367,7 +568,16 @@
* Device sends RTT message
* @param rttMessage RTT message to be sent
*/
- @Override
public void sendRttMessage(String rttMessage) {
}
+
+ /** @hide */
+ public IImsCallSession getServiceImpl() {
+ return mServiceImpl;
+ }
+
+ /** @hide */
+ public void setServiceImpl(IImsCallSession serviceImpl) {
+ mServiceImpl = serviceImpl;
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionListenerImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionListenerImplBase.java
deleted file mode 100644
index 6c18935..0000000
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionListenerImplBase.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.telephony.ims.stub;
-
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsConferenceState;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.ImsSuppServiceNotification;
-import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsCallSessionListener;
-
-/**
- * Base implementation of ImsCallSessionListenerBase, which implements stub versions of the methods
- * in the IImsCallSessionListener AIDL. Override the methods that your implementation of
- * ImsCallSessionListener supports.
- *
- * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
- * will break other implementations of ImsCallSessionListener maintained by other ImsServices.
- *
- * @hide
- */
-public class ImsCallSessionListenerImplBase extends IImsCallSessionListener.Stub {
- /**
- * Notifies the result of the basic session operation (setup / terminate).
- */
- @Override
- public void callSessionProgressing(IImsCallSession session, ImsStreamMediaProfile profile) {
- // no-op
- }
-
- @Override
- public void callSessionStarted(IImsCallSession session, ImsCallProfile profile) {
- // no-op
- }
-
- @Override
- public void callSessionStartFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- @Override
- public void callSessionTerminated(IImsCallSession session, ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- /**
- * Notifies the result of the call hold/resume operation.
- */
- @Override
- public void callSessionHeld(IImsCallSession session, ImsCallProfile profile) {
- // no-op
- }
-
- @Override
- public void callSessionHoldFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- @Override
- public void callSessionHoldReceived(IImsCallSession session, ImsCallProfile profile) {
- // no-op
- }
-
- @Override
- public void callSessionResumed(IImsCallSession session, ImsCallProfile profile) {
- // no-op
- }
-
- @Override
- public void callSessionResumeFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- @Override
- public void callSessionResumeReceived(IImsCallSession session, ImsCallProfile profile) {
- // no-op
- }
-
- /**
- * Notifies the result of call merge operation.
- */
- @Override
- public void callSessionMergeStarted(IImsCallSession session, IImsCallSession newSession,
- ImsCallProfile profile) {
- // no-op
- }
-
- @Override
- public void callSessionMergeComplete(IImsCallSession session) {
- // no-op
- }
-
- @Override
- public void callSessionMergeFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- /**
- * Notifies the result of call upgrade / downgrade or any other call
- * updates.
- */
- @Override
- public void callSessionUpdated(IImsCallSession session, ImsCallProfile profile) {
- // no-op
- }
-
- @Override
- public void callSessionUpdateFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- @Override
- public void callSessionUpdateReceived(IImsCallSession session, ImsCallProfile profile) {
- // no-op
- }
-
- /**
- * Notifies the result of conference extension.
- */
- @Override
- public void callSessionConferenceExtended(IImsCallSession session, IImsCallSession newSession,
- ImsCallProfile profile) {
- // no-op
- }
-
- @Override
- public void callSessionConferenceExtendFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- @Override
- public void callSessionConferenceExtendReceived(IImsCallSession session,
- IImsCallSession newSession,
- ImsCallProfile profile) {
- // no-op
- }
-
- /**
- * Notifies the result of the participant invitation / removal to/from the
- * conference session.
- */
- @Override
- public void callSessionInviteParticipantsRequestDelivered(IImsCallSession session) {
- // no-op
- }
-
- @Override
- public void callSessionInviteParticipantsRequestFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- @Override
- public void callSessionRemoveParticipantsRequestDelivered(IImsCallSession session) {
- // no-op
- }
-
- @Override
- public void callSessionRemoveParticipantsRequestFailed(IImsCallSession session,
- ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- /**
- * Notifies the changes of the conference info. the conference session.
- */
- @Override
- public void callSessionConferenceStateUpdated(IImsCallSession session,
- ImsConferenceState state) {
- // no-op
- }
-
- /**
- * Notifies the incoming USSD message.
- */
- @Override
- public void callSessionUssdMessageReceived(IImsCallSession session, int mode,
- String ussdMessage) {
- // no-op
- }
-
- /**
- * Notifies of a case where a {@link com.android.ims.internal.ImsCallSession} may potentially
- * handover from one radio technology to another.
- * @param session
- * @param srcAccessTech The source radio access technology; one of the access technology
- * constants defined in {@link android.telephony.ServiceState}. For
- * example {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
- * @param targetAccessTech The target radio access technology; one of the access technology
- * constants defined in {@link android.telephony.ServiceState}. For
- * example {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
- */
- @Override
- public void callSessionMayHandover(IImsCallSession session, int srcAccessTech,
- int targetAccessTech) {
- // no-op
- }
-
- /**
- * Notifies of handover information for this call
- */
- @Override
- public void callSessionHandover(IImsCallSession session, int srcAccessTech,
- int targetAccessTech,
- ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- @Override
- public void callSessionHandoverFailed(IImsCallSession session, int srcAccessTech,
- int targetAccessTech,
- ImsReasonInfo reasonInfo) {
- // no-op
- }
-
- /**
- * Notifies the TTY mode change by remote party.
- *
- * @param mode one of the following: -
- * {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} -
- * {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} -
- * {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} -
- * {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
- */
- @Override
- public void callSessionTtyModeReceived(IImsCallSession session, int mode) {
- // no-op
- }
-
- /**
- * Notifies of a change to the multiparty state for this
- * {@code ImsCallSession}.
- *
- * @param session The call session.
- * @param isMultiParty {@code true} if the session became multiparty,
- * {@code false} otherwise.
- */
- @Override
- public void callSessionMultipartyStateChanged(IImsCallSession session, boolean isMultiParty) {
- // no-op
- }
-
- /**
- * Notifies the supplementary service information for the current session.
- */
- @Override
- public void callSessionSuppServiceReceived(IImsCallSession session,
- ImsSuppServiceNotification suppSrvNotification) {
- // no-op
- }
-
- /**
- * Received RTT modify request from Remote Party
- * @param session The call session.
- * @param callProfile ImsCallProfile with updated attribute
- */
- @Override
- public void callSessionRttModifyRequestReceived(IImsCallSession session,
- ImsCallProfile callProfile) {
- // no-op
- }
-
- /**
- * Received response for RTT modify request
- * @param status true : Accepted the request
- * false : Declined the request
- */
- @Override
- public void callSessionRttModifyResponseReceived(int status) {
- // no -op
- }
-
- /**
- * Device received RTT message from Remote UE
- * @param rttMessage RTT message received
- */
- @Override
- public void callSessionRttMessageReceived(String rttMessage) {
- // no-op
- }
-}
-
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 1670e6b..dcd7ea7 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 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.
@@ -16,31 +16,24 @@
package android.telephony.ims.stub;
+import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsConfigCallback;
import android.util.Log;
import com.android.ims.ImsConfig;
-import com.android.ims.ImsConfigListener;
-import com.android.ims.internal.IImsConfig;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.ref.WeakReference;
import java.util.HashMap;
-
/**
- * Base implementation of ImsConfig.
- * Override the methods that your implementation of ImsConfig supports.
- *
- * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
- * will break other implementations of ImsConfig maintained by other ImsServices.
- *
- * Provides APIs to get/set the IMS service feature/capability/parameters.
- * The config items include:
- * 1) Items provisioned by the operator.
- * 2) Items configured by user. Mainly service feature class.
+ * Controls the modification of IMS specific configurations. For more information on the supported
+ * IMS configuration constants, see {@link ImsConfig}.
*
* The inner class {@link ImsConfigStub} implements methods of IImsConfig AIDL interface.
* The IImsConfig AIDL interface is called by ImsConfig, which may exist in many other processes.
@@ -51,142 +44,10 @@
* performed every time.
* @hide
*/
-
+@SystemApi
public class ImsConfigImplBase {
- static final private String TAG = "ImsConfigImplBase";
-
- ImsConfigStub mImsConfigStub;
-
- public ImsConfigImplBase(Context context) {
- mImsConfigStub = new ImsConfigStub(this, context);
- }
-
- /**
- * Gets the value for ims service/capabilities parameters from the provisioned
- * value storage. Synchronous blocking call.
- *
- * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @return value in Integer format.
- */
- public int getProvisionedValue(int item) throws RemoteException {
- return -1;
- }
-
- /**
- * Gets the value for ims service/capabilities parameters from the provisioned
- * value storage. Synchronous blocking call.
- *
- * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @return value in String format.
- */
- public String getProvisionedStringValue(int item) throws RemoteException {
- return null;
- }
-
- /**
- * Sets the value for IMS service/capabilities parameters by the operator device
- * management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived. Synchronous blocking call.
- *
- * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @param value in Integer format.
- * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
- */
- public int setProvisionedValue(int item, int value) throws RemoteException {
- return ImsConfig.OperationStatusConstants.FAILED;
- }
-
- /**
- * Sets the value for IMS service/capabilities parameters by the operator device
- * management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived. Synchronous blocking call.
- *
- * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @param value in String format.
- * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
- */
- public int setProvisionedStringValue(int item, String value) throws RemoteException {
- return ImsConfig.OperationStatusConstants.FAILED;
- }
-
- /**
- * Gets the value of the specified IMS feature item for specified network type.
- * This operation gets the feature config value from the master storage (i.e. final
- * value). Asynchronous non-blocking call.
- *
- * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
- * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
- * @param listener feature value returned asynchronously through listener.
- */
- public void getFeatureValue(int feature, int network, ImsConfigListener listener)
- throws RemoteException {
- }
-
- /**
- * Sets the value for IMS feature item for specified network type.
- * This operation stores the user setting in setting db from which master db
- * is derived.
- *
- * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
- * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
- * @param value as defined in com.android.ims.ImsConfig#FeatureValueConstants.
- * @param listener, provided if caller needs to be notified for set result.
- */
- public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
- throws RemoteException {
- }
-
- /**
- * Gets the value for IMS VoLTE provisioned.
- * This should be the same as the operator provisioned value if applies.
- */
- public boolean getVolteProvisioned() throws RemoteException {
- return false;
- }
-
- /**
- * Gets the value for IMS feature item video quality.
- *
- * @param listener Video quality value returned asynchronously through listener.
- */
- public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
- }
-
- /**
- * Sets the value for IMS feature item video quality.
- *
- * @param quality, defines the value of video quality.
- * @param listener, provided if caller needs to be notified for set result.
- */
- public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException {
- }
-
- public IImsConfig getIImsConfig() { return mImsConfigStub; }
-
- /**
- * Updates provisioning value and notifies the framework of the change.
- * Doesn't call #setProvisionedValue and assumes the result succeeded.
- * This should only be used by modem when they implicitly changed provisioned values.
- *
- * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @param value in Integer format.
- */
- public final void notifyProvisionedValueChanged(int item, int value) {
- mImsConfigStub.updateCachedValue(item, value, true);
- }
-
- /**
- * Updates provisioning value and notifies the framework of the change.
- * Doesn't call #setProvisionedValue and assumes the result succeeded.
- * This should only be used by modem when they implicitly changed provisioned values.
- *
- * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @param value in String format.
- */
- public final void notifyProvisionedValueChanged(int item, String value) {
- mImsConfigStub.updateCachedValue(item, value, true);
- }
+ private static final String TAG = "ImsConfigImplBase";
/**
* Implements the IImsConfig AIDL interface, which is called by potentially many processes
@@ -208,32 +69,41 @@
*/
@VisibleForTesting
static public class ImsConfigStub extends IImsConfig.Stub {
- Context mContext;
WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
@VisibleForTesting
- public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Context context) {
- mContext = context;
+ public ImsConfigStub(ImsConfigImplBase imsConfigImplBase) {
mImsConfigImplBaseWeakReference =
new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
}
+ @Override
+ public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException {
+ getImsConfigImpl().addImsConfigCallback(c);
+ }
+
+ @Override
+ public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException {
+ getImsConfigImpl().removeImsConfigCallback(c);
+ }
+
/**
* Gets the value for ims service/capabilities parameters. It first checks its local cache,
- * if missed, it will call ImsConfigImplBase.getProvisionedValue.
+ * if missed, it will call ImsConfigImplBase.getConfigInt.
* Synchronous blocking call.
*
- * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @return value in Integer format.
+ * @param item integer key
+ * @return value in Integer format or {@link #CONFIG_RESULT_UNKNOWN} if
+ * unavailable.
*/
@Override
- public synchronized int getProvisionedValue(int item) throws RemoteException {
+ public synchronized int getConfigInt(int item) throws RemoteException {
if (mProvisionedIntValue.containsKey(item)) {
return mProvisionedIntValue.get(item);
} else {
- int retVal = getImsConfigImpl().getProvisionedValue(item);
+ int retVal = getImsConfigImpl().getConfigInt(item);
if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
updateCachedValue(item, retVal, false);
}
@@ -243,18 +113,18 @@
/**
* Gets the value for ims service/capabilities parameters. It first checks its local cache,
- * if missed, it will call #ImsConfigImplBase.getProvisionedValue.
+ * if missed, it will call #ImsConfigImplBase.getConfigString.
* Synchronous blocking call.
*
- * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param item integer key
* @return value in String format.
*/
@Override
- public synchronized String getProvisionedStringValue(int item) throws RemoteException {
+ public synchronized String getConfigString(int item) throws RemoteException {
if (mProvisionedIntValue.containsKey(item)) {
return mProvisionedStringValue.get(item);
} else {
- String retVal = getImsConfigImpl().getProvisionedStringValue(item);
+ String retVal = getImsConfigImpl().getConfigString(item);
if (retVal != null) {
updateCachedValue(item, retVal, false);
}
@@ -268,16 +138,17 @@
* from which the master value is derived, and write it into local cache.
* Synchronous blocking call.
*
- * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param item integer key
* @param value in Integer format.
- * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+ * @return the result of setting the configuration value, defined as either
+ * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
*/
@Override
- public synchronized int setProvisionedValue(int item, int value) throws RemoteException {
+ public synchronized int setConfigInt(int item, int value) throws RemoteException {
mProvisionedIntValue.remove(item);
- int retVal = getImsConfigImpl().setProvisionedValue(item, value);
+ int retVal = getImsConfigImpl().setConfig(item, value);
if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
- updateCachedValue(item, retVal, true);
+ updateCachedValue(item, value, true);
} else {
Log.d(TAG, "Set provision value of " + item +
" to " + value + " failed with error code " + retVal);
@@ -294,63 +165,21 @@
*
* @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
* @param value in String format.
- * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+ * @return the result of setting the configuration value, defined as either
+ * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
*/
@Override
- public synchronized int setProvisionedStringValue(int item, String value)
+ public synchronized int setConfigString(int item, String value)
throws RemoteException {
mProvisionedStringValue.remove(item);
- int retVal = getImsConfigImpl().setProvisionedStringValue(item, value);
+ int retVal = getImsConfigImpl().setConfig(item, value);
if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
- updateCachedValue(item, retVal, true);
+ updateCachedValue(item, value, true);
}
return retVal;
}
- /**
- * Wrapper function to call ImsConfigImplBase.getFeatureValue.
- */
- @Override
- public void getFeatureValue(int feature, int network, ImsConfigListener listener)
- throws RemoteException {
- getImsConfigImpl().getFeatureValue(feature, network, listener);
- }
-
- /**
- * Wrapper function to call ImsConfigImplBase.setFeatureValue.
- */
- @Override
- public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
- throws RemoteException {
- getImsConfigImpl().setFeatureValue(feature, network, value, listener);
- }
-
- /**
- * Wrapper function to call ImsConfigImplBase.getVolteProvisioned.
- */
- @Override
- public boolean getVolteProvisioned() throws RemoteException {
- return getImsConfigImpl().getVolteProvisioned();
- }
-
- /**
- * Wrapper function to call ImsConfigImplBase.getVideoQuality.
- */
- @Override
- public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
- getImsConfigImpl().getVideoQuality(listener);
- }
-
- /**
- * Wrapper function to call ImsConfigImplBase.setVideoQuality.
- */
- @Override
- public void setVideoQuality(int quality, ImsConfigListener listener)
- throws RemoteException {
- getImsConfigImpl().setVideoQuality(quality, listener);
- }
-
private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
ImsConfigImplBase ref = mImsConfigImplBaseWeakReference.get();
if (ref == null) {
@@ -360,32 +189,228 @@
}
}
- private void sendImsConfigChangedIntent(int item, int value) {
- sendImsConfigChangedIntent(item, Integer.toString(value));
+ private void notifyImsConfigChanged(int item, int value) throws RemoteException {
+ getImsConfigImpl().notifyConfigChanged(item, value);
}
- private void sendImsConfigChangedIntent(int item, String value) {
- Intent configChangedIntent = new Intent(ImsConfig.ACTION_IMS_CONFIG_CHANGED);
- configChangedIntent.putExtra(ImsConfig.EXTRA_CHANGED_ITEM, item);
- configChangedIntent.putExtra(ImsConfig.EXTRA_NEW_VALUE, value);
- if (mContext != null) {
- mContext.sendBroadcast(configChangedIntent);
- }
+ private void notifyImsConfigChanged(int item, String value) throws RemoteException {
+ getImsConfigImpl().notifyConfigChanged(item, value);
}
- protected synchronized void updateCachedValue(int item, int value, boolean notifyChange) {
+ protected synchronized void updateCachedValue(int item, int value, boolean notifyChange)
+ throws RemoteException {
mProvisionedIntValue.put(item, value);
if (notifyChange) {
- sendImsConfigChangedIntent(item, value);
+ notifyImsConfigChanged(item, value);
}
}
- protected synchronized void updateCachedValue(
- int item, String value, boolean notifyChange) {
+ protected synchronized void updateCachedValue(int item, String value,
+ boolean notifyChange) throws RemoteException {
mProvisionedStringValue.put(item, value);
if (notifyChange) {
- sendImsConfigChangedIntent(item, value);
+ notifyImsConfigChanged(item, value);
}
}
}
+
+ /**
+ * Callback that the framework uses for receiving Configuration change updates.
+ * {@hide}
+ */
+ public static class Callback extends IImsConfigCallback.Stub {
+
+ @Override
+ public final void onIntConfigChanged(int item, int value) throws RemoteException {
+ onConfigChanged(item, value);
+ }
+
+ @Override
+ public final void onStringConfigChanged(int item, String value) throws RemoteException {
+ onConfigChanged(item, value);
+ }
+
+ /**
+ * Called when the IMS configuration has changed.
+ * @param item the IMS configuration key constant, as defined in ImsConfig.
+ * @param value the new integer value of the IMS configuration constant.
+ */
+ public void onConfigChanged(int item, int value) {
+ // Base Implementation
+ }
+
+ /**
+ * Called when the IMS configuration has changed.
+ * @param item the IMS configuration key constant, as defined in ImsConfig.
+ * @param value the new String value of the IMS configuration constant.
+ */
+ public void onConfigChanged(int item, String value) {
+ // Base Implementation
+ }
+ }
+
+ /**
+ * The configuration requested resulted in an unknown result. This may happen if the
+ * IMS configurations are unavailable.
+ */
+ public static final int CONFIG_RESULT_UNKNOWN = -1;
+ /**
+ * Setting the configuration value completed.
+ */
+ public static final int CONFIG_RESULT_SUCCESS = 0;
+ /**
+ * Setting the configuration value failed.
+ */
+ public static final int CONFIG_RESULT_FAILED = 1;
+
+ private final RemoteCallbackList<IImsConfigCallback> mCallbacks = new RemoteCallbackList<>();
+ ImsConfigStub mImsConfigStub;
+
+ /**
+ * Used for compatibility between older versions of the ImsService.
+ * @hide
+ */
+ public ImsConfigImplBase(Context context) {
+ mImsConfigStub = new ImsConfigStub(this);
+ }
+
+ public ImsConfigImplBase() {
+ mImsConfigStub = new ImsConfigStub(this);
+ }
+
+ /**
+ * Adds a {@link Callback} to the list of callbacks notified when a value in the configuration
+ * changes.
+ * @param c callback to add.
+ */
+ private void addImsConfigCallback(IImsConfigCallback c) {
+ mCallbacks.register(c);
+ }
+ /**
+ * Removes a {@link Callback} to the list of callbacks notified when a value in the
+ * configuration changes.
+ *
+ * @param c callback to remove.
+ */
+ private void removeImsConfigCallback(IImsConfigCallback c) {
+ mCallbacks.unregister(c);
+ }
+
+ /**
+ * @param item
+ * @param value
+ */
+ private final void notifyConfigChanged(int item, int value) {
+ // can be null in testing
+ if (mCallbacks == null) {
+ return;
+ }
+ mCallbacks.broadcast(c -> {
+ try {
+ c.onIntConfigChanged(item, value);
+ } catch (RemoteException e) {
+ Log.w(TAG, "notifyConfigChanged(int): dead binder in notify, skipping.");
+ }
+ });
+ }
+
+ private void notifyConfigChanged(int item, String value) {
+ // can be null in testing
+ if (mCallbacks == null) {
+ return;
+ }
+ mCallbacks.broadcast(c -> {
+ try {
+ c.onStringConfigChanged(item, value);
+ } catch (RemoteException e) {
+ Log.w(TAG, "notifyConfigChanged(string): dead binder in notify, skipping.");
+ }
+ });
+ }
+
+ /**
+ * @hide
+ */
+ public IImsConfig getIImsConfig() { return mImsConfigStub; }
+
+ /**
+ * Updates provisioning value and notifies the framework of the change.
+ * Doesn't call {@link #setConfig(int,int)} and assumes the result succeeded.
+ * This should only be used when the IMS implementer implicitly changed provisioned values.
+ *
+ * @param item an integer key.
+ * @param value in Integer format.
+ */
+ public final void notifyProvisionedValueChanged(int item, int value) {
+ try {
+ mImsConfigStub.updateCachedValue(item, value, true);
+ } catch (RemoteException e) {
+ Log.w(TAG, "notifyProvisionedValueChanged(int): Framework connection is dead.");
+ }
+ }
+
+ /**
+ * Updates provisioning value and notifies the framework of the change.
+ * Doesn't call {@link #setConfig(int,String)} and assumes the result succeeded.
+ * This should only be used when the IMS implementer implicitly changed provisioned values.
+ *
+ * @param item an integer key.
+ * @param value in String format.
+ */
+ public final void notifyProvisionedValueChanged(int item, String value) {
+ try {
+ mImsConfigStub.updateCachedValue(item, value, true);
+ } catch (RemoteException e) {
+ Log.w(TAG, "notifyProvisionedValueChanged(string): Framework connection is dead.");
+ }
+ }
+
+ /**
+ * Sets the configuration value for this ImsService.
+ *
+ * @param item an integer key.
+ * @param value an integer containing the configuration value.
+ * @return the result of setting the configuration value, defined as either
+ * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+ */
+ public int setConfig(int item, int value) {
+ // Base Implementation - To be overridden.
+ return CONFIG_RESULT_FAILED;
+ }
+
+ /**
+ * Sets the configuration value for this ImsService.
+ *
+ * @param item an integer key.
+ * @param value a String containing the new configuration value.
+ * @return Result of setting the configuration value, defined as either
+ * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+ */
+ public int setConfig(int item, String value) {
+ // Base Implementation - To be overridden.
+ return CONFIG_RESULT_FAILED;
+ }
+
+ /**
+ * Gets the currently stored value configuration value from the ImsService for {@code item}.
+ *
+ * @param item an integer key.
+ * @return configuration value, stored in integer format or {@link #CONFIG_RESULT_UNKNOWN} if
+ * unavailable.
+ */
+ public int getConfigInt(int item) {
+ // Base Implementation - To be overridden.
+ return CONFIG_RESULT_UNKNOWN;
+ }
+
+ /**
+ * Gets the currently stored value configuration value from the ImsService for {@code item}.
+ *
+ * @param item an integer key.
+ * @return configuration value, stored in String format or {@code null} if unavailable.
+ */
+ public String getConfigString(int item) {
+ // Base Implementation - To be overridden.
+ return null;
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 89f95ff..06c35ea 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -16,7 +16,9 @@
package android.telephony.ims.stub;
+import android.annotation.SystemApi;
import android.os.RemoteException;
+import android.util.Log;
import com.android.ims.internal.IImsEcbm;
import com.android.ims.internal.IImsEcbmListener;
@@ -30,22 +32,65 @@
*
* @hide
*/
+@SystemApi
+public class ImsEcbmImplBase {
+ private static final String TAG = "ImsEcbmImplBase";
-public class ImsEcbmImplBase extends IImsEcbm.Stub {
+ private IImsEcbmListener mListener;
+ private IImsEcbm mImsEcbm = new IImsEcbm.Stub() {
+ @Override
+ public void setListener(IImsEcbmListener listener) {
+ mListener = listener;
+ }
- /**
- * Sets the listener.
- */
- @Override
- public void setListener(IImsEcbmListener listener) throws RemoteException {
+ @Override
+ public void exitEmergencyCallbackMode() {
+ ImsEcbmImplBase.this.exitEmergencyCallbackMode();
+ }
+ };
+ /** @hide */
+ public IImsEcbm getImsEcbm() {
+ return mImsEcbm;
}
/**
- * Requests Modem to come out of ECBM mode
+ * This method should be implemented by the IMS provider. Framework will trigger this method to
+ * request to come out of ECBM mode
*/
- @Override
- public void exitEmergencyCallbackMode() throws RemoteException {
+ public void exitEmergencyCallbackMode() {
+ Log.d(TAG, "exitEmergencyCallbackMode() not implemented");
+ }
+ /**
+ * Notifies the framework when the device enters Emergency Callback Mode.
+ *
+ * @throws RuntimeException if the connection to the framework is not available.
+ */
+ public final void enteredEcbm() {
+ Log.d(TAG, "Entered ECBM.");
+ if (mListener != null) {
+ try {
+ mListener.enteredECBM();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Notifies the framework when the device exits Emergency Callback Mode.
+ *
+ * @throws RuntimeException if the connection to the framework is not available.
+ */
+ public final void exitedEcbm() {
+ Log.d(TAG, "Exited ECBM.");
+ if (mListener != null) {
+ try {
+ mListener.exitedECBM();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
}
diff --git a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.aidl b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.aidl
similarity index 93%
rename from telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.aidl
rename to telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.aidl
index e890cf8..e2ae0e8 100644
--- a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.aidl
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.aidl
@@ -14,6 +14,6 @@
* limitations under the License
*/
-package android.telephony.ims.internal.stub;
+package android.telephony.ims.stub;
parcelable ImsFeatureConfiguration;
diff --git a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
similarity index 77%
rename from telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.java
rename to telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index 244c957..98b67c3 100644
--- a/telephony/java/android/telephony/ims/internal/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 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.
@@ -14,29 +14,34 @@
* limitations under the License
*/
-package android.telephony.ims.internal.stub;
+package android.telephony.ims.stub;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.ims.internal.feature.ImsFeature;
+import android.telephony.ims.feature.ImsFeature;
import android.util.ArraySet;
-import java.util.Arrays;
import java.util.Set;
/**
* Container class for IMS Feature configuration. This class contains the features that the
- * ImsService supports, which are defined in {@link ImsFeature.FeatureType}.
+ * ImsService supports, which are defined in {@link ImsFeature} as
+ * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+ * {@link ImsFeature#FEATURE_RCS}.
+ *
* @hide
*/
-public class ImsFeatureConfiguration implements Parcelable {
+@SystemApi
+public final class ImsFeatureConfiguration implements Parcelable {
/**
* Features that this ImsService supports.
*/
private final Set<Integer> mFeatures;
/**
- * Creates an ImsFeatureConfiguration with the features
+ * Builder for {@link ImsFeatureConfiguration} that makes adding supported {@link ImsFeature}s
+ * easier.
*/
public static class Builder {
ImsFeatureConfiguration mConfig;
@@ -72,7 +77,10 @@
* Configuration of the ImsService, which describes which features the ImsService supports
* (for registration).
* @param features an array of feature integers defined in {@link ImsFeature} that describe
- * which features this ImsService supports.
+ * which features this ImsService supports. Supported values are
+ * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+ * {@link ImsFeature#FEATURE_RCS}.
+ * @hide
*/
public ImsFeatureConfiguration(int[] features) {
mFeatures = new ArraySet<>();
@@ -85,7 +93,9 @@
}
/**
- * @return an int[] containing the features that this ImsService supports.
+ * @return an int[] containing the features that this ImsService supports. Supported values are
+ * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+ * {@link ImsFeature#FEATURE_RCS}.
*/
public int[] getServiceFeatures() {
return mFeatures.stream().mapToInt(i->i).toArray();
@@ -95,6 +105,7 @@
mFeatures.add(feature);
}
+ /** @hide */
protected ImsFeatureConfiguration(Parcel in) {
int[] features = in.createIntArray();
if (features != null) {
@@ -130,16 +141,23 @@
dest.writeIntArray(mFeatures.stream().mapToInt(i->i).toArray());
}
+ /**
+ * @hide
+ */
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ImsFeatureConfiguration)) return false;
- ImsFeatureConfiguration that = (ImsFeatureConfiguration) o;
+ ImsFeatureConfiguration
+ that = (ImsFeatureConfiguration) o;
return mFeatures.equals(that.mFeatures);
}
+ /**
+ * @hide
+ */
@Override
public int hashCode() {
return mFeatures.hashCode();
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index 05da9da..ce2d89a 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -16,11 +16,16 @@
package android.telephony.ims.stub;
+import android.annotation.SystemApi;
import android.os.RemoteException;
+import android.util.Log;
+import android.telephony.ims.ImsExternalCallState;
import com.android.ims.internal.IImsExternalCallStateListener;
import com.android.ims.internal.IImsMultiEndpoint;
+import java.util.List;
+
/**
* Base implementation of ImsMultiEndpoint, which implements stub versions of the methods
* in the IImsMultiEndpoint AIDL. Override the methods that your implementation of
@@ -31,23 +36,49 @@
*
* @hide
*/
+@SystemApi
+public class ImsMultiEndpointImplBase {
+ private static final String TAG = "MultiEndpointImplBase";
-public class ImsMultiEndpointImplBase extends IImsMultiEndpoint.Stub {
+ private IImsExternalCallStateListener mListener;
+ private IImsMultiEndpoint mImsMultiEndpoint = new IImsMultiEndpoint.Stub() {
+ @Override
+ public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
+ mListener = listener;
+ }
- /**
- * Sets the listener.
- */
- @Override
- public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
+ @Override
+ public void requestImsExternalCallStateInfo() throws RemoteException {
+ ImsMultiEndpointImplBase.this.requestImsExternalCallStateInfo();
+ }
+ };
+ /** @hide */
+ public IImsMultiEndpoint getIImsMultiEndpoint() {
+ return mImsMultiEndpoint;
}
/**
- * Query API to get the latest Dialog Event Package information
- * Should be invoked only after setListener is done
+ * Notifies framework when Dialog Event Package update is received
+ *
+ * @throws RuntimeException if the connection to the framework is not available.
*/
- @Override
- public void requestImsExternalCallStateInfo() throws RemoteException {
+ public final void onImsExternalCallStateUpdate(List<ImsExternalCallState> externalCallDialogs) {
+ Log.d(TAG, "ims external call state update triggered.");
+ if (mListener != null) {
+ try {
+ mListener.onImsExternalCallStateUpdate(externalCallDialogs);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ /**
+ * This method should be implemented by the IMS provider. Framework will trigger this to get the
+ * latest Dialog Event Package information. Should
+ */
+ public void requestImsExternalCallStateInfo() {
+ Log.d(TAG, "requestImsExternalCallStateInfo() not implemented");
}
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 42af083..4334d3a 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -17,15 +17,16 @@
package android.telephony.ims.stub;
import android.annotation.IntDef;
+import android.annotation.SystemApi;
import android.net.Uri;
-import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.util.Log;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.internal.IImsRegistration;
-import com.android.ims.internal.IImsRegistrationCallback;
+import android.telephony.ims.ImsReasonInfo;
+
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
@@ -36,11 +37,14 @@
* registration for this ImsService has changed status.
* @hide
*/
-
+@SystemApi
public class ImsRegistrationImplBase {
private static final String LOG_TAG = "ImsRegistrationImplBase";
+ /**
+ * @hide
+ */
// Defines the underlying radio technology type that we have registered for IMS over.
@IntDef(flag = true,
value = {
@@ -155,6 +159,9 @@
// Locked on mLock, create unspecified disconnect cause.
private ImsReasonInfo mLastDisconnectCause = new ImsReasonInfo();
+ /**
+ * @hide
+ */
public final IImsRegistration getBinder() {
return mBinder;
}
@@ -171,8 +178,8 @@
/**
* Notify the framework that the device is connected to the IMS network.
*
- * @param imsRadioTech the radio access technology. Valid values are defined in
- * {@link ImsRegistrationTech}.
+ * @param imsRadioTech the radio access technology. Valid values are defined as
+ * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
*/
public final void onRegistered(@ImsRegistrationTech int imsRadioTech) {
updateToState(imsRadioTech, REGISTRATION_STATE_REGISTERED);
@@ -189,8 +196,8 @@
/**
* Notify the framework that the device is trying to connect the IMS network.
*
- * @param imsRadioTech the radio access technology. Valid values are defined in
- * {@link ImsRegistrationTech}.
+ * @param imsRadioTech the radio access technology. Valid values are defined as
+ * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
*/
public final void onRegistering(@ImsRegistrationTech int imsRadioTech) {
updateToState(imsRadioTech, REGISTRATION_STATE_REGISTERING);
@@ -221,6 +228,13 @@
});
}
+ /**
+ * Notify the framework that the handover from the current radio technology to the technology
+ * defined in {@code imsRadioTech} has failed.
+ * @param imsRadioTech The technology that has failed to be changed. Valid values are
+ * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
+ * @param info The {@link ImsReasonInfo} for the failure to change technology.
+ */
public final void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech,
ImsReasonInfo info) {
mCallbacks.broadcast((c) -> {
@@ -233,6 +247,11 @@
});
}
+ /**
+ * The this device's subscriber associated {@link Uri}s have changed, which are used to filter
+ * out this device's {@link Uri}s during conference calling.
+ * @param uris
+ */
public final void onSubscriberAssociatedUriChanged(Uri[] uris) {
mCallbacks.broadcast((c) -> {
try {
@@ -264,6 +283,11 @@
}
}
+ /**
+ * @return the current registration connection type. Valid values are
+ * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}
+ * @hide
+ */
@VisibleForTesting
public final @ImsRegistrationTech int getConnectionType() {
synchronized (mLock) {
diff --git a/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
similarity index 97%
rename from telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java
rename to telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
index 89acc80..0673a38 100644
--- a/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
@@ -14,17 +14,16 @@
* limitations under the License
*/
-package android.telephony.ims.internal.stub;
+package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.os.RemoteException;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
+import android.telephony.ims.aidl.IImsSmsListener;
import android.util.Log;
-import com.android.ims.internal.IImsSmsListener;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -37,7 +36,7 @@
* @hide
*/
@SystemApi
-public class SmsImplBase {
+public class ImsSmsImplBase {
private static final String LOG_TAG = "SmsImplBase";
/** @hide */
@@ -158,7 +157,7 @@
* @param token token provided in {@link #onSmsReceived(int, String, byte[])}
* @param result result of delivering the message. Valid values are:
* {@link #DELIVER_STATUS_OK},
- * {@link #DELIVER_STATUS_OK}
+ * {@link #DELIVER_STATUS_ERROR}
* @param messageRef the message reference
*/
public void acknowledgeSms(int token, @DeliverStatusResult int messageRef, int result) {
@@ -299,9 +298,9 @@
}
/**
- * Called when SmsImpl has been initialized and communication with the framework is set up.
+ * Called when ImsSmsImpl has been initialized and communication with the framework is set up.
* Any attempt by this class to access the framework before this method is called will return
- * with an {@link RuntimeException}.
+ * with a {@link RuntimeException}.
*/
public void onReady() {
// Base Implementation - Should be overridden
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index 054a8b2..fcd7faf 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -16,177 +16,332 @@
package android.telephony.ims.stub;
+import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.RemoteException;
+import android.telephony.ims.ImsUtListener;
import com.android.ims.internal.IImsUt;
import com.android.ims.internal.IImsUtListener;
/**
- * Base implementation of ImsUt, which implements stub versions of the methods
- * in the IImsUt AIDL. Override the methods that your implementation of ImsUt supports.
- *
- * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
- * will break other implementations of ImsUt maintained by other ImsServices.
- *
- * Provides the Ut interface interworking to get/set the supplementary service configuration.
+ * Base implementation of IMS UT interface, which implements stubs. Override these methods to
+ * implement functionality.
*
* @hide
*/
+// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+// will break other implementations of ImsUt maintained by other ImsServices.
+@SystemApi
+public class ImsUtImplBase {
-public class ImsUtImplBase extends IImsUt.Stub {
+ private IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
+ @Override
+ public void close() throws RemoteException {
+ ImsUtImplBase.this.close();
+ }
+
+ @Override
+ public int queryCallBarring(int cbType) throws RemoteException {
+ return ImsUtImplBase.this.queryCallBarring(cbType);
+ }
+
+ @Override
+ public int queryCallForward(int condition, String number) throws RemoteException {
+ return ImsUtImplBase.this.queryCallForward(condition, number);
+ }
+
+ @Override
+ public int queryCallWaiting() throws RemoteException {
+ return ImsUtImplBase.this.queryCallWaiting();
+ }
+
+ @Override
+ public int queryCLIR() throws RemoteException {
+ return ImsUtImplBase.this.queryCLIR();
+ }
+
+ @Override
+ public int queryCLIP() throws RemoteException {
+ return ImsUtImplBase.this.queryCLIP();
+ }
+
+ @Override
+ public int queryCOLR() throws RemoteException {
+ return ImsUtImplBase.this.queryCOLR();
+ }
+
+ @Override
+ public int queryCOLP() throws RemoteException {
+ return ImsUtImplBase.this.queryCOLP();
+ }
+
+ @Override
+ public int transact(Bundle ssInfo) throws RemoteException {
+ return ImsUtImplBase.this.transact(ssInfo);
+ }
+
+ @Override
+ public int updateCallBarring(int cbType, int action, String[] barrList) throws
+ RemoteException {
+ return ImsUtImplBase.this.updateCallBarring(cbType, action, barrList);
+ }
+
+ @Override
+ public int updateCallForward(int action, int condition, String number, int serviceClass,
+ int timeSeconds) throws RemoteException {
+ return ImsUtImplBase.this.updateCallForward(action, condition, number, serviceClass,
+ timeSeconds);
+ }
+
+ @Override
+ public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException {
+ return ImsUtImplBase.this.updateCallWaiting(enable, serviceClass);
+ }
+
+ @Override
+ public int updateCLIR(int clirMode) throws RemoteException {
+ return ImsUtImplBase.this.updateCLIR(clirMode);
+ }
+
+ @Override
+ public int updateCLIP(boolean enable) throws RemoteException {
+ return ImsUtImplBase.this.updateCLIP(enable);
+ }
+
+ @Override
+ public int updateCOLR(int presentation) throws RemoteException {
+ return ImsUtImplBase.this.updateCOLR(presentation);
+ }
+
+ @Override
+ public int updateCOLP(boolean enable) throws RemoteException {
+ return ImsUtImplBase.this.updateCOLP(enable);
+ }
+
+ @Override
+ public void setListener(IImsUtListener listener) throws RemoteException {
+ ImsUtImplBase.this.setListener(new ImsUtListener(listener));
+ }
+
+ @Override
+ public int queryCallBarringForServiceClass(int cbType, int serviceClass)
+ throws RemoteException {
+ return ImsUtImplBase.this.queryCallBarringForServiceClass(cbType, serviceClass);
+ }
+
+ @Override
+ public int updateCallBarringForServiceClass(int cbType, int action,
+ String[] barrList, int serviceClass) throws RemoteException {
+ return ImsUtImplBase.this.updateCallBarringForServiceClass(
+ cbType, action, barrList, serviceClass);
+ }
+ };
/**
- * Closes the object. This object is not usable after being closed.
+ * Called when the framework no longer needs to interact with the IMS UT implementation any
+ * longer.
*/
- @Override
- public void close() throws RemoteException {
+ public void close() {
}
/**
- * Retrieves the configuration of the call barring.
+ * Retrieves the call barring configuration.
+ * @param cbType
*/
- @Override
- public int queryCallBarring(int cbType) throws RemoteException {
+ public int queryCallBarring(int cbType) {
return -1;
}
/**
* Retrieves the configuration of the call barring for specified service class.
*/
- @Override
- public int queryCallBarringForServiceClass(int cbType, int serviceClass)
- throws RemoteException {
+ public int queryCallBarringForServiceClass(int cbType, int serviceClass) {
return -1;
}
/**
* Retrieves the configuration of the call forward.
*/
- @Override
- public int queryCallForward(int condition, String number) throws RemoteException {
+ public int queryCallForward(int condition, String number) {
return -1;
}
/**
* Retrieves the configuration of the call waiting.
*/
- @Override
- public int queryCallWaiting() throws RemoteException {
+ public int queryCallWaiting() {
return -1;
}
/**
* Retrieves the default CLIR setting.
+ * @hide
*/
- @Override
- public int queryCLIR() throws RemoteException {
+ public int queryCLIR() {
+ return queryClir();
+ }
+
+ /**
+ * Retrieves the CLIP call setting.
+ * @hide
+ */
+ public int queryCLIP() {
+ return queryClip();
+ }
+
+ /**
+ * Retrieves the COLR call setting.
+ * @hide
+ */
+ public int queryCOLR() {
+ return queryColr();
+ }
+
+ /**
+ * Retrieves the COLP call setting.
+ * @hide
+ */
+ public int queryCOLP() {
+ return queryColp();
+ }
+
+ /**
+ * Retrieves the default CLIR setting.
+ */
+ public int queryClir() {
return -1;
}
/**
* Retrieves the CLIP call setting.
*/
- @Override
- public int queryCLIP() throws RemoteException {
+ public int queryClip() {
return -1;
}
/**
* Retrieves the COLR call setting.
*/
- @Override
- public int queryCOLR() throws RemoteException {
+ public int queryColr() {
return -1;
}
/**
* Retrieves the COLP call setting.
*/
- @Override
- public int queryCOLP() throws RemoteException {
+ public int queryColp() {
return -1;
}
/**
* Updates or retrieves the supplementary service configuration.
*/
- @Override
- public int transact(Bundle ssInfo) throws RemoteException {
+ public int transact(Bundle ssInfo) {
return -1;
}
/**
* Updates the configuration of the call barring.
*/
- @Override
- public int updateCallBarring(int cbType, int action, String[] barrList) throws RemoteException {
+ public int updateCallBarring(int cbType, int action, String[] barrList) {
return -1;
}
/**
* Updates the configuration of the call barring for specified service class.
*/
- @Override
public int updateCallBarringForServiceClass(int cbType, int action, String[] barrList,
- int serviceClass) throws RemoteException {
+ int serviceClass) {
return -1;
}
/**
* Updates the configuration of the call forward.
*/
- @Override
public int updateCallForward(int action, int condition, String number, int serviceClass,
- int timeSeconds) throws RemoteException {
+ int timeSeconds) {
return 0;
}
/**
* Updates the configuration of the call waiting.
*/
- @Override
- public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException {
+ public int updateCallWaiting(boolean enable, int serviceClass) {
return -1;
}
/**
* Updates the configuration of the CLIR supplementary service.
+ * @hide
*/
- @Override
- public int updateCLIR(int clirMode) throws RemoteException {
+ public int updateCLIR(int clirMode) {
+ return updateClir(clirMode);
+ }
+
+ /**
+ * Updates the configuration of the CLIP supplementary service.
+ * @hide
+ */
+ public int updateCLIP(boolean enable) {
+ return updateClip(enable);
+ }
+
+ /**
+ * Updates the configuration of the COLR supplementary service.
+ * @hide
+ */
+ public int updateCOLR(int presentation) {
+ return updateColr(presentation);
+ }
+
+ /**
+ * Updates the configuration of the COLP supplementary service.
+ * @hide
+ */
+ public int updateCOLP(boolean enable) {
+ return updateColp(enable);
+ }
+
+ /**
+ * Updates the configuration of the CLIR supplementary service.
+ */
+ public int updateClir(int clirMode) {
return -1;
}
/**
* Updates the configuration of the CLIP supplementary service.
*/
- @Override
- public int updateCLIP(boolean enable) throws RemoteException {
+ public int updateClip(boolean enable) {
return -1;
}
/**
* Updates the configuration of the COLR supplementary service.
*/
- @Override
- public int updateCOLR(int presentation) throws RemoteException {
+ public int updateColr(int presentation) {
return -1;
}
/**
* Updates the configuration of the COLP supplementary service.
*/
- @Override
- public int updateCOLP(boolean enable) throws RemoteException {
+ public int updateColp(boolean enable) {
return -1;
}
/**
* Sets the listener.
*/
- @Override
- public void setListener(IImsUtListener listener) throws RemoteException {
+ public void setListener(ImsUtListener listener) {
+ }
+
+ /**
+ * @hide
+ */
+ public IImsUt getInterface() {
+ return mServiceImpl;
}
}
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index cd0c4b1..1dda6bf 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -19,8 +19,9 @@
import android.content.Context;
import android.os.RemoteException;
import android.telephony.Rlog;
-
-import com.android.ims.internal.IImsConfig;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.stub.ImsConfigImplBase;
/**
* Provides APIs to get/set the IMS service feature/capability/parameters.
@@ -46,7 +47,7 @@
/**
* Broadcast action: the configuration was changed
- *
+ * @deprecated Use {@link ImsConfig#addConfigCallback(ImsConfigImplBase.Callback)} instead.
* @hide
*/
public static final String ACTION_IMS_CONFIG_CHANGED =
@@ -70,6 +71,8 @@
/**
* Defines IMS service/capability feature constants.
+ * @deprecated Use
+ * {@link android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability} instead.
*/
public static class FeatureConstants {
public static final int FEATURE_TYPE_UNKNOWN = -1;
@@ -539,84 +542,133 @@
}
public ImsConfig(IImsConfig iconfig, Context context) {
- if (DBG) Rlog.d(TAG, "ImsConfig creates");
+ if (DBG) Rlog.d(TAG, "ImsConfig created");
miConfig = iconfig;
mContext = context;
}
/**
- * Gets the provisioned value for IMS service/capabilities parameters used by IMS stack.
- * This function should not be called from the mainthread as it could block the
- * mainthread.
+ * @deprecated see {@link #getInt(int)} instead.
+ */
+ public int getProvisionedValue(int item) throws ImsException {
+ return getConfigInt(item);
+ }
+
+ /**
+ * Gets the configuration value for IMS service/capabilities parameters used by IMS stack.
*
* @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
* @return the value in Integer format.
- *
- * @throws ImsException if calling the IMS service results in an error.
+ * @throws ImsException if the ImsService is unavailable.
*/
- public int getProvisionedValue(int item) throws ImsException {
+ public int getConfigInt(int item) throws ImsException {
int ret = 0;
try {
- ret = miConfig.getProvisionedValue(item);
+ ret = miConfig.getConfigInt(item);
} catch (RemoteException e) {
- throw new ImsException("getValue()", e,
+ throw new ImsException("getInt()", e,
ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
}
- if (DBG) Rlog.d(TAG, "getProvisionedValue(): item = " + item + ", ret =" + ret);
+ if (DBG) Rlog.d(TAG, "getInt(): item = " + item + ", ret =" + ret);
return ret;
}
/**
- * Gets the provisioned value for IMS service/capabilities parameters used by IMS stack.
- * This function should not be called from the mainthread as it could block the
- * mainthread.
+ * @deprecated see {@link #getConfigString(int)} instead
+ */
+ public String getProvisionedStringValue(int item) throws ImsException {
+ return getConfigString(item);
+ }
+
+ /**
+ * Gets the configuration value for IMS service/capabilities parameters used by IMS stack.
*
* @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
* @return value in String format.
*
- * @throws ImsException if calling the IMS service results in an error.
+ * @throws ImsException if the ImsService is unavailable.
*/
- public String getProvisionedStringValue(int item) throws ImsException {
+ public String getConfigString(int item) throws ImsException {
String ret = "Unknown";
try {
- ret = miConfig.getProvisionedStringValue(item);
+ ret = miConfig.getConfigString(item);
} catch (RemoteException e) {
- throw new ImsException("getProvisionedStringValue()", e,
+ throw new ImsException("getConfigString()", e,
ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
}
- if (DBG) Rlog.d(TAG, "getProvisionedStringValue(): item = " + item + ", ret =" + ret);
+ if (DBG) Rlog.d(TAG, "getConfigString(): item = " + item + ", ret =" + ret);
return ret;
}
/**
- * Sets the value for IMS service/capabilities parameters by
- * the operator device management entity.
- * This function should not be called from main thread as it could block
- * mainthread.
+ * @deprecated see {@link #setConfig(int, int)} instead.
+ */
+ public int setProvisionedValue(int item, int value) throws ImsException {
+ return setConfig(item, value);
+ }
+
+ /**
+ * @deprecated see {@link #setConfig(int, String)} instead.
+ */
+ public int setProvisionedStringValue(int item, String value) throws ImsException {
+ return setConfig(item, value);
+ }
+
+ /**
+ * Sets the value for ImsService configuration item.
*
* @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
* @param value in Integer format.
* @return as defined in com.android.ims.ImsConfig#OperationStatusConstants
*
- * @throws ImsException if calling the IMS service results in an error.
+ * @throws ImsException if the ImsService is unavailable.
*/
- public int setProvisionedValue(int item, int value)
- throws ImsException {
+ public int setConfig(int item, int value) throws ImsException {
int ret = OperationStatusConstants.UNKNOWN;
if (DBG) {
- Rlog.d(TAG, "setProvisionedValue(): item = " + item +
+ Rlog.d(TAG, "setConfig(): item = " + item +
"value = " + value);
}
try {
- ret = miConfig.setProvisionedValue(item, value);
+ ret = miConfig.setConfigInt(item, value);
} catch (RemoteException e) {
- throw new ImsException("setProvisionedValue()", e,
+ throw new ImsException("setConfig()", e,
ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
}
if (DBG) {
- Rlog.d(TAG, "setProvisionedValue(): item = " + item +
+ Rlog.d(TAG, "setConfig(): item = " + item +
+ " value = " + value + " ret = " + ret);
+ }
+
+ return ret;
+
+ }
+
+ /**
+ * Sets the value for ImsService configuration item.
+ *
+ * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+ * @param value in Integer format.
+ * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants
+ *
+ * @throws ImsException if the ImsService is unavailable.
+ */
+ public int setConfig(int item, String value) throws ImsException {
+ int ret = OperationStatusConstants.UNKNOWN;
+ if (DBG) {
+ Rlog.d(TAG, "setConfig(): item = " + item +
+ "value = " + value);
+ }
+ try {
+ ret = miConfig.setConfigString(item, value);
+ } catch (RemoteException e) {
+ throw new ImsException("setConfig()", e,
+ ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
+ }
+ if (DBG) {
+ Rlog.d(TAG, "setConfig(): item = " + item +
" value = " + value + " ret = " + ret);
}
@@ -624,79 +676,32 @@
}
/**
- * Sets the value for IMS service/capabilities parameters by
- * the operator device management entity.
- * This function should not be called from main thread as it could block
- * mainthread.
+ * Adds a {@link ImsConfigImplBase.Callback} to the ImsService to notify when a Configuration
+ * item has changed.
*
- * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
- * @param value in String format.
- * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants
- *
- * @throws ImsException if calling the IMS service results in an error.
+ * Make sure to call {@link #removeConfigCallback(ImsConfigImplBase.Callback)} when finished
+ * using this callback.
*/
- public int setProvisionedStringValue(int item, String value)
- throws ImsException {
- int ret = OperationStatusConstants.UNKNOWN;
+ public void addConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException {
+ if (DBG) Rlog.d(TAG, "addConfigCallback: " + callback);
try {
- ret = miConfig.setProvisionedStringValue(item, value);
+ miConfig.addImsConfigCallback(callback);
} catch (RemoteException e) {
- throw new ImsException("setProvisionedStringValue()", e,
- ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
- }
- if (DBG) {
- Rlog.d(TAG, "setProvisionedStringValue(): item = " + item +
- ", value =" + value);
- }
-
- return ret;
- }
-
- /**
- * Gets the value for IMS feature item for specified network type.
- *
- * @param feature, defined as in FeatureConstants.
- * @param network, defined as in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
- * @param listener, provided to be notified for the feature on/off status.
- * @return void
- *
- * @throws ImsException if calling the IMS service results in an error.
- */
- public void getFeatureValue(int feature, int network,
- ImsConfigListener listener) throws ImsException {
- if (DBG) {
- Rlog.d(TAG, "getFeatureValue: feature = " + feature + ", network =" + network +
- ", listener =" + listener);
- }
- try {
- miConfig.getFeatureValue(feature, network, listener);
- } catch (RemoteException e) {
- throw new ImsException("getFeatureValue()", e,
+ throw new ImsException("addConfigCallback()", e,
ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
}
}
/**
- * Sets the value for IMS feature item for specified network type.
- *
- * @param feature, as defined in FeatureConstants.
- * @param network, as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
- * @param value, as defined in FeatureValueConstants.
- * @param listener, provided if caller needs to be notified for set result.
- * @return void
- *
- * @throws ImsException if calling the IMS service results in an error.
+ * Removes a {@link ImsConfigImplBase.Callback} from the ImsService that was previously added
+ * by {@link #addConfigCallback(ImsConfigImplBase.Callback)}.
*/
- public void setFeatureValue(int feature, int network, int value,
- ImsConfigListener listener) throws ImsException {
- if (DBG) {
- Rlog.d(TAG, "setFeatureValue: feature = " + feature + ", network =" + network +
- ", value =" + value + ", listener =" + listener);
- }
+ public void removeConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException {
+ if (DBG) Rlog.d(TAG, "removeConfigCallback: " + callback);
try {
- miConfig.setFeatureValue(feature, network, value, listener);
- } catch (RemoteException e) {
- throw new ImsException("setFeatureValue()", e,
+ miConfig.removeImsConfigCallback(callback);
+ } catch (RemoteException e) {
+ throw new ImsException("removeConfigCallback()", e,
ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
}
}
diff --git a/telephony/java/com/android/ims/ImsException.java b/telephony/java/com/android/ims/ImsException.java
index 0e8bad7..f35e886 100644
--- a/telephony/java/com/android/ims/ImsException.java
+++ b/telephony/java/com/android/ims/ImsException.java
@@ -16,6 +16,8 @@
package com.android.ims;
+import android.telephony.ims.ImsReasonInfo;
+
/**
* This class defines a general IMS-related exception.
*
diff --git a/telephony/java/com/android/ims/ImsUtInterface.java b/telephony/java/com/android/ims/ImsUtInterface.java
index 14c184a..c9d4405 100644
--- a/telephony/java/com/android/ims/ImsUtInterface.java
+++ b/telephony/java/com/android/ims/ImsUtInterface.java
@@ -18,6 +18,8 @@
import android.os.Handler;
import android.os.Message;
+import android.telephony.ims.ImsCallForwardInfo;
+import android.telephony.ims.ImsSsInfo;
/**
* Provides APIs for the supplementary service settings using IMS (Ut interface).
diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
index c6fc5e5..203e6cf 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
@@ -17,9 +17,10 @@
package com.android.ims.internal;
import android.os.Message;
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.internal.IImsCallSessionListener;
+import android.telephony.ims.aidl.IImsCallSessionListener;
+
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsStreamMediaProfile;
import com.android.ims.internal.IImsVideoCallProvider;
/**
diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
index 748092d..a8e8b7dd 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
@@ -16,12 +16,12 @@
package com.android.ims.internal;
-import com.android.ims.ImsStreamMediaProfile;
-import com.android.ims.ImsCallProfile;
-import com.android.ims.ImsReasonInfo;
-import com.android.ims.ImsConferenceState;
+import android.telephony.ims.ImsStreamMediaProfile;
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsConferenceState;
import com.android.ims.internal.IImsCallSession;
-import com.android.ims.ImsSuppServiceNotification;
+import android.telephony.ims.ImsSuppServiceNotification;
/**
* A listener type for receiving notification on IMS call session events.
diff --git a/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
index 1621967..b3d8139 100644
--- a/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
@@ -16,7 +16,7 @@
package com.android.ims.internal;
-import com.android.ims.ImsExternalCallState;
+import android.telephony.ims.ImsExternalCallState;
/**
* A listener type for receiving notifications about DEP through IMS
diff --git a/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl b/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl
index 41b1042..b83b130 100644
--- a/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl
@@ -17,9 +17,9 @@
package com.android.ims.internal;
/**
-* Interface from ImsFeature in the ImsService to ImsServiceController.
+ * Interface from ImsFeature in the ImsService to ImsServiceController.
* {@hide}
*/
oneway interface IImsFeatureStatusCallback {
void notifyImsFeatureStatus(int featureStatus);
-}
\ No newline at end of file
+}
diff --git a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
index 10c7f3e..5151192 100644
--- a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
+++ b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
@@ -18,14 +18,12 @@
import android.app.PendingIntent;
-import com.android.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallProfile;
import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsCallSessionListener;
import com.android.ims.internal.IImsConfig;
import com.android.ims.internal.IImsEcbm;
import com.android.ims.internal.IImsMultiEndpoint;
import com.android.ims.internal.IImsRegistrationListener;
-import com.android.ims.internal.IImsSmsListener;
import com.android.ims.internal.IImsUt;
import android.os.Message;
@@ -44,8 +42,7 @@
void addRegistrationListener(in IImsRegistrationListener listener);
void removeRegistrationListener(in IImsRegistrationListener listener);
ImsCallProfile createCallProfile(int sessionId, int callSessionType, int callType);
- IImsCallSession createCallSession(int sessionId, in ImsCallProfile profile,
- IImsCallSessionListener listener);
+ IImsCallSession createCallSession(int sessionId, in ImsCallProfile profile);
IImsCallSession getPendingCallSession(int sessionId, String callId);
IImsUt getUtInterface();
IImsConfig getConfigInterface();
@@ -54,12 +51,4 @@
IImsEcbm getEcbmInterface();
void setUiTTYMode(int uiTtyMode, in Message onComplete);
IImsMultiEndpoint getMultiEndpointInterface();
- // SMS APIs
- void setSmsListener(IImsSmsListener l);
- oneway void sendSms(in int token, int messageRef, String format, String smsc, boolean retry,
- in byte[] pdu);
- oneway void acknowledgeSms(int token, int messageRef, int result);
- oneway void acknowledgeSmsReport(int token, int messageRef, int result);
- String getSmsFormat();
- oneway void onSmsReady();
}
diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
index 15f8726..2212109 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
@@ -16,7 +16,7 @@
package com.android.ims.internal;
-import com.android.ims.ImsReasonInfo;
+import android.telephony.ims.ImsReasonInfo;
import android.net.Uri;
diff --git a/telephony/java/com/android/ims/internal/IImsService.aidl b/telephony/java/com/android/ims/internal/IImsService.aidl
index 406d22d..c3cc6fb 100644
--- a/telephony/java/com/android/ims/internal/IImsService.aidl
+++ b/telephony/java/com/android/ims/internal/IImsService.aidl
@@ -18,7 +18,7 @@
import android.app.PendingIntent;
-import com.android.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallProfile;
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsCallSessionListener;
import com.android.ims.internal.IImsConfig;
diff --git a/telephony/java/com/android/ims/internal/IImsServiceController.aidl b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
index 7ac25ac..857089f 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceController.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
@@ -18,7 +18,6 @@
import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.ims.internal.IImsMMTelFeature;
-import com.android.ims.internal.IImsRegistration;
import com.android.ims.internal.IImsRcsFeature;
/**
@@ -30,5 +29,4 @@
IImsMMTelFeature createMMTelFeature(int slotId, in IImsFeatureStatusCallback c);
IImsRcsFeature createRcsFeature(int slotId, in IImsFeatureStatusCallback c);
void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c);
- IImsRegistration getRegistration(int slotId);
}
diff --git a/telephony/java/com/android/ims/internal/IImsUtListener.aidl b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
index 1bc0369..a603cd3 100644
--- a/telephony/java/com/android/ims/internal/IImsUtListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
@@ -18,11 +18,11 @@
import android.os.Bundle;
-import com.android.ims.ImsCallForwardInfo;
-import com.android.ims.ImsSsData;
-import com.android.ims.ImsSsInfo;
+import android.telephony.ims.ImsCallForwardInfo;
+import android.telephony.ims.ImsSsInfo;
import com.android.ims.internal.IImsUt;
-import com.android.ims.ImsReasonInfo;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsSsData;
/**
* {@hide}
diff --git a/telephony/java/com/android/internal/telephony/ExponentialBackoff.java b/telephony/java/com/android/internal/telephony/ExponentialBackoff.java
index 80958c0..f323a0c 100644
--- a/telephony/java/com/android/internal/telephony/ExponentialBackoff.java
+++ b/telephony/java/com/android/internal/telephony/ExponentialBackoff.java
@@ -20,6 +20,8 @@
import android.os.Handler;
import android.os.Looper;
+import com.android.internal.annotations.VisibleForTesting;
+
/** The implementation of exponential backoff with jitter applied. */
public class ExponentialBackoff {
private int mRetryCounter;
@@ -27,8 +29,31 @@
private long mMaximumDelayMs;
private long mCurrentDelayMs;
private int mMultiplier;
- private Runnable mRunnable;
- private Handler mHandler;
+ private final Runnable mRunnable;
+ private final Handler mHandler;
+
+ /**
+ * Implementation of Handler methods, Adapter for testing (can't spy on final methods).
+ */
+ private HandlerAdapter mHandlerAdapter = new HandlerAdapter() {
+ @Override
+ public boolean postDelayed(Runnable runnable, long delayMillis) {
+ return mHandler.postDelayed(runnable, delayMillis);
+ }
+
+ @Override
+ public void removeCallbacks(Runnable runnable) {
+ mHandler.removeCallbacks(runnable);
+ }
+ };
+
+ /**
+ * Need to spy final methods for testing.
+ */
+ public interface HandlerAdapter {
+ boolean postDelayed(Runnable runnable, long delayMillis);
+ void removeCallbacks(Runnable runnable);
+ }
public ExponentialBackoff(
long initialDelayMs,
@@ -57,14 +82,14 @@
public void start() {
mRetryCounter = 0;
mCurrentDelayMs = mStartDelayMs;
- mHandler.removeCallbacks(mRunnable);
- mHandler.postDelayed(mRunnable, mCurrentDelayMs);
+ mHandlerAdapter.removeCallbacks(mRunnable);
+ mHandlerAdapter.postDelayed(mRunnable, mCurrentDelayMs);
}
/** Stops the backoff, all pending messages will be removed from the message queue. */
public void stop() {
mRetryCounter = 0;
- mHandler.removeCallbacks(mRunnable);
+ mHandlerAdapter.removeCallbacks(mRunnable);
}
/** Should call when the retry action has failed and we want to retry after a longer delay. */
@@ -73,12 +98,17 @@
long temp = Math.min(
mMaximumDelayMs, (long) (mStartDelayMs * Math.pow(mMultiplier, mRetryCounter)));
mCurrentDelayMs = (long) (((1 + Math.random()) / 2) * temp);
- mHandler.removeCallbacks(mRunnable);
- mHandler.postDelayed(mRunnable, mCurrentDelayMs);
+ mHandlerAdapter.removeCallbacks(mRunnable);
+ mHandlerAdapter.postDelayed(mRunnable, mCurrentDelayMs);
}
/** Returns the delay for the most recently posted message. */
public long getCurrentDelay() {
return mCurrentDelayMs;
}
+
+ @VisibleForTesting
+ public void setHandlerAdapter(HandlerAdapter a) {
+ mHandlerAdapter = a;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index f8a040d..0ed0820 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -202,14 +202,6 @@
String[] getIsimPcscf(int subId);
/**
- * TODO: Deprecate and remove this interface. Superceded by getIccsimChallengeResponse.
- * Returns the response of ISIM Authetification through RIL.
- * @return the response of ISIM Authetification, or null if
- * the Authentification hasn't been successed or isn't present iphonesubinfo.
- */
- String getIsimChallengeResponse(String nonce);
-
- /**
* Returns the response of the SIM application on the UICC to authentication
* challenge/response algorithm. The data string and challenge response are
* Base64 encoded Strings.
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index dfb3c34..2b4c059 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -38,9 +38,10 @@
import android.telephony.SignalStrength;
import android.telephony.TelephonyHistogram;
import android.telephony.VisualVoicemailSmsFilterSettings;
-import com.android.ims.internal.IImsMMTelFeature;
-import com.android.ims.internal.IImsRcsFeature;
-import com.android.ims.internal.IImsRegistration;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsMmTelFeature;
+import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IImsRegistration;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.OperatorInfo;
@@ -680,6 +681,7 @@
* Input parameters equivalent to TS 27.007 AT+CSIM command.
*
* @param subId The subscription to use.
+ * @param callingPackage the name of the package making the call.
* @param cla Class of the APDU command.
* @param instruction Instruction of the APDU command.
* @param p1 P1 value of the APDU command.
@@ -690,7 +692,7 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
*/
- String iccTransmitApduBasicChannel(int subId, int cla, int instruction,
+ String iccTransmitApduBasicChannel(int subId, String callingPackage, int cla, int instruction,
int p1, int p2, int p3, String data);
/**
@@ -787,20 +789,21 @@
int getTetherApnRequired();
/**
- * Get IImsMMTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature
- * as well as registering the MMTelFeature for callbacks using the IImsServiceFeatureCallback
- * interface.
- */
- IImsMMTelFeature getMMTelFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback);
+ * Enables framework IMS and triggers IMS Registration.
+ */
+ void enableIms(int slotId);
/**
- * Get IImsMMTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature
- * as well as registering the MMTelFeature for callbacks using the IImsServiceFeatureCallback
+ * Disables framework IMS and triggers IMS deregistration.
+ */
+ void disableIms(int slotId);
+
+ /**
+ * Get IImsMmTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature
+ * as well as registering the MmTelFeature for callbacks using the IImsServiceFeatureCallback
* interface.
- * Used for emergency calling only.
*/
- IImsMMTelFeature getEmergencyMMTelFeatureAndListen(int slotId,
- in IImsServiceFeatureCallback callback);
+ IImsMmTelFeature getMmTelFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback);
/**
* Get IImsRcsFeature binder from ImsResolver that corresponds to the subId and RCS feature
@@ -815,6 +818,11 @@
IImsRegistration getImsRegistration(int slotId, int feature);
/**
+ * Returns the IImsConfig associated with the slot and feature specified.
+ */
+ IImsConfig getImsConfig(int slotId, int feature);
+
+ /**
* Set the network selection mode to automatic.
*
* @param subId the id of the subscription to update.
diff --git a/test-base/Android.bp b/test-base/Android.bp
index ccf57b0..62fed61 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -83,28 +83,3 @@
"junit",
],
}
-
-// Build the legacy-android-test library
-// =====================================
-// This contains the android.test classes that were in Android API level 25,
-// including those from android.test.runner.
-// Also contains the com.android.internal.util.Predicate[s] classes.
-java_library_static {
- name: "legacy-android-test",
-
- srcs: [
- "src/android/**/*.java",
- "src/com/**/*.java",
- ],
-
- static_libs: [
- "android.test.runner-minus-junit",
- "android.test.mock",
- ],
-
- no_framework_libs: true,
- libs: [
- "framework",
- "junit",
- ],
-}
diff --git a/test-legacy/Android.bp b/test-legacy/Android.bp
new file mode 100644
index 0000000..d2af8a9
--- /dev/null
+++ b/test-legacy/Android.bp
@@ -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.
+//
+
+// Build the legacy-android-test library
+// =====================================
+// This contains the android.test classes that were in Android API level 25,
+// including those from android.test.runner.
+// Also contains the com.android.internal.util.Predicate[s] classes.
+java_library_static {
+ name: "legacy-android-test",
+
+ static_libs: [
+ "android.test.base-minus-junit",
+ "android.test.runner-minus-junit",
+ "android.test.mock",
+ ],
+
+ no_framework_libs: true,
+ libs: [
+ "framework",
+ "junit",
+ ],
+}
diff --git a/test-legacy/Android.mk b/test-legacy/Android.mk
new file mode 100644
index 0000000..b8c5326
--- /dev/null
+++ b/test-legacy/Android.mk
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+# For unbundled build we'll use the prebuilt jar from prebuilts/sdk.
+ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
+
+# Build the android.test.legacy library
+# =====================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := android.test.legacy
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_JAVA_LIBRARIES := junit
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android.test.base-minus-junit \
+ android.test.runner-minus-junit \
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Archive a copy of the classes.jar in SDK build.
+$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.legacy.jar)
+
+endif # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
diff --git a/test-mock/Android.mk b/test-mock/Android.mk
index 7926a77..5c586c7 100644
--- a/test-mock/Android.mk
+++ b/test-mock/Android.mk
@@ -31,7 +31,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(android_test_mock_source_files)
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework conscrypt okhttp bouncycastle
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src/android/test/mock
@@ -116,7 +116,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(android_test_mock_source_files)
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework conscrypt okhttp bouncycastle
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src/android/test/mock
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index f5c2bc6..706f636 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -117,20 +117,5 @@
endif # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true
-# Build the android.test.legacy library
-# =====================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := android.test.legacy
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src/android)
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_JAVA_LIBRARIES := android.test.mock.stubs junit
-LOCAL_STATIC_JAVA_LIBRARIES := android.test.base-minus-junit
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
# additionally, build unit tests in a separate .apk
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/FrameworkPerf/AndroidManifest.xml b/tests/FrameworkPerf/AndroidManifest.xml
index d62ef9e..2591aaf 100644
--- a/tests/FrameworkPerf/AndroidManifest.xml
+++ b/tests/FrameworkPerf/AndroidManifest.xml
@@ -1,6 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.frameworkperf">
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-sdk android:minSdkVersion="5" />
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index ebf5f68..c8f96c9 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -285,7 +285,8 @@
<activity
android:name="ColoredShadowsActivity"
- android:label="View/ColoredShadows">
+ android:label="View/ColoredShadows"
+ android:theme="@style/ThemeColoredShadows">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.test.hwui.TEST" />
diff --git a/tests/HwAccelerationTest/res/values/styles.xml b/tests/HwAccelerationTest/res/values/styles.xml
index 108709b..fa5437f 100644
--- a/tests/HwAccelerationTest/res/values/styles.xml
+++ b/tests/HwAccelerationTest/res/values/styles.xml
@@ -34,4 +34,11 @@
<item name="android:translationZ">400dp</item>
<item name="android:layout_alignParentBottom">true</item>
</style>
+
+ <style name="ThemeColoredShadows" parent="@android:style/Theme.Material.Light">
+ <!--
+ <item name="android:ambientShadowAlpha">0</item>
+ <item name="android:spotShadowAlpha">1</item>
+ -->
+ </style>
</resources>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java
index 135c93c..901d90e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java
@@ -17,6 +17,9 @@
package com.android.test.hwui;
import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
@@ -36,7 +39,9 @@
private void setShadowColors(ViewGroup row, int rowIndex) {
for (int i = 0; i < row.getChildCount(); i++) {
View view = row.getChildAt(i);
- view.setShadowColor(shadowColorFor(view));
+ //view.setBackground(new MyHackyBackground());
+ view.setOutlineSpotShadowColor(shadowColorFor(view));
+ view.setOutlineAmbientShadowColor(shadowColorFor(view));
view.setElevation(6.0f * (rowIndex + 1));
}
}
@@ -44,12 +49,27 @@
private int shadowColorFor(View view) {
switch (view.getId()) {
case R.id.grey: return 0xFF3C4043;
- case R.id.blue: return 0xFF185ABC;
- case R.id.red: return 0xFFB31412;
- case R.id.yellow: return 0xFFEA8600;
- case R.id.green: return 0xFF137333;
+ case R.id.blue: return Color.BLUE;
+ case R.id.red: return 0xFFEA4335;
+ case R.id.yellow: return 0xFFFBBC04;
+ case R.id.green: return 0xFF34A853;
default: return 0xFF000000;
}
}
+ private static class MyHackyBackground extends ColorDrawable {
+ MyHackyBackground() {
+ super(0);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public int getAlpha() {
+ return 254;
+ }
+ }
}
diff --git a/tests/OneMedia/AndroidManifest.xml b/tests/OneMedia/AndroidManifest.xml
index 8697f1b..c6824ec 100644
--- a/tests/OneMedia/AndroidManifest.xml
+++ b/tests/OneMedia/AndroidManifest.xml
@@ -5,7 +5,6 @@
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="19"/>
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
diff --git a/tests/UsbTests/Android.mk b/tests/UsbTests/Android.mk
new file mode 100644
index 0000000..a04f32a
--- /dev/null
+++ b/tests/UsbTests/Android.mk
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ frameworks-base-testutils \
+ android-support-test \
+ mockito-target-inline-minus-junit4 \
+ platform-test-annotations \
+ services.core \
+ services.net \
+ services.usb \
+ truth-prebuilt \
+
+LOCAL_JNI_SHARED_LIBRARIES := \
+ libdexmakerjvmtiagent \
+
+LOCAL_CERTIFICATE := platform
+
+LOCAL_PACKAGE_NAME := UsbTests
+
+LOCAL_COMPATIBILITY_SUITE := device-tests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/UsbTests/AndroidManifest.xml b/tests/UsbTests/AndroidManifest.xml
new file mode 100644
index 0000000..5d60695
--- /dev/null
+++ b/tests/UsbTests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.usb" >
+
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
+
+ <application android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.server.usb"
+ android:label="UsbTests"/>
+</manifest>
diff --git a/tests/UsbTests/AndroidTest.xml b/tests/UsbTests/AndroidTest.xml
new file mode 100644
index 0000000..0b623fb
--- /dev/null
+++ b/tests/UsbTests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<!-- 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.
+-->
+<configuration description="Runs sample instrumentation test.">
+ <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="UsbTests.apk"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="UsbTests"/>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.server.usb"/>
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
new file mode 100644
index 0000000..c491b46
--- /dev/null
+++ b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
@@ -0,0 +1,316 @@
+/*
+ * 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.server.usb;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.hardware.usb.UsbManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.FgThread;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Tests for UsbHandler state changes.
+ */
+@RunWith(AndroidJUnit4.class)
+public class UsbHandlerTest {
+ private static final String TAG = UsbHandlerTest.class.getSimpleName();
+
+ @Mock
+ private UsbDeviceManager mUsbDeviceManager;
+ @Mock
+ private UsbDebuggingManager mUsbDebuggingManager;
+ @Mock
+ private UsbAlsaManager mUsbAlsaManager;
+ @Mock
+ private UsbSettingsManager mUsbSettingsManager;
+ @Mock
+ private SharedPreferences mSharedPreferences;
+ @Mock
+ private SharedPreferences.Editor mEditor;
+
+ private MockUsbHandler mUsbHandler;
+
+ private static final int MSG_UPDATE_STATE = 0;
+ private static final int MSG_ENABLE_ADB = 1;
+ private static final int MSG_SET_CURRENT_FUNCTIONS = 2;
+ private static final int MSG_SYSTEM_READY = 3;
+ private static final int MSG_BOOT_COMPLETED = 4;
+ private static final int MSG_USER_SWITCHED = 5;
+ private static final int MSG_UPDATE_USER_RESTRICTIONS = 6;
+ private static final int MSG_SET_SCREEN_UNLOCKED_FUNCTIONS = 12;
+ private static final int MSG_UPDATE_SCREEN_LOCK = 13;
+
+ private Map<String, String> mMockProperties;
+ private Map<String, Integer> mMockGlobalSettings;
+
+ private class MockUsbHandler extends UsbDeviceManager.UsbHandler {
+ boolean mIsUsbTransferAllowed;
+ Intent mBroadcastedIntent;
+
+ MockUsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager,
+ UsbDebuggingManager debuggingManager, UsbAlsaManager alsaManager,
+ UsbSettingsManager settingsManager) {
+ super(looper, context, deviceManager, debuggingManager, alsaManager, settingsManager);
+ mUseUsbNotification = false;
+ mIsUsbTransferAllowed = true;
+ mCurrentUsbFunctionsReceived = true;
+ }
+
+ @Override
+ protected void setEnabledFunctions(long functions, boolean force) {
+ mCurrentFunctions = functions;
+ }
+
+ @Override
+ protected void setSystemProperty(String property, String value) {
+ mMockProperties.put(property, value);
+ }
+
+ @Override
+ protected void putGlobalSettings(ContentResolver resolver, String setting, int val) {
+ mMockGlobalSettings.put(setting, val);
+ }
+
+ @Override
+ protected String getSystemProperty(String property, String def) {
+ if (mMockProperties.containsKey(property)) {
+ return mMockProperties.get(property);
+ }
+ return def;
+ }
+
+ @Override
+ protected boolean isUsbTransferAllowed() {
+ return mIsUsbTransferAllowed;
+ }
+
+ @Override
+ protected SharedPreferences getPinnedSharedPrefs(Context context) {
+ return mSharedPreferences;
+ }
+
+ @Override
+ protected void sendStickyBroadcast(Intent intent) {
+ mBroadcastedIntent = intent;
+ }
+ }
+
+ @Before
+ public void before() {
+ MockitoAnnotations.initMocks(this);
+ mMockProperties = new HashMap<>();
+ mMockGlobalSettings = new HashMap<>();
+ when(mSharedPreferences.edit()).thenReturn(mEditor);
+
+ mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
+ InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbDebuggingManager,
+ mUsbAlsaManager, mUsbSettingsManager);
+ }
+
+ @SmallTest
+ public void setFunctionsMtp() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+ }
+
+ @SmallTest
+ public void setFunctionsPtp() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_PTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_PTP, 0);
+ }
+
+ @SmallTest
+ public void setFunctionsMidi() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MIDI));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MIDI, 0);
+ }
+
+ @SmallTest
+ public void setFunctionsRndis() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_RNDIS));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_RNDIS, 0);
+ }
+
+ @SmallTest
+ public void enableAdb() {
+ sendBootCompleteMessages(mUsbHandler);
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_ENABLE_ADB, 1));
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ assertTrue(mUsbHandler.mAdbEnabled);
+ assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler
+ .USB_PERSISTENT_CONFIG_PROPERTY), UsbManager.USB_FUNCTION_ADB);
+ verify(mUsbDebuggingManager).setAdbEnabled(true);
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1));
+
+ assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false));
+ assertTrue(mUsbHandler.mBroadcastedIntent
+ .getBooleanExtra(UsbManager.USB_CONFIGURED, false));
+ assertTrue(mUsbHandler.mBroadcastedIntent
+ .getBooleanExtra(UsbManager.USB_FUNCTION_ADB, false));
+ }
+
+ @SmallTest
+ public void disableAdb() {
+ mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY,
+ UsbManager.USB_FUNCTION_ADB);
+ mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
+ InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbDebuggingManager,
+ mUsbAlsaManager, mUsbSettingsManager);
+
+ sendBootCompleteMessages(mUsbHandler);
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_ENABLE_ADB, 0));
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ assertFalse(mUsbHandler.mAdbEnabled);
+ assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler
+ .USB_PERSISTENT_CONFIG_PROPERTY), "");
+ verify(mUsbDebuggingManager).setAdbEnabled(false);
+ }
+
+ @SmallTest
+ public void bootCompletedCharging() {
+ sendBootCompleteMessages(mUsbHandler);
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ }
+
+ @Test
+ @SmallTest
+ public void bootCompletedAdbEnabled() {
+ mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY, "adb");
+ mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
+ InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbDebuggingManager,
+ mUsbAlsaManager, mUsbSettingsManager);
+
+ sendBootCompleteMessages(mUsbHandler);
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ assertEquals(mMockGlobalSettings.get(Settings.Global.ADB_ENABLED).intValue(), 1);
+ assertTrue(mUsbHandler.mAdbEnabled);
+ verify(mUsbDebuggingManager).setAdbEnabled(true);
+ }
+
+ @SmallTest
+ public void userSwitchedDisablesMtp() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_USER_SWITCHED,
+ UserHandle.getCallingUserId() + 1));
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ }
+
+ @SmallTest
+ public void changedRestrictionsDisablesMtp() {
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+
+ mUsbHandler.mIsUsbTransferAllowed = false;
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_USER_RESTRICTIONS));
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ }
+
+ @SmallTest
+ public void disconnectResetsCharging() {
+ sendBootCompleteMessages(mUsbHandler);
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 0, 0));
+
+ assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
+ }
+
+ @SmallTest
+ public void configuredSendsBroadcast() {
+ sendBootCompleteMessages(mUsbHandler);
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1));
+
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+ assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false));
+ assertTrue(mUsbHandler.mBroadcastedIntent
+ .getBooleanExtra(UsbManager.USB_CONFIGURED, false));
+ assertTrue(mUsbHandler.mBroadcastedIntent
+ .getBooleanExtra(UsbManager.USB_FUNCTION_MTP, false));
+ }
+
+ @SmallTest
+ public void setScreenUnlockedFunctions() {
+ sendBootCompleteMessages(mUsbHandler);
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0));
+
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS,
+ UsbManager.FUNCTION_MTP));
+ assertNotEquals(mUsbHandler.getScreenUnlockedFunctions() & UsbManager.FUNCTION_MTP, 0);
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+ verify(mEditor).putString(String.format(Locale.ENGLISH,
+ UsbDeviceManager.UNLOCKED_CONFIG_PREF, mUsbHandler.mCurrentUser),
+ UsbManager.USB_FUNCTION_MTP);
+ }
+
+ @SmallTest
+ public void unlockScreen() {
+ when(mSharedPreferences.getString(String.format(Locale.ENGLISH,
+ UsbDeviceManager.UNLOCKED_CONFIG_PREF, mUsbHandler.mCurrentUser), ""))
+ .thenReturn(UsbManager.USB_FUNCTION_MTP);
+ sendBootCompleteMessages(mUsbHandler);
+ mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0));
+
+ assertNotEquals(mUsbHandler.getScreenUnlockedFunctions() & UsbManager.FUNCTION_MTP, 0);
+ assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
+ }
+
+ private static void sendBootCompleteMessages(Handler handler) {
+ handler.handleMessage(handler.obtainMessage(MSG_BOOT_COMPLETED));
+ handler.handleMessage(handler.obtainMessage(MSG_SYSTEM_READY));
+ }
+}
\ No newline at end of file
diff --git a/tests/libs-permissions/Android.mk b/tests/libs-permissions/Android.mk
new file mode 100644
index 0000000..eb38623
--- /dev/null
+++ b/tests/libs-permissions/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product
+LOCAL_PRODUCT_MODULE := true
+LOCAL_SRC_FILES := $(call all-java-files-under, product/java)
+LOCAL_REQUIRED_MODULES := com.android.test.libs.product.xml
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
+LOCAL_SRC_FILES:= product/com.android.test.libs.product.xml
+include $(BUILD_PREBUILT)
diff --git a/libs/androidfw/tests/data/basic/res/layout/layout.xml b/tests/libs-permissions/product/com.android.test.libs.product.xml
similarity index 61%
copy from libs/androidfw/tests/data/basic/res/layout/layout.xml
copy to tests/libs-permissions/product/com.android.test.libs.product.xml
index 045ede4..0a955e9 100644
--- a/libs/androidfw/tests/data/basic/res/layout/layout.xml
+++ b/tests/libs-permissions/product/com.android.test.libs.product.xml
@@ -4,22 +4,17 @@
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.
-->
-<Button xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/ok"
- android:layout_width="0sp"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:layout_marginStart="2dip"
- android:layout_marginEnd="2dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textStyle="bold"
- android:text="@android:string/ok" />
\ No newline at end of file
+
+<permissions>
+ <library name="com.android.test.libs.product"
+ file="/product/framework/com.android.test.libs.product.jar" />
+</permissions>
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl b/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java
similarity index 63%
copy from telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
copy to tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java
index f6005b6..f49b46e 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl
+++ b/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2017 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.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,12 +14,16 @@
* limitations under the License.
*/
-package android.telephony.ims.internal.aidl;
+package com.android.test.libs.product;
/**
- * See RcsFeature for more information.
- * {@hide}
+ * Test class for product libs.
*/
-interface IImsRcsFeature {
- //Empty Default Implementation
-}
\ No newline at end of file
+public class LibsProductTest {
+
+ /**
+ * Dummpy method for testing.
+ */
+ public static void test() {
+ }
+}
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 994f3cc..9130e7d 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -39,6 +39,7 @@
libc++ \
libcrypto \
libcutils \
+ libdexfile \
libframeworksnettestsjni \
libhidl-gen-utils \
libhidlbase \
diff --git a/tests/net/java/com/android/server/NetworkManagementServiceTest.java b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
index 2ac73db..56a075b 100644
--- a/tests/net/java/com/android/server/NetworkManagementServiceTest.java
+++ b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
@@ -99,8 +99,12 @@
@After
public void tearDown() throws Exception {
- if (mSocket != null) mSocket.close();
- if (mServerSocket != null) mServerSocket.close();
+ mNMService.shutdown();
+ // Once NetworkManagementService#shutdown() actually does something and shutdowns
+ // the underlying NativeDaemonConnector, the block below should be uncommented.
+ // if (mOutputStream != null) mOutputStream.close();
+ // if (mSocket != null) mSocket.close();
+ // if (mServerSocket != null) mServerSocket.close();
}
/**
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 9f2cb92..8359fe2 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -66,7 +66,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -175,7 +174,6 @@
}
@Test
- @Ignore
public void testDefaultNetworkEvents() throws Exception {
final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
@@ -294,7 +292,6 @@
}
@Test
- @Ignore
public void testEndToEndLogging() throws Exception {
// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
@@ -635,6 +632,7 @@
when(nai.getCurrentScore()).thenReturn(score);
nai.linkProperties = new LinkProperties();
nai.networkCapabilities = new NetworkCapabilities();
+ nai.lastValidated = true;
for (int t : BitUtils.unpackBits(transports)) {
nai.networkCapabilities.addTransportType(t);
}
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 099cfd4..e692652 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -311,7 +311,7 @@
// Emulate pressing the USB tethering button in Settings UI.
mTethering.startTethering(TETHERING_USB, null, false);
mLooper.dispatchAll();
- verify(mUsbManager, times(1)).setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
+ verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
// Pretend we receive a USB connected broadcast. Here we also pretend
// that the RNDIS function is somehow enabled, so that we see if we
diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk
index b001c8c..3c80ad8 100644
--- a/tests/privapp-permissions/Android.mk
+++ b/tests/privapp-permissions/Android.mk
@@ -29,3 +29,17 @@
LOCAL_SRC_FILES:= vendor/privapp-permissions-test.xml
include $(BUILD_PREBUILT)
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := ProductPrivAppPermissionTest
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MANIFEST_FILE := product/AndroidManifest.xml
+LOCAL_PRODUCT_MODULE := true
+LOCAL_REQUIRED_MODULES := productprivapp-permissions-test.xml
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := productprivapp-permissions-test.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
+LOCAL_SRC_FILES:= product/privapp-permissions-test.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/privapp-permissions/product/AndroidManifest.xml b/tests/privapp-permissions/product/AndroidManifest.xml
new file mode 100644
index 0000000..3d9415c
--- /dev/null
+++ b/tests/privapp-permissions/product/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.framework.permission.privapp.tests.product">
+
+ <!-- MANAGE_USB is signature|privileged -->
+ <uses-permission android:name="android.permission.MANAGE_USB"/>
+</manifest>
diff --git a/tests/privapp-permissions/product/privapp-permissions-test.xml b/tests/privapp-permissions/product/privapp-permissions-test.xml
new file mode 100644
index 0000000..f298f9d
--- /dev/null
+++ b/tests/privapp-permissions/product/privapp-permissions-test.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<permissions>
+ <privapp-permissions package="com.android.framework.permission.privapp.tests.product">
+ <permission name="android.permission.MANAGE_USB"/>
+ </privapp-permissions>
+</permissions>
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index 069360e..df483b2 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -318,7 +318,7 @@
float dimension_value = 4;
float fraction_value = 5;
int32 int_decimal_value = 6;
- uint32 int_hexidecimal_value = 7;
+ uint32 int_hexadecimal_value = 7;
bool boolean_value = 8;
uint32 color_argb8_value = 9;
uint32 color_rgb8_value = 10;
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 81bc2c8..f1eb952 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -792,9 +792,9 @@
val.dataType = android::Res_value::TYPE_INT_DEC;
val.data = static_cast<uint32_t>(pb_prim.int_decimal_value());
} break;
- case pb::Primitive::kIntHexidecimalValue: {
+ case pb::Primitive::kIntHexadecimalValue: {
val.dataType = android::Res_value::TYPE_INT_HEX;
- val.data = pb_prim.int_hexidecimal_value();
+ val.data = pb_prim.int_hexadecimal_value();
} break;
case pb::Primitive::kBooleanValue: {
val.dataType = android::Res_value::TYPE_INT_BOOLEAN;
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index e9622f5..1d00852 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -460,7 +460,7 @@
pb_prim->set_int_decimal_value(static_cast<int32_t>(val.data));
} break;
case android::Res_value::TYPE_INT_HEX: {
- pb_prim->set_int_hexidecimal_value(val.data);
+ pb_prim->set_int_hexadecimal_value(val.data);
} break;
case android::Res_value::TYPE_INT_BOOLEAN: {
pb_prim->set_boolean_value(static_cast<bool>(val.data));
diff --git a/tools/incident_report/main.cpp b/tools/incident_report/main.cpp
index bd1b973..302d739 100644
--- a/tools/incident_report/main.cpp
+++ b/tools/incident_report/main.cpp
@@ -452,9 +452,10 @@
bool adbIncidentWorkaround = true;
pid_t childPid = -1;
vector<string> sections;
+ const char* privacy = NULL;
int opt;
- while ((opt = getopt(argc, argv, "bhi:o:s:tw")) != -1) {
+ while ((opt = getopt(argc, argv, "bhi:o:s:twp:")) != -1) {
switch (opt) {
case 'b':
outputFormat = OUTPUT_PROTO;
@@ -477,6 +478,9 @@
case 'w':
adbIncidentWorkaround = false;
break;
+ case 'p':
+ privacy = optarg;
+ break;
default:
usage(stderr);
return 1;
@@ -526,7 +530,7 @@
}
// TODO: This is what the real implementation will be...
- char const** args = (char const**)malloc(sizeof(char*) * (6 + sections.size()));
+ char const** args = (char const**)malloc(sizeof(char*) * (8 + sections.size()));
int argpos = 0;
args[argpos++] = "adb";
if (adbSerial != NULL) {
@@ -535,6 +539,10 @@
}
args[argpos++] = "shell";
args[argpos++] = "incident";
+ if (privacy != NULL) {
+ args[argpos++] = "-p";
+ args[argpos++] = privacy;
+ }
for (vector<string>::const_iterator it=sections.begin(); it!=sections.end(); it++) {
args[argpos++] = it->c_str();
}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 101b3e2..309bc80 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -108,8 +108,6 @@
boolean isDualBandSupported();
- boolean saveConfiguration(String packageName);
-
DhcpInfo getDhcpInfo();
boolean isScanAlwaysAvailable();
@@ -160,9 +158,6 @@
int getVerboseLoggingLevel();
- void enableAggressiveHandover(int enabled);
- int getAggressiveHandover();
-
void enableWifiConnectivityManager(boolean enabled);
void disableEphemeralNetwork(String SSID, String packageName);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 05dcb33..897b1ea 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1620,19 +1620,14 @@
}
/**
- * Creates a configuration token describing the current network of MIME type
- * application/vnd.wfa.wsc. Can be used to configure WiFi networks via NFC.
+ * WPS has been deprecated from Client mode operation.
*
- * @return hex-string encoded configuration token or null if there is no current network
+ * @return null
* @hide
* @deprecated This API is deprecated
*/
public String getCurrentNetworkWpsNfcConfigurationToken() {
- try {
- return mService.getCurrentNetworkWpsNfcConfigurationToken();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return null;
}
/**
@@ -1693,18 +1688,14 @@
* existing networks. You should assume the network IDs can be different
* after calling this method.
*
- * @return {@code true} if the operation succeeded
+ * @return {@code false} Will always return true.
* @deprecated There is no need to call this method -
* {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)}
* and {@link #removeNetwork(int)} already persist the configurations automatically.
*/
@Deprecated
public boolean saveConfiguration() {
- try {
- return mService.saveConfiguration(mContext.getOpPackageName());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return true;
}
/**
@@ -2851,36 +2842,6 @@
((ActionListener) listener).onSuccess();
}
break;
- case WifiManager.START_WPS_SUCCEEDED:
- if (listener != null) {
- WpsResult result = (WpsResult) message.obj;
- ((WpsCallback) listener).onStarted(result.pin);
- //Listener needs to stay until completion or failure
- synchronized (mListenerMapLock) {
- mListenerMap.put(message.arg2, listener);
- }
- }
- break;
- case WifiManager.WPS_COMPLETED:
- if (listener != null) {
- ((WpsCallback) listener).onSucceeded();
- }
- break;
- case WifiManager.WPS_FAILED:
- if (listener != null) {
- ((WpsCallback) listener).onFailed(message.arg1);
- }
- break;
- case WifiManager.CANCEL_WPS_SUCCEDED:
- if (listener != null) {
- ((WpsCallback) listener).onSucceeded();
- }
- break;
- case WifiManager.CANCEL_WPS_FAILED:
- if (listener != null) {
- ((WpsCallback) listener).onFailed(message.arg1);
- }
- break;
case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
if (listener != null) {
RssiPacketCountInfo info = (RssiPacketCountInfo) message.obj;
@@ -3059,29 +3020,32 @@
}
/**
- * Start Wi-fi Protected Setup
+ * WPS suport has been deprecated from Client mode and this method will immediately trigger
+ * {@link WpsCallback#onFailed(int)} with a generic error.
*
* @param config WPS configuration (does not support {@link WpsInfo#LABEL})
* @param listener for callbacks on success or failure. Can be null.
- * @throws IllegalStateException if the WifiManager instance needs to be
- * initialized again
+ * @throws IllegalStateException if the WifiManager instance needs to be initialized again
* @deprecated This API is deprecated
*/
public void startWps(WpsInfo config, WpsCallback listener) {
- if (config == null) throw new IllegalArgumentException("config cannot be null");
- getChannel().sendMessage(START_WPS, 0, putListener(listener), config);
+ if (listener != null ) {
+ listener.onFailed(ERROR);
+ }
}
/**
- * Cancel any ongoing Wi-fi Protected Setup
+ * WPS support has been deprecated from Client mode and this method will immediately trigger
+ * {@link WpsCallback#onFailed(int)} with a generic error.
*
* @param listener for callbacks on success or failure. Can be null.
- * @throws IllegalStateException if the WifiManager instance needs to be
- * initialized again
+ * @throws IllegalStateException if the WifiManager instance needs to be initialized again
* @deprecated This API is deprecated
*/
public void cancelWps(WpsCallback listener) {
- getChannel().sendMessage(CANCEL_WPS, 0, putListener(listener));
+ if (listener != null) {
+ listener.onFailed(ERROR);
+ }
}
/**
@@ -3568,32 +3532,7 @@
}
/**
- * Set wifi Aggressive Handover. Called from developer settings.
- * @hide
- */
- public void enableAggressiveHandover(int enabled) {
- try {
- mService.enableAggressiveHandover(enabled);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get the WiFi Handover aggressiveness.This is used by settings
- * to decide what to show within the picker.
- * @hide
- */
- public int getAggressiveHandover() {
- try {
- return mService.getAggressiveHandover();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Resets all wifi manager settings back to factory defaults.
+ * Removes all saved wifi networks.
*
* @hide
*/
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index 9f73622..699f54c 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -22,6 +22,8 @@
import android.net.NetworkSpecifier;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import dalvik.system.CloseGuard;
import java.lang.ref.WeakReference;
@@ -142,6 +144,34 @@
}
/**
+ * Access the client ID of the Aware session.
+ *
+ * Note: internal visibility for testing.
+ *
+ * @return The internal client ID.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public int getClientId() {
+ return mClientId;
+ }
+
+ /**
+ * Access the discovery session ID of the Aware session.
+ *
+ * Note: internal visibility for testing.
+ *
+ * @return The internal discovery session ID.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public int getSessionId() {
+ return mSessionId;
+ }
+
+ /**
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
* {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
@@ -246,8 +276,7 @@
* or
* {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}.
* On a RESPONDER this value is used to gate the acceptance of a connection
- * request from only that peer. A RESPONDER may specify a {@code null} -
- * indicating that it will accept connection requests from any device.
+ * request from only that peer.
*
* @return A {@link NetworkSpecifier} to be used to construct
* {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
@@ -255,7 +284,7 @@
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public NetworkSpecifier createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) {
+ public NetworkSpecifier createNetworkSpecifierOpen(@NonNull PeerHandle peerHandle) {
if (mTerminated) {
Log.w(TAG, "createNetworkSpecifierOpen: called on terminated session");
return null;
@@ -295,8 +324,7 @@
* byte[], java.util.List)} or
* {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
- * from only that peer. A RESPONDER may specify a {@code null} - indicating
- * that it will accept connection requests from any device.
+ * from only that peer.
* @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
* the passphrase. Use the
* {@link #createNetworkSpecifierOpen(PeerHandle)} API to
@@ -309,7 +337,7 @@
* [or other varieties of that API].
*/
public NetworkSpecifier createNetworkSpecifierPassphrase(
- @Nullable PeerHandle peerHandle, @NonNull String passphrase) {
+ @NonNull PeerHandle peerHandle, @NonNull String passphrase) {
if (!WifiAwareUtils.validatePassphrase(passphrase)) {
throw new IllegalArgumentException("Passphrase must meet length requirements");
}
@@ -354,8 +382,7 @@
* byte[], java.util.List)} or
* {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
- * from only that peer. A RESPONDER may specify a null - indicating that
- * it will accept connection requests from any device.
+ * from only that peer.
* @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
* encrypting the data-path. Use the
* {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} to specify a
@@ -371,7 +398,7 @@
* @hide
*/
@SystemApi
- public NetworkSpecifier createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
+ public NetworkSpecifier createNetworkSpecifierPmk(@NonNull PeerHandle peerHandle,
@NonNull byte[] pmk) {
if (!WifiAwareUtils.validatePmk(pmk)) {
throw new IllegalArgumentException("PMK must 32 bytes");
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 2f0c316..06a5c2e 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -406,7 +406,7 @@
/** @hide */
public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId,
- PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
+ @NonNull PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
+ ", peerHandle=" + ((peerHandle == null) ? peerHandle : peerHandle.peerId)
@@ -420,12 +420,9 @@
"createNetworkSpecifier: Invalid 'role' argument when creating a network "
+ "specifier");
}
- if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
- if (peerHandle == null) {
- throw new IllegalArgumentException(
- "createNetworkSpecifier: Invalid peer handle (value of null) - not "
- + "permitted on INITIATOR");
- }
+ if (peerHandle == null) {
+ throw new IllegalArgumentException(
+ "createNetworkSpecifier: Invalid peer handle - cannot be null");
}
return new WifiAwareNetworkSpecifier(
@@ -443,7 +440,7 @@
/** @hide */
public NetworkSpecifier createNetworkSpecifier(int clientId, @DataPathRole int role,
- @Nullable byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
+ @NonNull byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
Log.v(TAG, "createNetworkSpecifier: role=" + role
+ ", pmk=" + ((pmk == null) ? "null" : "non-null")
@@ -456,11 +453,9 @@
"createNetworkSpecifier: Invalid 'role' argument when creating a network "
+ "specifier");
}
- if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
- if (peer == null) {
- throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC "
- + "address - null not permitted on INITIATOR");
- }
+ if (peer == null) {
+ throw new IllegalArgumentException(
+ "createNetworkSpecifier: Invalid peer MAC - cannot be null");
}
if (peer != null && peer.length != 6) {
throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC address");
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index f26b9f5..3219653 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -25,6 +25,8 @@
import android.os.Looper;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import dalvik.system.CloseGuard;
import java.lang.ref.WeakReference;
@@ -97,6 +99,20 @@
}
/**
+ * Access the client ID of the Aware session.
+ *
+ * Note: internal visibility for testing.
+ *
+ * @return The internal client ID.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public int getClientId() {
+ return mClientId;
+ }
+
+ /**
* Issue a request to the Aware service to create a new Aware publish discovery session, using
* the specified {@code publishConfig} configuration. The results of the publish operation
* are routed to the callbacks of {@link DiscoverySessionCallback}:
@@ -207,8 +223,7 @@
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
* @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this
* value is used to gate the acceptance of a connection request from only that
- * peer. A RESPONDER may specify a {@code null} - indicating that it will accept
- * connection requests from any device.
+ * peer.
*
* @return A {@link NetworkSpecifier} to be used to construct
* {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
@@ -217,7 +232,7 @@
* [or other varieties of that API].
*/
public NetworkSpecifier createNetworkSpecifierOpen(
- @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer) {
+ @WifiAwareManager.DataPathRole int role, @NonNull byte[] peer) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager");
@@ -246,8 +261,7 @@
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
* @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this
* value is used to gate the acceptance of a connection request from only that
- * peer. A RESPONDER may specify a {@code null} - indicating that it will accept
- * connection requests from any device.
+ * peer.
* @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
* the passphrase. Use {@link #createNetworkSpecifierOpen(int, byte[])} to
* specify an open (unencrypted) link.
@@ -259,7 +273,7 @@
* [or other varieties of that API].
*/
public NetworkSpecifier createNetworkSpecifierPassphrase(
- @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer,
+ @WifiAwareManager.DataPathRole int role, @NonNull byte[] peer,
@NonNull String passphrase) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
@@ -293,8 +307,7 @@
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
* @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this
* value is used to gate the acceptance of a connection request from only that
- * peer. A RESPONDER may specify a null - indicating that it will accept
- * connection requests from any device.
+ * peer.
* @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
* encrypting the data-path. Use the
* {@link #createNetworkSpecifierPassphrase(int, byte[], String)} to specify a
@@ -311,7 +324,7 @@
*/
@SystemApi
public NetworkSpecifier createNetworkSpecifierPmk(
- @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer, @NonNull byte[] pmk) {
+ @WifiAwareManager.DataPathRole int role, @NonNull byte[] peer, @NonNull byte[] pmk) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager");
diff --git a/wifi/tests/src/android/net/wifi/ParcelUtilTest.java b/wifi/tests/src/android/net/wifi/ParcelUtilTest.java
index 6787594..0c3bf3b 100644
--- a/wifi/tests/src/android/net/wifi/ParcelUtilTest.java
+++ b/wifi/tests/src/android/net/wifi/ParcelUtilTest.java
@@ -22,7 +22,7 @@
import static org.junit.Assert.assertNull;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java
index 689ebba..458c43d 100644
--- a/wifi/tests/src/android/net/wifi/ScanResultTest.java
+++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java
@@ -22,7 +22,7 @@
import static org.mockito.Mockito.validateMockitoUsage;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.net.wifi.WifiScanner.ScanSettings;
import org.junit.After;
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
index 1a7dd13..e569efe 100644
--- a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -28,7 +28,7 @@
import android.net.wifi.WifiEnterpriseConfig.Phase2;
import android.os.Parcel;
import android.security.Credentials;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 4b5f645..71ca068 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -35,6 +35,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.*;
@@ -51,7 +52,7 @@
import android.os.Message;
import android.os.Messenger;
import android.os.test.TestLooper;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
@@ -950,4 +951,86 @@
doThrow(new SecurityException()).when(mWifiService).setCountryCode(anyString());
mWifiManager.setCountryCode(TEST_COUNTRY_CODE);
}
+
+ /**
+ * Test that calls to get the current WPS config token return null and do not have any
+ * interactions with WifiServiceImpl.
+ */
+ @Test
+ public void testGetCurrentNetworkWpsNfcConfigurationTokenReturnsNull() {
+ assertNull(mWifiManager.getCurrentNetworkWpsNfcConfigurationToken());
+ verifyNoMoreInteractions(mWifiService);
+ }
+
+
+ class WpsCallbackTester extends WifiManager.WpsCallback {
+ public boolean mStarted = false;
+ public boolean mSucceeded = false;
+ public boolean mFailed = false;
+ public int mFailureCode = -1;
+
+ @Override
+ public void onStarted(String pin) {
+ mStarted = true;
+ }
+
+ @Override
+ public void onSucceeded() {
+ mSucceeded = true;
+ }
+
+ @Override
+ public void onFailed(int reason) {
+ mFailed = true;
+ mFailureCode = reason;
+ }
+
+ }
+
+ /**
+ * Verify that a call to start WPS immediately returns a failure.
+ */
+ @Test
+ public void testStartWpsImmediatelyFailsWithCallback() {
+ WpsCallbackTester wpsCallback = new WpsCallbackTester();
+ mWifiManager.startWps(null, wpsCallback);
+ assertTrue(wpsCallback.mFailed);
+ assertEquals(WifiManager.ERROR, wpsCallback.mFailureCode);
+ assertFalse(wpsCallback.mStarted);
+ assertFalse(wpsCallback.mSucceeded);
+ verifyNoMoreInteractions(mWifiService);
+ }
+
+ /**
+ * Verify that a call to start WPS does not go to WifiServiceImpl if we do not have a callback.
+ */
+ @Test
+ public void testStartWpsDoesNotCallWifiServiceImpl() {
+ mWifiManager.startWps(null, null);
+ verifyNoMoreInteractions(mWifiService);
+ }
+
+ /**
+i * Verify that a call to cancel WPS immediately returns a failure.
+ */
+ @Test
+ public void testCancelWpsImmediatelyFailsWithCallback() {
+ WpsCallbackTester wpsCallback = new WpsCallbackTester();
+ mWifiManager.cancelWps(wpsCallback);
+ assertTrue(wpsCallback.mFailed);
+ assertEquals(WifiManager.ERROR, wpsCallback.mFailureCode);
+ assertFalse(wpsCallback.mStarted);
+ assertFalse(wpsCallback.mSucceeded);
+ verifyNoMoreInteractions(mWifiService);
+ }
+
+ /**
+ * Verify that a call to cancel WPS does not go to WifiServiceImpl if we do not have a callback.
+ */
+ @Test
+ public void testCancelWpsDoesNotCallWifiServiceImpl() {
+ mWifiManager.cancelWps(null);
+ verifyNoMoreInteractions(mWifiService);
+ }
+
}
diff --git a/wifi/tests/src/android/net/wifi/WifiScannerTest.java b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
index a4366d4..96d5a51 100644
--- a/wifi/tests/src/android/net/wifi/WifiScannerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
@@ -25,7 +25,7 @@
import android.os.Handler;
import android.os.Parcel;
import android.os.test.TestLooper;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.net.wifi.WifiScanner.ScanSettings;
import com.android.internal.util.test.BidirectionalAsyncChannelServer;
diff --git a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
index 15641ab..6ecd931 100644
--- a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
@@ -18,7 +18,7 @@
import static org.hamcrest.core.IsEqual.equalTo;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Rule;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
index 2dd0537..0515e06 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
@@ -20,7 +20,7 @@
import static org.junit.Assert.assertEquals;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Rule;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 9cab66a..84e3ed9 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -31,7 +31,7 @@
import android.os.IBinder;
import android.os.Parcel;
import android.os.test.TestLooper;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import libcore.util.HexEncoding;
@@ -1022,7 +1022,7 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testNetworkSpecifierWithClientNullPmk() throws Exception {
- executeNetworkSpecifierWithClient(true, null, null);
+ executeNetworkSpecifierWithClient(new PeerHandle(123412), true, null, null);
}
/**
@@ -1030,7 +1030,7 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testNetworkSpecifierWithClientIncorrectLengthPmk() throws Exception {
- executeNetworkSpecifierWithClient(true, "012".getBytes(), null);
+ executeNetworkSpecifierWithClient(new PeerHandle(123412), true, "012".getBytes(), null);
}
/**
@@ -1038,7 +1038,7 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testNetworkSpecifierWithClientNullPassphrase() throws Exception {
- executeNetworkSpecifierWithClient(false, null, null);
+ executeNetworkSpecifierWithClient(new PeerHandle(123412), false, null, null);
}
/**
@@ -1046,7 +1046,7 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testNetworkSpecifierWithClientShortPassphrase() throws Exception {
- executeNetworkSpecifierWithClient(false, null, "012");
+ executeNetworkSpecifierWithClient(new PeerHandle(123412), false, null, "012");
}
/**
@@ -1054,15 +1054,23 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testNetworkSpecifierWithClientLongPassphrase() throws Exception {
- executeNetworkSpecifierWithClient(false, null,
+ executeNetworkSpecifierWithClient(new PeerHandle(123412), false, null,
"0123456789012345678901234567890123456789012345678901234567890123456789");
}
- private void executeNetworkSpecifierWithClient(boolean doPmk, byte[] pmk, String passphrase)
- throws Exception {
+ /**
+ * Validate that a null PeerHandle triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierWithClientNullPeer() throws Exception {
+ executeNetworkSpecifierWithClient(null, false, null,
+ "0123456789012345678901234567890123456789012345678901234567890123456789");
+ }
+
+ private void executeNetworkSpecifierWithClient(PeerHandle peerHandle, boolean doPmk, byte[] pmk,
+ String passphrase) throws Exception {
final int clientId = 4565;
final int sessionId = 123;
- final PeerHandle peerHandle = new PeerHandle(123412);
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final PublishConfig publishConfig = new PublishConfig.Builder().build();
@@ -1108,7 +1116,8 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testNetworkSpecifierDirectNullPmk() throws Exception {
- executeNetworkSpecifierDirect(true, null, null);
+ executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false), true,
+ null, null);
}
/**
@@ -1116,7 +1125,8 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testNetworkSpecifierDirectIncorrectLengthPmk() throws Exception {
- executeNetworkSpecifierDirect(true, "012".getBytes(), null);
+ executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false), true,
+ "012".getBytes(), null);
}
/**
@@ -1124,7 +1134,8 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testNetworkSpecifierDirectNullPassphrase() throws Exception {
- executeNetworkSpecifierDirect(false, null, null);
+ executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false),
+ false, null, null);
}
/**
@@ -1132,7 +1143,8 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testNetworkSpecifierDirectShortPassphrase() throws Exception {
- executeNetworkSpecifierDirect(false, null, "012");
+ executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false),
+ false, null, "012");
}
/**
@@ -1140,14 +1152,22 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testNetworkSpecifierDirectLongPassphrase() throws Exception {
- executeNetworkSpecifierDirect(false, null,
+ executeNetworkSpecifierDirect(HexEncoding.decode("000102030405".toCharArray(), false),
+ false, null,
"0123456789012345678901234567890123456789012345678901234567890123456789");
}
- private void executeNetworkSpecifierDirect(boolean doPmk, byte[] pmk, String passphrase)
- throws Exception {
+ /**
+ * Validate that a null peer MAC triggers an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testNetworkSpecifierDirectNullPeer() throws Exception {
+ executeNetworkSpecifierDirect(null, false, null, null);
+ }
+
+ private void executeNetworkSpecifierDirect(byte[] someMac, boolean doPmk, byte[] pmk,
+ String passphrase) throws Exception {
final int clientId = 134;
- final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false);
final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
index 56bb437..f32fe59 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
@@ -22,7 +22,7 @@
import android.net.wifi.FakeKeys;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import java.io.BufferedReader;
import java.io.IOException;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java b/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
index 9670bfa..d3f91f0 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
@@ -23,7 +23,7 @@
import android.net.Uri;
import android.net.wifi.WifiSsid;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index afcf3e3..940adc8 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -25,7 +25,7 @@
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.util.Base64;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
index afa9fd6..707b64f 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
@@ -25,7 +25,7 @@
import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.text.TextUtils;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/omadm/XMLParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/omadm/XMLParserTest.java
index c2dcec6..ef478c7 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/omadm/XMLParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/omadm/XMLParserTest.java
@@ -20,7 +20,7 @@
import android.net.wifi.hotspot2.omadm.XMLNode;
import android.net.wifi.hotspot2.omadm.XMLParser;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index 9bfc010..b573adf 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -22,7 +22,7 @@
import android.net.wifi.EAPConstants;
import android.net.wifi.FakeKeys;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
index c41c11f..5c9df6a 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
@@ -20,7 +20,7 @@
import static org.junit.Assert.assertTrue;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
index 2a36764..171d6ff 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
@@ -20,7 +20,7 @@
import static org.junit.Assert.assertTrue;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.util.Base64;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
index 551ed43..2a7526b 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
@@ -20,7 +20,7 @@
import static org.junit.Assert.assertTrue;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.util.Base64;
import org.junit.Test;