Merge "Remove replaced BubbleMetadata methods from SDK." into rvc-dev
diff --git a/Android.bp b/Android.bp
index 6653bd4..30d4409 100644
--- a/Android.bp
+++ b/Android.bp
@@ -548,33 +548,9 @@
],
}
-java_library {
- name: "framework-annotation-proc",
- srcs: [
- ":framework-all-sources",
- "core/java/**/*.logtags",
- ],
- sdk_version: "core_platform",
- libs: [
- "app-compat-annotations",
- "ext",
- "unsupportedappusage",
- ],
-
- installable: false,
- plugins: [
- "compat-changeid-annotation-processor",
- ],
- static_libs: [
- "framework-internal-utils",
- "exoplayer2-extractor",
- "android.hardware.wifi-V1.0-java-constants",
- ]
-}
-
platform_compat_config {
name: "framework-platform-compat-config",
- src: ":framework-annotation-proc",
+ src: ":framework-minus-apex",
}
// A temporary build target that is conditionally included on the bootclasspath if
@@ -1275,7 +1251,22 @@
removed_api_file: "telephony/api/system-removed.txt",
},
},
- defaults: ["framework-module-stubs-defaults-systemapi"],
+ // TODO: make telephony inherit the shared stubs and remove this
+ args: "--show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS" +
+ "\\) " +
+ "--error UnhiddenSystemApi " +
+ "--hide BroadcastBehavior " +
+ "--hide DeprecationMismatch " +
+ "--hide HiddenSuperclass " +
+ "--hide HiddenTypedefConstant " +
+ "--hide HiddenTypeParameter " +
+ "--hide MissingPermission " +
+ "--hide RequiresPermission " +
+ "--hide SdkConstant " +
+ "--hide Todo " +
+ "--hide Typo " +
+ "--hide UnavailableSymbol ",
filter_packages: ["android.telephony"],
sdk_version: "system_current",
}
diff --git a/apex/Android.bp b/apex/Android.bp
index e8f6e6b..5f418d4 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -26,6 +26,20 @@
"--hide Typo " +
"--hide UnavailableSymbol "
+// TODO: modularize this so not every module has the same whitelist
+framework_packages_to_document = [
+ "android",
+ "dalvik",
+ "java",
+ "javax",
+ "junit",
+ "org.apache.http",
+ "org.json",
+ "org.w3c.dom",
+ "org.xml.sax",
+ "org.xmlpull",
+]
+
// TODO: remove the hiding when server classes are cleaned up.
mainline_framework_stubs_args =
mainline_stubs_args +
@@ -54,6 +68,7 @@
args: mainline_framework_stubs_args,
installable: false,
sdk_version: "current",
+ filter_packages: framework_packages_to_document,
check_api: {
current: {
api_file: "api/current.txt",
@@ -72,6 +87,7 @@
libs: ["framework-annotations-lib"],
installable: false,
sdk_version: "system_current",
+ filter_packages: framework_packages_to_document,
check_api: {
current: {
api_file: "api/system-current.txt",
@@ -88,18 +104,30 @@
name: "framework-module-stubs-lib-defaults-publicapi",
installable: false,
sdk_version: "module_current",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/public",
+ },
}
java_defaults {
name: "framework-module-stubs-lib-defaults-systemapi",
installable: false,
sdk_version: "module_current",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/system",
+ },
}
java_defaults {
name: "framework-module-stubs-lib-defaults-module_libs_api",
installable: false,
sdk_version: "module_current",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/module-lib",
+ },
}
// The defaults for module_libs comes in two parts - defaults for API checks
@@ -113,6 +141,7 @@
libs: ["framework-annotations-lib"],
installable: false,
sdk_version: "module_current",
+ filter_packages: framework_packages_to_document,
check_api: {
current: {
api_file: "api/module-lib-current.txt",
@@ -131,12 +160,14 @@
libs: ["framework-annotations-lib"],
installable: false,
sdk_version: "module_current",
+ filter_packages: framework_packages_to_document,
}
stubs_defaults {
name: "service-module-stubs-srcs-defaults",
args: mainline_service_stubs_args,
installable: false,
+ filter_packages: ["com.android."],
check_api: {
current: {
api_file: "api/current.txt",
@@ -153,4 +184,8 @@
// module java_library system_server stub libs.
java_defaults {
name: "service-module-stubs-defaults",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/system-server",
+ },
}
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index c0e3d55..943baae 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
+import android.media.MediaCodec.CryptoInfo;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Pair;
@@ -45,6 +46,7 @@
import com.google.android.exoplayer2.extractor.ts.Ac3Extractor;
import com.google.android.exoplayer2.extractor.ts.Ac4Extractor;
import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
+import com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory;
import com.google.android.exoplayer2.extractor.ts.PsExtractor;
import com.google.android.exoplayer2.extractor.ts.TsExtractor;
import com.google.android.exoplayer2.extractor.wav.WavExtractor;
@@ -385,7 +387,7 @@
/**
* Called once all the data of a sample has been passed to {@link #onSampleDataFound}.
*
- * <p>Also includes sample metadata, like presentation timestamp and flags.
+ * <p>Includes sample metadata, like presentation timestamp and flags.
*
* @param trackIndex The index of the track to which the sample corresponds.
* @param timeMicros The media timestamp associated with the sample, in microseconds.
@@ -395,8 +397,10 @@
* @param offset The number of bytes that have been consumed by {@code
* onSampleDataFound(int, MediaParser.InputReader)} for the specified track, since the
* last byte belonging to the sample whose metadata is being passed.
- * @param cryptoData Encryption data required to decrypt the sample. May be null for
- * unencrypted samples.
+ * @param cryptoInfo Encryption data required to decrypt the sample. May be null for
+ * unencrypted samples. MediaParser may reuse {@link CryptoInfo} instances to avoid
+ * allocations, so implementations of this method must not write to or keep reference to
+ * the fields of this parameter.
*/
void onSampleCompleted(
int trackIndex,
@@ -404,7 +408,7 @@
int flags,
int size,
int offset,
- @Nullable MediaCodec.CryptoInfo cryptoData);
+ @Nullable CryptoInfo cryptoInfo);
}
/**
@@ -646,6 +650,9 @@
private static final Map<String, ExtractorFactory> EXTRACTOR_FACTORIES_BY_NAME;
private static final Map<String, Class> EXPECTED_TYPE_BY_PARAMETER_NAME;
+ private static final String TS_MODE_SINGLE_PMT = "single_pmt";
+ private static final String TS_MODE_MULTI_PMT = "multi_pmt";
+ private static final String TS_MODE_HLS = "hls";
// Instance creation methods.
@@ -819,6 +826,12 @@
+ value.getClass().getSimpleName()
+ " was passed.");
}
+ if (PARAMETER_TS_MODE.equals(parameterName)
+ && !TS_MODE_SINGLE_PMT.equals(value)
+ && !TS_MODE_HLS.equals(value)
+ && !TS_MODE_MULTI_PMT.equals(value)) {
+ throw new IllegalArgumentException(PARAMETER_TS_MODE + " does not accept: " + value);
+ }
mParserParameters.put(parameterName, value);
return this;
}
@@ -887,8 +900,7 @@
mExtractor.init(new ExtractorOutputAdapter());
} else {
for (String parserName : mParserNamesPool) {
- Extractor extractor =
- EXTRACTOR_FACTORIES_BY_NAME.get(parserName).createInstance();
+ Extractor extractor = createExtractor(parserName);
try {
if (extractor.sniff(mExtractorInput)) {
mExtractorName = parserName;
@@ -993,6 +1005,124 @@
mPendingSeekTimeMicros = -1;
}
+ private Extractor createExtractor(String parserName) {
+ int flags = 0;
+ switch (parserName) {
+ case PARSER_NAME_MATROSKA:
+ flags =
+ getBooleanParameter(PARAMETER_MATROSKA_DISABLE_CUES_SEEKING)
+ ? MatroskaExtractor.FLAG_DISABLE_SEEK_FOR_CUES
+ : 0;
+ return new MatroskaExtractor(flags);
+ case PARSER_NAME_FMP4:
+ flags |=
+ getBooleanParameter(PARAMETER_MP4_IGNORE_EDIT_LISTS)
+ ? FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_MP4_IGNORE_TFDT_BOX)
+ ? FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES)
+ ? FragmentedMp4Extractor
+ .FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
+ : 0;
+ return new FragmentedMp4Extractor(flags);
+ case PARSER_NAME_MP4:
+ flags |=
+ getBooleanParameter(PARAMETER_MP4_IGNORE_EDIT_LISTS)
+ ? Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
+ : 0;
+ return new Mp4Extractor();
+ case PARSER_NAME_MP3:
+ flags |=
+ getBooleanParameter(PARAMETER_MP3_DISABLE_ID3)
+ ? Mp3Extractor.FLAG_DISABLE_ID3_METADATA
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_MP3_ENABLE_CBR_SEEKING)
+ ? Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
+ : 0;
+ // TODO: Add index seeking once we update the ExoPlayer version.
+ return new Mp3Extractor(flags);
+ case PARSER_NAME_ADTS:
+ flags |=
+ getBooleanParameter(PARAMETER_ADTS_ENABLE_CBR_SEEKING)
+ ? AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
+ : 0;
+ return new AdtsExtractor(flags);
+ case PARSER_NAME_AC3:
+ return new Ac3Extractor();
+ case PARSER_NAME_TS:
+ flags |=
+ getBooleanParameter(PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES)
+ ? DefaultTsPayloadReaderFactory.FLAG_ALLOW_NON_IDR_KEYFRAMES
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_TS_DETECT_ACCESS_UNITS)
+ ? DefaultTsPayloadReaderFactory.FLAG_DETECT_ACCESS_UNITS
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS)
+ ? DefaultTsPayloadReaderFactory.FLAG_ENABLE_HDMV_DTS_AUDIO_STREAMS
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_TS_IGNORE_AAC_STREAM)
+ ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_AAC_STREAM
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_TS_IGNORE_AVC_STREAM)
+ ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_H264_STREAM
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM)
+ ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_SPLICE_INFO_STREAM
+ : 0;
+ String tsMode = getStringParameter(PARAMETER_TS_MODE, TS_MODE_SINGLE_PMT);
+ int hlsMode =
+ TS_MODE_SINGLE_PMT.equals(tsMode)
+ ? TsExtractor.MODE_SINGLE_PMT
+ : TS_MODE_HLS.equals(tsMode)
+ ? TsExtractor.MODE_HLS
+ : TsExtractor.MODE_MULTI_PMT;
+ return new TsExtractor(hlsMode, flags);
+ case PARSER_NAME_FLV:
+ return new FlvExtractor();
+ case PARSER_NAME_OGG:
+ return new OggExtractor();
+ case PARSER_NAME_PS:
+ return new PsExtractor();
+ case PARSER_NAME_WAV:
+ return new WavExtractor();
+ case PARSER_NAME_AMR:
+ flags |=
+ getBooleanParameter(PARAMETER_AMR_ENABLE_CBR_SEEKING)
+ ? AmrExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
+ : 0;
+ return new AmrExtractor(flags);
+ case PARSER_NAME_AC4:
+ return new Ac4Extractor();
+ case PARSER_NAME_FLAC:
+ flags |=
+ getBooleanParameter(PARAMETER_FLAC_DISABLE_ID3)
+ ? FlacExtractor.FLAG_DISABLE_ID3_METADATA
+ : 0;
+ return new FlacExtractor(flags);
+ default:
+ // Should never happen.
+ throw new IllegalStateException("Unexpected attempt to create: " + parserName);
+ }
+ }
+
+ private boolean getBooleanParameter(String name) {
+ return (boolean) mParserParameters.getOrDefault(name, false);
+ }
+
+ private String getStringParameter(String name, String defaultValue) {
+ return (String) mParserParameters.getOrDefault(name, defaultValue);
+ }
+
// Private classes.
private static final class InputReadingDataSource implements DataSource {
@@ -1277,7 +1407,7 @@
return null;
}
- private static MediaCodec.CryptoInfo toCryptoInfo(TrackOutput.CryptoData encryptionData) {
+ private static CryptoInfo toCryptoInfo(TrackOutput.CryptoData encryptionData) {
// TODO: Implement.
return null;
}
diff --git a/apex/permission/service/Android.bp b/apex/permission/service/Android.bp
index 679c98d..5cdcdd3 100644
--- a/apex/permission/service/Android.bp
+++ b/apex/permission/service/Android.bp
@@ -17,6 +17,7 @@
srcs: [
"java/**/*.java",
],
+ path: "java",
}
java_library {
diff --git a/apex/sdkextensions/framework/api/current.txt b/apex/sdkextensions/framework/api/current.txt
index 9041262..d802177 100644
--- a/apex/sdkextensions/framework/api/current.txt
+++ b/apex/sdkextensions/framework/api/current.txt
@@ -1,10 +1 @@
// Signature format: 2.0
-package android.os.ext.test {
-
- @Deprecated public class Test {
- ctor @Deprecated public Test();
- method @Deprecated public void testE();
- }
-
-}
-
diff --git a/apex/sdkextensions/framework/api/module-lib-current.txt b/apex/sdkextensions/framework/api/module-lib-current.txt
index 494c12f..d802177 100644
--- a/apex/sdkextensions/framework/api/module-lib-current.txt
+++ b/apex/sdkextensions/framework/api/module-lib-current.txt
@@ -1,9 +1 @@
// Signature format: 2.0
-package android.os.ext.test {
-
- @Deprecated public class Test {
- method @Deprecated public void testD();
- }
-
-}
-
diff --git a/apex/sdkextensions/framework/api/system-current.txt b/apex/sdkextensions/framework/api/system-current.txt
index 056eb41..bbff4c5 100644
--- a/apex/sdkextensions/framework/api/system-current.txt
+++ b/apex/sdkextensions/framework/api/system-current.txt
@@ -7,12 +7,3 @@
}
-package android.os.ext.test {
-
- @Deprecated public class Test {
- method @Deprecated public void testF();
- method @Deprecated public void testG();
- }
-
-}
-
diff --git a/apex/sdkextensions/framework/java/android/os/ext/test/Test.java b/apex/sdkextensions/framework/java/android/os/ext/test/Test.java
deleted file mode 100644
index 1715f49..0000000
--- a/apex/sdkextensions/framework/java/android/os/ext/test/Test.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os.ext.test;
-
-import android.annotation.SystemApi;
-
-/**
- * This class exists temporarily to verify SDK updates are working properly.
- * @deprecated Do not use.
- */
-@Deprecated
-public class Test {
-
- public Test() { }
-
- /** @hide */
- public void testA() {}
-
- /** @hide */
- public void testB() {}
-
- /** @hide */
- public void testC() {}
-
- /** @hide */
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public void testD() {}
-
- public void testE() {}
-
- /** @hide */
- @SystemApi
- public void testF() {}
-
- /** @hide */
- @SystemApi
- public void testG() {}
-
-}
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
index 804eb03..7480ec8 100644
--- a/apex/statsd/framework/Android.bp
+++ b/apex/statsd/framework/Android.bp
@@ -89,7 +89,7 @@
droidstubs {
name: "framework-statsd-stubs-srcs-publicapi",
defaults: [
- "framework-module-stubs-defaults-systemapi",
+ "framework-module-stubs-defaults-publicapi",
"framework-statsd-stubs-srcs-defaults",
],
}
diff --git a/apex/statsd/framework/api/current.txt b/apex/statsd/framework/api/current.txt
index d802177..a655693 100644
--- a/apex/statsd/framework/api/current.txt
+++ b/apex/statsd/framework/api/current.txt
@@ -1 +1,12 @@
// Signature format: 2.0
+package android.util {
+
+ public final class StatsLog {
+ method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public static boolean logBinaryPushStateChanged(@NonNull String, long, int, int, @NonNull long[]);
+ method public static boolean logEvent(int);
+ method public static boolean logStart(int);
+ method public static boolean logStop(int);
+ }
+
+}
+
diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
index 3f199e8..240222e 100644
--- a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
+++ b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
@@ -29,6 +29,7 @@
import com.android.internal.os.StatsdConfigProto.AtomMatcher;
import com.android.internal.os.StatsdConfigProto.FieldFilter;
import com.android.internal.os.StatsdConfigProto.GaugeMetric;
+import com.android.internal.os.StatsdConfigProto.PullAtomPackages;
import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
import com.android.internal.os.StatsdConfigProto.StatsdConfig;
import com.android.internal.os.StatsdConfigProto.TimeUnit;
@@ -271,6 +272,9 @@
.setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES)
.setMaxNumGaugeAtomsPerBucket(1000)
)
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(PULL_ATOM_TAG)
+ .addPackages(LibStatsPullTests.class.getPackage().getName()))
.build();
statsManager.addConfig(sConfigId, config.toByteArray());
assertThat(StatsConfigUtils.verifyValidConfigExists(statsManager, sConfigId)).isTrue();
diff --git a/api/current.txt b/api/current.txt
index 80bdead..40347c7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -277,7 +277,6 @@
field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
- field public static final int actor = 16844313; // 0x1010619
field public static final int addPrintersActivity = 16843750; // 0x10103e6
field public static final int addStatesFromChildren = 16842992; // 0x10100f0
field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -13386,6 +13385,7 @@
method public void disableWriteAheadLogging();
method public boolean enableWriteAheadLogging();
method public void endTransaction();
+ method public void execPerConnectionSQL(@NonNull String, @Nullable Object[]) throws android.database.SQLException;
method public void execSQL(String) throws android.database.SQLException;
method public void execSQL(String, Object[]) throws android.database.SQLException;
method public static String findEditTable(String);
@@ -24353,7 +24353,7 @@
}
public final class AudioMetadata {
- method @NonNull public static android.media.AudioMetadata.Map createMap();
+ method @NonNull public static android.media.AudioMetadataMap createMap();
}
public static class AudioMetadata.Format {
@@ -24371,16 +24371,16 @@
method @NonNull public Class<T> getValueClass();
}
- public static interface AudioMetadata.Map extends android.media.AudioMetadata.ReadMap {
+ public interface AudioMetadataMap extends android.media.AudioMetadataReadMap {
method @Nullable public <T> T remove(@NonNull android.media.AudioMetadata.Key<T>);
method @Nullable public <T> T set(@NonNull android.media.AudioMetadata.Key<T>, @NonNull T);
}
- public static interface AudioMetadata.ReadMap {
+ public interface AudioMetadataReadMap {
method public <T> boolean containsKey(@NonNull android.media.AudioMetadata.Key<T>);
- method @NonNull public android.media.AudioMetadata.Map dup();
+ method @NonNull public android.media.AudioMetadataMap dup();
method @Nullable public <T> T get(@NonNull android.media.AudioMetadata.Key<T>);
- method public int size();
+ method @IntRange(from=0) public int size();
}
public final class AudioPlaybackCaptureConfiguration {
@@ -24695,7 +24695,7 @@
}
public static interface AudioTrack.OnCodecFormatChangedListener {
- method public void onCodecFormatChanged(@NonNull android.media.AudioTrack, @Nullable android.media.AudioMetadata.ReadMap);
+ method public void onCodecFormatChanged(@NonNull android.media.AudioTrack, @Nullable android.media.AudioMetadataReadMap);
}
public static interface AudioTrack.OnPlaybackPositionUpdateListener {
@@ -30340,11 +30340,11 @@
}
public class NetworkRequest implements android.os.Parcelable {
+ method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkCapabilities);
method public int describeContents();
method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
method public boolean hasCapability(int);
method public boolean hasTransport(int);
- method public boolean satisfiedBy(@Nullable android.net.NetworkCapabilities);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkRequest> CREATOR;
}
@@ -37189,15 +37189,6 @@
}
-package android.os.ext.test {
-
- @Deprecated public class Test {
- ctor @Deprecated public Test();
- method @Deprecated public void testE();
- }
-
-}
-
package android.os.health {
public class HealthStats {
@@ -43140,9 +43131,9 @@
}
public final class InlinePresentation implements android.os.Parcelable {
- ctor public InlinePresentation(@NonNull android.app.slice.Slice, @NonNull android.view.inline.InlinePresentationSpec, boolean);
+ ctor public InlinePresentation(@NonNull android.app.slice.Slice, @NonNull android.widget.inline.InlinePresentationSpec, boolean);
method public int describeContents();
- method @NonNull public android.view.inline.InlinePresentationSpec getInlinePresentationSpec();
+ method @NonNull public android.widget.inline.InlinePresentationSpec getInlinePresentationSpec();
method @NonNull public android.app.slice.Slice getSlice();
method public boolean isPinned();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -55757,7 +55748,7 @@
field public int softInputMode;
field @Deprecated public int systemUiVisibility;
field public android.os.IBinder token;
- field @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION, to="BASE_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION, to="APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING, to="APPLICATION_STARTING"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION, to="DRAWN_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, to="APPLICATION_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA, to="APPLICATION_MEDIA"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, to="APPLICATION_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x3ed, to="APPLICATION_ABOVE_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG, to="APPLICATION_ATTACHED_DIALOG"), @android.view.ViewDebug.IntToString(from=0x3ec, to="APPLICATION_MEDIA_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR, to="STATUS_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR, to="SEARCH_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PHONE, to="PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, to="SYSTEM_ALERT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_TOAST, to="TOAST"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, to="SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE, to="PRIORITY_PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG, to="SYSTEM_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, to="KEYGUARD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, to="SYSTEM_ERROR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD, to="INPUT_METHOD"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG, to="INPUT_METHOD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_WALLPAPER, to="WALLPAPER"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, to="STATUS_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7df, to="SECURE_SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e0, to="DRAG"), @android.view.ViewDebug.IntToString(from=0x7e1, to="STATUS_BAR_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x7e2, to="POINTER"), @android.view.ViewDebug.IntToString(from=0x7e3, to="NAVIGATION_BAR"), @android.view.ViewDebug.IntToString(from=0x7e4, to="VOLUME_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e5, to="BOOT_PROGRESS"), @android.view.ViewDebug.IntToString(from=0x7e6, to="INPUT_CONSUMER"), @android.view.ViewDebug.IntToString(from=0x7e7, to="DREAM"), @android.view.ViewDebug.IntToString(from=0x7e8, to="NAVIGATION_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7ea, to="DISPLAY_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7eb, to="MAGNIFICATION_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7f5, to="PRESENTATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION, to="PRIVATE_PRESENTATION"), @android.view.ViewDebug.IntToString(from=0x7ef, to="VOICE_INTERACTION"), @android.view.ViewDebug.IntToString(from=0x7f1, to="VOICE_INTERACTION_STARTING"), @android.view.ViewDebug.IntToString(from=0x7f2, to="DOCK_DIVIDER"), @android.view.ViewDebug.IntToString(from=0x7f3, to="QS_DIALOG"), @android.view.ViewDebug.IntToString(from=0x7f4, to="SCREENSHOT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, to="APPLICATION_OVERLAY")}) public int type;
+ field @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION, to="BASE_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION, to="APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING, to="APPLICATION_STARTING"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION, to="DRAWN_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, to="APPLICATION_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA, to="APPLICATION_MEDIA"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, to="APPLICATION_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x3ed, to="APPLICATION_ABOVE_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG, to="APPLICATION_ATTACHED_DIALOG"), @android.view.ViewDebug.IntToString(from=0x3ec, to="APPLICATION_MEDIA_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR, to="STATUS_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR, to="SEARCH_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PHONE, to="PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, to="SYSTEM_ALERT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_TOAST, to="TOAST"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, to="SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE, to="PRIORITY_PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG, to="SYSTEM_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, to="KEYGUARD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, to="SYSTEM_ERROR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD, to="INPUT_METHOD"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG, to="INPUT_METHOD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_WALLPAPER, to="WALLPAPER"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, to="STATUS_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7df, to="SECURE_SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e0, to="DRAG"), @android.view.ViewDebug.IntToString(from=0x7e1, to="STATUS_BAR_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x7e2, to="POINTER"), @android.view.ViewDebug.IntToString(from=0x7e3, to="NAVIGATION_BAR"), @android.view.ViewDebug.IntToString(from=0x7e4, to="VOLUME_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e5, to="BOOT_PROGRESS"), @android.view.ViewDebug.IntToString(from=0x7e6, to="INPUT_CONSUMER"), @android.view.ViewDebug.IntToString(from=0x7e8, to="NAVIGATION_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7ea, to="DISPLAY_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7eb, to="MAGNIFICATION_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7f5, to="PRESENTATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION, to="PRIVATE_PRESENTATION"), @android.view.ViewDebug.IntToString(from=0x7ef, to="VOICE_INTERACTION"), @android.view.ViewDebug.IntToString(from=0x7f1, to="VOICE_INTERACTION_STARTING"), @android.view.ViewDebug.IntToString(from=0x7f2, to="DOCK_DIVIDER"), @android.view.ViewDebug.IntToString(from=0x7f3, to="QS_DIALOG"), @android.view.ViewDebug.IntToString(from=0x7f4, to="SCREENSHOT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, to="APPLICATION_OVERLAY")}) public int type;
field public float verticalMargin;
field @android.view.ViewDebug.ExportedProperty public float verticalWeight;
field public int windowAnimations;
@@ -56784,38 +56775,6 @@
}
-package android.view.inline {
-
- public class InlineContentView extends android.view.ViewGroup {
- method @Nullable public android.view.SurfaceControl getSurfaceControl();
- method public boolean isZOrderedOnTop();
- method public void onLayout(boolean, int, int, int, int);
- method public void setSurfaceControlCallback(@Nullable android.view.inline.InlineContentView.SurfaceControlCallback);
- method public boolean setZOrderedOnTop(boolean);
- }
-
- public static interface InlineContentView.SurfaceControlCallback {
- method public void onCreated(@NonNull android.view.SurfaceControl);
- method public void onDestroyed(@NonNull android.view.SurfaceControl);
- }
-
- public final class InlinePresentationSpec implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.util.Size getMaxSize();
- method @NonNull public android.util.Size getMinSize();
- method @Nullable public android.os.Bundle getStyle();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.view.inline.InlinePresentationSpec> CREATOR;
- }
-
- public static final class InlinePresentationSpec.Builder {
- ctor public InlinePresentationSpec.Builder(@NonNull android.util.Size, @NonNull android.util.Size);
- method @NonNull public android.view.inline.InlinePresentationSpec build();
- method @NonNull public android.view.inline.InlinePresentationSpec.Builder setStyle(@NonNull android.os.Bundle);
- }
-
-}
-
package android.view.inputmethod {
public class BaseInputConnection implements android.view.inputmethod.InputConnection {
@@ -56987,7 +56946,7 @@
public final class InlineSuggestion implements android.os.Parcelable {
method public int describeContents();
method @NonNull public android.view.inputmethod.InlineSuggestionInfo getInfo();
- method public void inflate(@NonNull android.content.Context, @NonNull android.util.Size, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.inline.InlineContentView>);
+ method public void inflate(@NonNull android.content.Context, @NonNull android.util.Size, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.widget.inline.InlineContentView>);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestion> CREATOR;
}
@@ -56995,7 +56954,7 @@
public final class InlineSuggestionInfo implements android.os.Parcelable {
method public int describeContents();
method @Nullable public String[] getAutofillHints();
- method @NonNull public android.view.inline.InlinePresentationSpec getPresentationSpec();
+ method @NonNull public android.widget.inline.InlinePresentationSpec getInlinePresentationSpec();
method @NonNull public String getSource();
method @NonNull public String getType();
method public boolean isPinned();
@@ -57011,8 +56970,8 @@
method public int describeContents();
method @Nullable public android.os.Bundle getExtras();
method @NonNull public String getHostPackageName();
+ method @NonNull public java.util.List<android.widget.inline.InlinePresentationSpec> getInlinePresentationSpecs();
method public int getMaxSuggestionCount();
- method @NonNull public java.util.List<android.view.inline.InlinePresentationSpec> getPresentationSpecs();
method @NonNull public android.os.LocaleList getSupportedLocales();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestionsRequest> CREATOR;
@@ -57020,10 +56979,11 @@
}
public static final class InlineSuggestionsRequest.Builder {
- ctor public InlineSuggestionsRequest.Builder(@NonNull java.util.List<android.view.inline.InlinePresentationSpec>);
- method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder addPresentationSpecs(@NonNull android.view.inline.InlinePresentationSpec);
+ ctor public InlineSuggestionsRequest.Builder(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>);
+ method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder addInlinePresentationSpecs(@NonNull android.widget.inline.InlinePresentationSpec);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest build();
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setExtras(@NonNull android.os.Bundle);
+ method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setMaxSuggestionCount(int);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setSupportedLocales(@NonNull android.os.LocaleList);
}
@@ -61617,6 +61577,38 @@
}
+package android.widget.inline {
+
+ public class InlineContentView extends android.view.ViewGroup {
+ method @Nullable public android.view.SurfaceControl getSurfaceControl();
+ method public boolean isZOrderedOnTop();
+ method public void onLayout(boolean, int, int, int, int);
+ method public void setSurfaceControlCallback(@Nullable android.widget.inline.InlineContentView.SurfaceControlCallback);
+ method public boolean setZOrderedOnTop(boolean);
+ }
+
+ public static interface InlineContentView.SurfaceControlCallback {
+ method public void onCreated(@NonNull android.view.SurfaceControl);
+ method public void onDestroyed(@NonNull android.view.SurfaceControl);
+ }
+
+ public final class InlinePresentationSpec implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.util.Size getMaxSize();
+ method @NonNull public android.util.Size getMinSize();
+ method @Nullable public android.os.Bundle getStyle();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.widget.inline.InlinePresentationSpec> CREATOR;
+ }
+
+ public static final class InlinePresentationSpec.Builder {
+ ctor public InlinePresentationSpec.Builder(@NonNull android.util.Size, @NonNull android.util.Size);
+ method @NonNull public android.widget.inline.InlinePresentationSpec build();
+ method @NonNull public android.widget.inline.InlinePresentationSpec.Builder setStyle(@NonNull android.os.Bundle);
+ }
+
+}
+
package dalvik.annotation {
@Deprecated @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.ANNOTATION_TYPE}) public @interface TestTarget {
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index a1d9967..e91fe25 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -161,14 +161,6 @@
}
-package android.os.ext.test {
-
- @Deprecated public class Test {
- method @Deprecated public void testD();
- }
-
-}
-
package android.util {
public final class Log {
diff --git a/api/system-current.txt b/api/system-current.txt
index 6d5ba34..c7536f8 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3575,23 +3575,23 @@
public static final class SoundTrigger.Keyphrase implements android.os.Parcelable {
ctor public SoundTrigger.Keyphrase(int, int, @NonNull java.util.Locale, @NonNull String, @Nullable int[]);
+ method public int getId();
+ method @NonNull public java.util.Locale getLocale();
+ method public int getRecognitionModes();
+ method @NonNull public String getText();
+ method @NonNull public int[] getUsers();
method @NonNull public static android.hardware.soundtrigger.SoundTrigger.Keyphrase readFromParcel(@NonNull android.os.Parcel);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.Keyphrase> CREATOR;
- field public final int id;
- field @NonNull public final java.util.Locale locale;
- field public final int recognitionModes;
- field @NonNull public final String text;
- field @NonNull public final int[] users;
}
public static final class SoundTrigger.KeyphraseSoundModel extends android.hardware.soundtrigger.SoundTrigger.SoundModel implements android.os.Parcelable {
ctor public SoundTrigger.KeyphraseSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], @Nullable android.hardware.soundtrigger.SoundTrigger.Keyphrase[], int);
ctor public SoundTrigger.KeyphraseSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], @Nullable android.hardware.soundtrigger.SoundTrigger.Keyphrase[]);
+ method @NonNull public android.hardware.soundtrigger.SoundTrigger.Keyphrase[] getKeyphrases();
method @NonNull public static android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel readFromParcel(@NonNull android.os.Parcel);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel> CREATOR;
- field @NonNull public final android.hardware.soundtrigger.SoundTrigger.Keyphrase[] keyphrases;
}
public static final class SoundTrigger.ModelParamRange implements android.os.Parcelable {
@@ -3603,26 +3603,26 @@
public static final class SoundTrigger.ModuleProperties implements android.os.Parcelable {
method public int describeContents();
+ method public int getAudioCapabilities();
+ method @NonNull public String getDescription();
+ method public int getId();
+ method @NonNull public String getImplementor();
+ method public int getMaxBufferMillis();
+ method public int getMaxKeyphrases();
+ method public int getMaxSoundModels();
+ method public int getMaxUsers();
+ method public int getPowerConsumptionMw();
+ method public int getRecognitionModes();
+ method @NonNull public String getSupportedModelArch();
+ method @NonNull public java.util.UUID getUuid();
+ method public int getVersion();
+ method public boolean isCaptureTransitionSupported();
+ method public boolean isConcurrentCaptureSupported();
+ method public boolean isTriggerReturnedInEvent();
method public void writeToParcel(android.os.Parcel, int);
field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModuleProperties> CREATOR;
- field public final int audioCapabilities;
- field @NonNull public final String description;
- field public final int id;
- field @NonNull public final String implementor;
- field public final int maxBufferMs;
- field public final int maxKeyphrases;
- field public final int maxSoundModels;
- field public final int maxUsers;
- field public final int powerConsumptionMw;
- field public final int recognitionModes;
- field public final boolean returnsTriggerInEvent;
- field @NonNull public final String supportedModelArch;
- field public final boolean supportsCaptureTransition;
- field public final boolean supportsConcurrentCapture;
- field @NonNull public final java.util.UUID uuid;
- field public final int version;
}
public static class SoundTrigger.RecognitionEvent {
@@ -3633,13 +3633,13 @@
}
public static class SoundTrigger.SoundModel {
+ method @NonNull public byte[] getData();
+ method public int getType();
+ method @NonNull public java.util.UUID getUuid();
+ method @NonNull public java.util.UUID getVendorUuid();
+ method public int getVersion();
field public static final int TYPE_GENERIC_SOUND = 1; // 0x1
field public static final int TYPE_KEYPHRASE = 0; // 0x0
- field @NonNull public final byte[] data;
- field public final int type;
- field @NonNull public final java.util.UUID uuid;
- field @NonNull public final java.util.UUID vendorUuid;
- field public final int version;
}
}
@@ -4178,11 +4178,11 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDeviceForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener) throws java.lang.SecurityException;
method public void clearAudioServerStateCallback();
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
- method @IntRange(from=0) public int getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
+ method @IntRange(from=0) public long getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups();
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getDevicesForAttributes(@NonNull android.media.AudioAttributes);
- method @IntRange(from=0) public int getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
+ method @IntRange(from=0) public long getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAttributes getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
@@ -4197,7 +4197,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.MODIFY_AUDIO_ROUTING}) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int requestAudioFocus(@NonNull android.media.AudioFocusRequest, @Nullable android.media.audiopolicy.AudioPolicy);
- method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) long);
method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes);
@@ -4272,17 +4272,11 @@
}
public static class AudioTrack.TunerConfiguration {
+ ctor @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public AudioTrack.TunerConfiguration(@IntRange(from=1) int, @IntRange(from=1) int);
method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getContentId();
method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getSyncId();
}
- public static class AudioTrack.TunerConfiguration.Builder {
- ctor public AudioTrack.TunerConfiguration.Builder();
- method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration build();
- method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration.Builder setContentId(@IntRange(from=1) int);
- method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration.Builder setSyncId(@IntRange(from=1) int);
- }
-
public class HwAudioSource {
method public boolean isPlaying();
method public void start();
@@ -6183,7 +6177,6 @@
public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
ctor public MatchAllNetworkSpecifier();
method public int describeContents();
- method public boolean satisfiedBy(android.net.NetworkSpecifier);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.MatchAllNetworkSpecifier> CREATOR;
}
@@ -6204,13 +6197,14 @@
public abstract class NetworkAgent {
ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider);
method @Nullable public android.net.Network getNetwork();
+ method public void markConnected();
method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData);
method public void onAutomaticReconnectDisabled();
method public void onNetworkUnwanted();
method public void onRemoveKeepalivePacketFilter(int);
method public void onSaveAcceptUnvalidated(boolean);
method public void onSignalStrengthThresholdsUpdated(@NonNull int[]);
- method public void onStartSocketKeepalive(int, @IntRange(from=10, to=3600) int, @NonNull android.net.KeepalivePacketData);
+ method public void onStartSocketKeepalive(int, @NonNull java.time.Duration, @NonNull android.net.KeepalivePacketData);
method public void onStopSocketKeepalive(int);
method public void onValidationStatus(int, @Nullable android.net.Uri);
method @NonNull public android.net.Network register();
@@ -6218,7 +6212,6 @@
method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
method public final void sendNetworkScore(@IntRange(from=0, to=99) int);
method public final void sendSocketKeepaliveEvent(int, int);
- method public void setConnected();
method public void unregister();
field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
field public static final int VALIDATION_STATUS_VALID = 1; // 0x1
@@ -6289,8 +6282,8 @@
ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String);
method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest);
method public int getProviderId();
- method public void onNetworkRequested(@NonNull android.net.NetworkRequest, int, int);
- method public void onRequestWithdrawn(@NonNull android.net.NetworkRequest);
+ method public void onNetworkRequestWithdrawn(@NonNull android.net.NetworkRequest);
+ method public void onNetworkRequested(@NonNull android.net.NetworkRequest, @IntRange(from=0, to=99) int, int);
field public static final int ID_NONE = -1; // 0xffffffff
}
@@ -6337,8 +6330,8 @@
}
public abstract class NetworkSpecifier {
+ method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkSpecifier);
method @Nullable public android.net.NetworkSpecifier redact();
- method public abstract boolean satisfiedBy(@Nullable android.net.NetworkSpecifier);
}
public class NetworkStack {
@@ -6441,10 +6434,6 @@
method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
}
- public final class TelephonyNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
- method public boolean satisfiedBy(android.net.NetworkSpecifier);
- }
-
public final class TetheredClient implements android.os.Parcelable {
ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
method public int describeContents();
@@ -7431,10 +7420,6 @@
field public int numUsage;
}
- public final class WifiNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
- method public boolean satisfiedBy(android.net.NetworkSpecifier);
- }
-
public final class WifiNetworkSuggestion implements android.os.Parcelable {
method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration();
}
@@ -7625,10 +7610,6 @@
method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
}
- public final class WifiAwareNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
- method public boolean satisfiedBy(android.net.NetworkSpecifier);
- }
-
public class WifiAwareSession implements java.lang.AutoCloseable {
method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, @NonNull byte[], @NonNull byte[]);
}
@@ -8709,15 +8690,6 @@
}
-package android.os.ext.test {
-
- @Deprecated public class Test {
- method @Deprecated public void testF();
- method @Deprecated public void testG();
- }
-
-}
-
package android.os.image {
public class DynamicSystemClient {
@@ -11339,9 +11311,9 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPin(String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
@@ -12711,9 +12683,6 @@
public final class ContentCaptureManager {
method public boolean isContentCaptureFeatureEnabled();
- }
-
- public abstract class ContentCaptureSession implements java.lang.AutoCloseable {
field public static final int NO_SESSION_ID = 0; // 0x0
}
diff --git a/api/test-current.txt b/api/test-current.txt
index ba6feed..f95f8e8 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5052,7 +5052,7 @@
}
public final class InlineSuggestionInfo implements android.os.Parcelable {
- method @NonNull public static android.view.inputmethod.InlineSuggestionInfo newInlineSuggestionInfo(@NonNull android.view.inline.InlinePresentationSpec, @NonNull String, @Nullable String[], @NonNull String, boolean);
+ method @NonNull public static android.view.inputmethod.InlineSuggestionInfo newInlineSuggestionInfo(@NonNull android.widget.inline.InlinePresentationSpec, @NonNull String, @Nullable String[], @NonNull String, boolean);
}
public final class InlineSuggestionsResponse implements android.os.Parcelable {
diff --git a/cmds/idmap2/idmap2/CreateMultiple.cpp b/cmds/idmap2/idmap2/CreateMultiple.cpp
index ba4ca62..4b70acc 100644
--- a/cmds/idmap2/idmap2/CreateMultiple.cpp
+++ b/cmds/idmap2/idmap2/CreateMultiple.cpp
@@ -22,6 +22,7 @@
#include <ostream>
#include <vector>
+#include "Commands.h"
#include "android-base/stringprintf.h"
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/CommandLineOptions.h"
@@ -30,7 +31,6 @@
#include "idmap2/Policies.h"
#include "idmap2/PolicyUtils.h"
#include "idmap2/SysTrace.h"
-#include "Commands.h"
using android::ApkAssets;
using android::base::StringPrintf;
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 8f5e49d..e55ea6c 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -93,7 +93,8 @@
return ok();
}
-Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path,
+Status Idmap2Service::verifyIdmap(const std::string& target_apk_path,
+ const std::string& overlay_apk_path,
int32_t fulfilled_policies ATTRIBUTE_UNUSED,
bool enforce_overlayable ATTRIBUTE_UNUSED,
int32_t user_id ATTRIBUTE_UNUSED, bool* _aidl_return) {
@@ -103,10 +104,15 @@
std::ifstream fin(idmap_path);
const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin);
fin.close();
- *_aidl_return = header && header->IsUpToDate();
+ if (!header) {
+ *_aidl_return = false;
+ return error("failed to parse idmap header");
+ }
+
+ *_aidl_return =
+ strcmp(header->GetTargetPath().data(), target_apk_path.data()) == 0 && header->IsUpToDate();
// TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed
-
return ok();
}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index b6f5136..0ed55a1 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -37,7 +37,8 @@
binder::Status removeIdmap(const std::string& overlay_apk_path, int32_t user_id,
bool* _aidl_return) override;
- binder::Status verifyIdmap(const std::string& overlay_apk_path, int32_t fulfilled_policies,
+ binder::Status verifyIdmap(const std::string& target_apk_path,
+ const std::string& overlay_apk_path, int32_t fulfilled_policies,
bool enforce_overlayable, int32_t user_id,
bool* _aidl_return) override;
diff --git a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
index f4cf651..156f1d7 100644
--- a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
+++ b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
@@ -22,8 +22,11 @@
interface IIdmap2 {
@utf8InCpp String getIdmapPath(@utf8InCpp String overlayApkPath, int userId);
boolean removeIdmap(@utf8InCpp String overlayApkPath, int userId);
- boolean verifyIdmap(@utf8InCpp String overlayApkPath, int fulfilledPolicies,
- boolean enforceOverlayable, int userId);
+ boolean verifyIdmap(@utf8InCpp String targetApkPath,
+ @utf8InCpp String overlayApkPath,
+ int fulfilledPolicies,
+ boolean enforceOverlayable,
+ int userId);
@nullable @utf8InCpp String createIdmap(@utf8InCpp String targetApkPath,
@utf8InCpp String overlayApkPath,
int fulfilledPolicies,
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 0bb1af1..4410f1c 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -24,6 +24,7 @@
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <sys/wait.h>
#include <binder/ProcessState.h>
@@ -99,11 +100,38 @@
}
static status_t notifyMediaScanner(const char* fileName) {
- String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://");
- cmd.append(fileName);
- cmd.append(" > /dev/null");
- int result = system(cmd.string());
- if (result < 0) {
+ std::string filePath("file://");
+ filePath.append(fileName);
+ char *cmd[] = {
+ (char*) "am",
+ (char*) "broadcast",
+ (char*) "am",
+ (char*) "android.intent.action.MEDIA_SCANNER_SCAN_FILE",
+ (char*) "-d",
+ &filePath[0],
+ nullptr
+ };
+
+ int status;
+ int pid = fork();
+ if (pid < 0){
+ fprintf(stderr, "Unable to fork in order to send intent for media scanner.\n");
+ return UNKNOWN_ERROR;
+ }
+ if (pid == 0){
+ int fd = open("/dev/null", O_WRONLY);
+ if (fd < 0){
+ fprintf(stderr, "Unable to open /dev/null for media scanner stdout redirection.\n");
+ exit(1);
+ }
+ dup2(fd, 1);
+ int result = execvp(cmd[0], cmd);
+ close(fd);
+ exit(result);
+ }
+ wait(&status);
+
+ if (status < 0) {
fprintf(stderr, "Unable to broadcast intent for media scanner.\n");
return UNKNOWN_ERROR;
}
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 45f21ae..776593d 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -333,6 +333,7 @@
"tests/external/puller_util_test.cpp",
"tests/external/StatsCallbackPuller_test.cpp",
"tests/external/StatsPuller_test.cpp",
+ "tests/external/StatsPullerManager_test.cpp",
"tests/FieldValue_test.cpp",
"tests/guardrail/StatsdStats_test.cpp",
"tests/indexed_priority_queue_test.cpp",
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 69b9fc7..4966b2e 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -536,6 +536,7 @@
new MetricsManager(key, config, mTimeBaseNs, timestampNs, mUidMap, mPullerManager,
mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
if (newMetricsManager->isConfigValid()) {
+ newMetricsManager->init();
mUidMap->OnConfigUpdated(key);
newMetricsManager->refreshTtl(timestampNs);
mMetricsManagers[key] = newMetricsManager;
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 812d10b..98879a0 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -385,9 +385,11 @@
dprintf(out, " PKG Optional package name to print the uids of the package\n");
dprintf(out, "\n");
dprintf(out, "\n");
- dprintf(out, "usage: adb shell cmd stats pull-source [int] \n");
+ dprintf(out, "usage: adb shell cmd stats pull-source ATOM_TAG [PACKAGE] \n");
dprintf(out, "\n");
- dprintf(out, " Prints the output of a pulled metrics source (int indicates source)\n");
+ dprintf(out, " Prints the output of a pulled atom\n");
+ dprintf(out, " UID The atom to pull\n");
+ dprintf(out, " PACKAGE The package to pull from. Default is AID_SYSTEM\n");
dprintf(out, "\n");
dprintf(out, "\n");
dprintf(out, "usage: adb shell cmd stats write-to-disk \n");
@@ -806,8 +808,21 @@
status_t StatsService::cmd_print_pulled_metrics(int out, const Vector<String8>& args) {
int s = atoi(args[1].c_str());
- vector<shared_ptr<LogEvent> > stats;
- if (mPullerManager->Pull(s, &stats)) {
+ vector<int32_t> uids;
+ if (args.size() > 2) {
+ string package = string(args[2].c_str());
+ auto it = UidMap::sAidToUidMapping.find(package);
+ if (it != UidMap::sAidToUidMapping.end()) {
+ uids.push_back(it->second);
+ } else {
+ set<int32_t> uids_set = mUidMap->getAppUid(package);
+ uids.insert(uids.end(), uids_set.begin(), uids_set.end());
+ }
+ } else {
+ uids.push_back(AID_SYSTEM);
+ }
+ vector<shared_ptr<LogEvent>> stats;
+ if (mPullerManager->Pull(s, uids, &stats)) {
for (const auto& it : stats) {
dprintf(out, "Pull from %d: %s\n", s, it->ToString().c_str());
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 979f950..9bba69c 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -1725,7 +1725,7 @@
* Logged from:
* packages/apps/Bluetooth/src/com/android/bluetooth/btservice/RemoteDevices.java
*
- * Next Tag: 5
+ * Next Tag: 6
*/
message BluetoothConnectionStateChanged {
// The state of the connection.
@@ -1747,6 +1747,15 @@
// Size: 32 byte
// Default: null or empty if the device identifier is not known
optional bytes new_obfuscated_id = 4 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -1755,7 +1764,7 @@
* Logged from:
* packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java
*
- * Next Tag: 3
+ * Next Tag: 4
*/
message BluetoothAclConnectionStateChanged {
// An identifier that can be used to match events for this device.
@@ -1768,6 +1777,15 @@
// The state of the connection.
// Eg: CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED.
optional android.bluetooth.ConnectionStateEnum state = 2;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 3;
}
/**
@@ -1777,7 +1795,7 @@
* packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
* packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetClientStateMachine.java
*
- * Next Tag: 4
+ * Next Tag: 5
*/
message BluetoothScoConnectionStateChanged {
// An identifier that can be used to match events for this device.
@@ -1793,6 +1811,15 @@
// Codec used for this SCO connection
// Default: UNKNOWN
optional android.bluetooth.hfp.ScoCodec codec = 3;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 4;
}
/**
@@ -1814,6 +1841,15 @@
// Size: 32 byte
// Default: null or empty if there is no active device for this profile
optional bytes obfuscated_id = 2 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 3;
}
// Logs when there is an event affecting Bluetooth device's link layer connection.
@@ -1897,6 +1933,15 @@
// HCI reason code associated with this event
// Default: STATUS_UNKNOWN
optional android.bluetooth.hci.StatusEnum reason_code = 9;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 10;
}
/**
@@ -1955,6 +2000,15 @@
// Current audio coding mode
// Default: AUDIO_CODING_MODE_UNKNOWN
optional android.bluetooth.a2dp.AudioCodingModeEnum audio_coding_mode = 3;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 4;
}
/**
@@ -1993,6 +2047,15 @@
optional int64 codec_specific_2 = 8;
optional int64 codec_specific_3 = 9;
optional int64 codec_specific_4 = 10;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 11;
}
/**
@@ -2035,6 +2098,15 @@
optional int64 codec_specific_2 = 8;
optional int64 codec_specific_3 = 9;
optional int64 codec_specific_4 = 10;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 11;
}
/**
@@ -2058,6 +2130,15 @@
// Number of bytes of PCM data that could not be read from the source
// Default: 0
optional int32 num_missing_pcm_bytes = 3;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 4;
}
/**
@@ -2088,6 +2169,15 @@
// Number of encoded bytes dropped in this event
// Default: 0
optional int32 num_dropped_encoded_bytes = 5;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 6;
}
/**
@@ -2119,6 +2209,15 @@
// Units: dBm
// Invalid when an out of range value is reported
optional int32 rssi = 4;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -2146,6 +2245,15 @@
// Range: uint16_t, 0-0xFFFF
// Default: 0xFFFFF
optional int32 failed_contact_counter = 4;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -2173,6 +2281,15 @@
// Units: dBm
// Invalid when an out of range value is reported
optional int32 transmit_power_level = 4;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -2302,6 +2419,15 @@
optional string hardware_version = 6;
// Software version of this device
optional string software_version = 7;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 8;
}
/**
@@ -2355,6 +2481,15 @@
optional int32 attribute_id = 3;
// Attribute value for the particular attribute
optional bytes attribute_value = 4 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -2387,6 +2522,15 @@
// Unbond Reason
// Default: UNBOND_REASON_UNKNOWN
optional android.bluetooth.UnbondReasonEnum unbond_reason = 6;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 7;
}
/**
@@ -2422,6 +2566,15 @@
// A status value related to this specific event
// Default: 0
optional int64 event_value = 7;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 8;
}
/**
@@ -2447,6 +2600,15 @@
// SMP failure reason code
// Default: PAIRING_FAIL_REASON_DEFAULT
optional android.bluetooth.smp.PairingFailReasonEnum smp_fail_reason = 4;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -2485,6 +2647,15 @@
optional int32 server_port = 8;
// Whether this is a server listener socket
optional android.bluetooth.SocketRoleEnum is_server = 9;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 10;
}
/**
@@ -2508,6 +2679,15 @@
// Also defined in: https://developer.android.com/reference/android/bluetooth/BluetoothClass
// Default: 0
optional int32 class_of_device = 2;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 3;
}
/**
diff --git a/cmds/statsd/src/external/PullUidProvider.h b/cmds/statsd/src/external/PullUidProvider.h
new file mode 100644
index 0000000..2318c50
--- /dev/null
+++ b/cmds/statsd/src/external/PullUidProvider.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <utils/RefBase.h>
+
+#include "StatsPuller.h"
+#include "logd/LogEvent.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class PullUidProvider : virtual public RefBase {
+public:
+ virtual ~PullUidProvider() {}
+
+ /**
+ * @param atomId The atom for which to get the uids.
+ */
+ virtual vector<int32_t> getPullAtomUids(int32_t atomId) = 0;
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 8b6a5a1..4ffa3d8 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -47,27 +47,73 @@
StatsPullerManager::StatsPullerManager()
: kAllPullAtomInfo({
// TrainInfo.
- {{.atomTag = util::TRAIN_INFO}, new TrainInfoPuller()},
+ {{.atomTag = util::TRAIN_INFO, .uid = -1}, new TrainInfoPuller()},
}),
mNextPullTimeNs(NO_ALARM_UPDATE) {
}
-bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
- AutoMutex _l(mLock);
- return PullLocked(tagId, data);
+bool StatsPullerManager::Pull(int tagId, const ConfigKey& configKey,
+ vector<shared_ptr<LogEvent>>* data, bool useUids) {
+ std::lock_guard<std::mutex> _l(mLock);
+ return PullLocked(tagId, configKey, data, useUids);
}
-bool StatsPullerManager::PullLocked(int tagId, vector<shared_ptr<LogEvent>>* data) {
- VLOG("Initiating pulling %d", tagId);
+bool StatsPullerManager::Pull(int tagId, const vector<int32_t>& uids,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids) {
+ std::lock_guard<std::mutex> _l(mLock);
+ return PullLocked(tagId, uids, data, useUids);
+}
- if (kAllPullAtomInfo.find({.atomTag = tagId}) != kAllPullAtomInfo.end()) {
- bool ret = kAllPullAtomInfo.find({.atomTag = tagId})->second->Pull(data);
- VLOG("pulled %d items", (int)data->size());
- if (!ret) {
- StatsdStats::getInstance().notePullFailed(tagId);
+bool StatsPullerManager::PullLocked(int tagId, const ConfigKey& configKey,
+ vector<shared_ptr<LogEvent>>* data, bool useUids) {
+ vector<int32_t> uids;
+ if (useUids) {
+ auto uidProviderIt = mPullUidProviders.find(configKey);
+ if (uidProviderIt == mPullUidProviders.end()) {
+ ALOGE("Error pulling tag %d. No pull uid provider for config key %s", tagId,
+ configKey.ToString().c_str());
+ return false;
}
- return ret;
+ sp<PullUidProvider> pullUidProvider = uidProviderIt->second.promote();
+ if (pullUidProvider == nullptr) {
+ ALOGE("Error pulling tag %d, pull uid provider for config %s is gone.", tagId,
+ configKey.ToString().c_str());
+ return false;
+ }
+ uids = pullUidProvider->getPullAtomUids(tagId);
+ }
+ return PullLocked(tagId, uids, data, useUids);
+}
+
+bool StatsPullerManager::PullLocked(int tagId, const vector<int32_t>& uids,
+ vector<shared_ptr<LogEvent>>* data, bool useUids) {
+ VLOG("Initiating pulling %d", tagId);
+ if (useUids) {
+ for (int32_t uid : uids) {
+ PullerKey key = {.atomTag = tagId, .uid = uid};
+ auto pullerIt = kAllPullAtomInfo.find(key);
+ if (pullerIt != kAllPullAtomInfo.end()) {
+ bool ret = pullerIt->second->Pull(data);
+ VLOG("pulled %zu items", data->size());
+ if (!ret) {
+ StatsdStats::getInstance().notePullFailed(tagId);
+ }
+ return ret;
+ }
+ }
+ ALOGW("StatsPullerManager: Unknown tagId %d", tagId);
+ return false; // Return early since we don't know what to pull.
} else {
+ PullerKey key = {.atomTag = tagId, .uid = -1};
+ auto pullerIt = kAllPullAtomInfo.find(key);
+ if (pullerIt != kAllPullAtomInfo.end()) {
+ bool ret = pullerIt->second->Pull(data);
+ VLOG("pulled %zu items", data->size());
+ if (!ret) {
+ StatsdStats::getInstance().notePullFailed(tagId);
+ }
+ return ret;
+ }
ALOGW("StatsPullerManager: Unknown tagId %d", tagId);
return false; // Return early since we don't know what to pull.
}
@@ -96,7 +142,7 @@
void StatsPullerManager::SetStatsCompanionService(
shared_ptr<IStatsCompanionService> statsCompanionService) {
- AutoMutex _l(mLock);
+ std::lock_guard<std::mutex> _l(mLock);
shared_ptr<IStatsCompanionService> tmpForLock = mStatsCompanionService;
mStatsCompanionService = statsCompanionService;
for (const auto& pulledAtom : kAllPullAtomInfo) {
@@ -107,10 +153,11 @@
}
}
-void StatsPullerManager::RegisterReceiver(int tagId, wp<PullDataReceiver> receiver,
- int64_t nextPullTimeNs, int64_t intervalNs) {
- AutoMutex _l(mLock);
- auto& receivers = mReceivers[tagId];
+void StatsPullerManager::RegisterReceiver(int tagId, const ConfigKey& configKey,
+ wp<PullDataReceiver> receiver, int64_t nextPullTimeNs,
+ int64_t intervalNs) {
+ std::lock_guard<std::mutex> _l(mLock);
+ auto& receivers = mReceivers[{.atomTag = tagId, .configKey = configKey}];
for (auto it = receivers.begin(); it != receivers.end(); it++) {
if (it->receiver == receiver) {
VLOG("Receiver already registered of %d", (int)receivers.size());
@@ -142,13 +189,15 @@
VLOG("Puller for tagId %d registered of %d", tagId, (int)receivers.size());
}
-void StatsPullerManager::UnRegisterReceiver(int tagId, wp<PullDataReceiver> receiver) {
- AutoMutex _l(mLock);
- if (mReceivers.find(tagId) == mReceivers.end()) {
+void StatsPullerManager::UnRegisterReceiver(int tagId, const ConfigKey& configKey,
+ wp<PullDataReceiver> receiver) {
+ std::lock_guard<std::mutex> _l(mLock);
+ auto receiversIt = mReceivers.find({.atomTag = tagId, .configKey = configKey});
+ if (receiversIt == mReceivers.end()) {
VLOG("Unknown pull code or no receivers: %d", tagId);
return;
}
- auto& receivers = mReceivers.find(tagId)->second;
+ std::list<ReceiverInfo>& receivers = receiversIt->second;
for (auto it = receivers.begin(); it != receivers.end(); it++) {
if (receiver == it->receiver) {
receivers.erase(it);
@@ -158,16 +207,26 @@
}
}
+void StatsPullerManager::RegisterPullUidProvider(const ConfigKey& configKey,
+ wp<PullUidProvider> provider) {
+ std::lock_guard<std::mutex> _l(mLock);
+ mPullUidProviders[configKey] = provider;
+}
+
+void StatsPullerManager::UnregisterPullUidProvider(const ConfigKey& configKey) {
+ std::lock_guard<std::mutex> _l(mLock);
+ mPullUidProviders.erase(configKey);
+}
+
void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) {
- AutoMutex _l(mLock);
+ std::lock_guard<std::mutex> _l(mLock);
int64_t wallClockNs = getWallClockNs();
int64_t minNextPullTimeNs = NO_ALARM_UPDATE;
- vector<pair<int, vector<ReceiverInfo*>>> needToPull =
- vector<pair<int, vector<ReceiverInfo*>>>();
+ vector<pair<const ReceiverKey*, vector<ReceiverInfo*>>> needToPull;
for (auto& pair : mReceivers) {
- vector<ReceiverInfo*> receivers = vector<ReceiverInfo*>();
+ vector<ReceiverInfo*> receivers;
if (pair.second.size() != 0) {
for (ReceiverInfo& receiverInfo : pair.second) {
if (receiverInfo.nextPullTimeNs <= elapsedTimeNs) {
@@ -179,17 +238,16 @@
}
}
if (receivers.size() > 0) {
- needToPull.push_back(make_pair(pair.first, receivers));
+ needToPull.push_back(make_pair(&pair.first, receivers));
}
}
}
-
for (const auto& pullInfo : needToPull) {
vector<shared_ptr<LogEvent>> data;
- bool pullSuccess = PullLocked(pullInfo.first, &data);
+ bool pullSuccess = PullLocked(pullInfo.first->atomTag, pullInfo.first->configKey, &data);
if (pullSuccess) {
- StatsdStats::getInstance().notePullDelay(
- pullInfo.first, getElapsedRealtimeNs() - elapsedTimeNs);
+ StatsdStats::getInstance().notePullDelay(pullInfo.first->atomTag,
+ getElapsedRealtimeNs() - elapsedTimeNs);
} else {
VLOG("pull failed at %lld, will try again later", (long long)elapsedTimeNs);
}
@@ -248,18 +306,19 @@
void StatsPullerManager::RegisterPullAtomCallback(const int uid, const int32_t atomTag,
const int64_t coolDownNs, const int64_t timeoutNs,
const vector<int32_t>& additiveFields,
- const shared_ptr<IPullAtomCallback>& callback) {
- AutoMutex _l(mLock);
+ const shared_ptr<IPullAtomCallback>& callback,
+ bool useUid) {
+ std::lock_guard<std::mutex> _l(mLock);
VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag);
// TODO(b/146439412): linkToDeath with the callback so that we can remove it
// and delete the puller.
StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
- kAllPullAtomInfo[{.atomTag = atomTag}] =
+ kAllPullAtomInfo[{.atomTag = atomTag, .uid = useUid ? uid : -1}] =
new StatsCallbackPuller(atomTag, callback, coolDownNs, timeoutNs, additiveFields);
}
void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag) {
- AutoMutex _l(mLock);
+ std::lock_guard<std::mutex> _l(mLock);
StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false);
kAllPullAtomInfo.erase({.atomTag = atomTag});
}
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index e067766..714b0ae 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -19,15 +19,16 @@
#include <aidl/android/os/IPullAtomCallback.h>
#include <aidl/android/os/IStatsCompanionService.h>
#include <utils/RefBase.h>
-#include <utils/threads.h>
#include <list>
#include <vector>
#include "PullDataReceiver.h"
+#include "PullUidProvider.h"
#include "StatsPuller.h"
#include "guardrail/StatsdStats.h"
#include "logd/LogEvent.h"
+#include "packages/UidMap.h"
using aidl::android::os::IPullAtomCallback;
using aidl::android::os::IStatsCompanionService;
@@ -67,11 +68,20 @@
// Registers a receiver for tagId. It will be pulled on the nextPullTimeNs
// and then every intervalNs thereafter.
- virtual void RegisterReceiver(int tagId, wp<PullDataReceiver> receiver, int64_t nextPullTimeNs,
+ virtual void RegisterReceiver(int tagId, const ConfigKey& configKey,
+ wp<PullDataReceiver> receiver, int64_t nextPullTimeNs,
int64_t intervalNs);
// Stop listening on a tagId.
- virtual void UnRegisterReceiver(int tagId, wp<PullDataReceiver> receiver);
+ virtual void UnRegisterReceiver(int tagId, const ConfigKey& configKey,
+ wp<PullDataReceiver> receiver);
+
+ // Registers a pull uid provider for the config key. When pulling atoms, it will be used to
+ // determine which atoms to pull from.
+ virtual void RegisterPullUidProvider(const ConfigKey& configKey, wp<PullUidProvider> provider);
+
+ // Unregister a pull uid provider.
+ virtual void UnregisterPullUidProvider(const ConfigKey& configKey);
// Verify if we know how to pull for this matcher
bool PullerForMatcherExists(int tagId) const;
@@ -85,9 +95,16 @@
// Returns false when
// 1) the pull fails
// 2) pull takes longer than mPullTimeoutNs (intrinsic to puller)
+ // 3) Either a PullUidProvider was not registered for the config, or the there was no puller
+ // registered for any of the uids for this atom.
// If the metric wants to make any change to the data, like timestamps, they
// should make a copy as this data may be shared with multiple metrics.
- virtual bool Pull(int tagId, vector<std::shared_ptr<LogEvent>>* data);
+ virtual bool Pull(int tagId, const ConfigKey& configKey,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids = false);
+
+ // Same as above, but directly specify the allowed uids to pull from.
+ virtual bool Pull(int tagId, const vector<int32_t>& uids,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids = false);
// Clear pull data cache immediately.
int ForceClearPullerCache();
@@ -99,7 +116,8 @@
void RegisterPullAtomCallback(const int uid, const int32_t atomTag, const int64_t coolDownNs,
const int64_t timeoutNs, const vector<int32_t>& additiveFields,
- const shared_ptr<IPullAtomCallback>& callback);
+ const shared_ptr<IPullAtomCallback>& callback,
+ bool useUid = false);
void UnregisterPullAtomCallback(const int uid, const int32_t atomTag);
@@ -108,19 +126,36 @@
private:
shared_ptr<IStatsCompanionService> mStatsCompanionService = nullptr;
+ // A struct containing an atom id and a Config Key
+ typedef struct ReceiverKey {
+ const int atomTag;
+ const ConfigKey configKey;
+
+ inline bool operator<(const ReceiverKey& that) const {
+ return atomTag == that.atomTag ? configKey < that.configKey : atomTag < that.atomTag;
+ }
+ } ReceiverKey;
+
typedef struct {
int64_t nextPullTimeNs;
int64_t intervalNs;
wp<PullDataReceiver> receiver;
} ReceiverInfo;
- // mapping from simple matcher tagId to receivers
- std::map<int, std::list<ReceiverInfo>> mReceivers;
+ // mapping from Receiver Key to receivers
+ std::map<ReceiverKey, std::list<ReceiverInfo>> mReceivers;
- bool PullLocked(int tagId, vector<std::shared_ptr<LogEvent>>* data);
+ // mapping from Config Key to the PullUidProvider for that config
+ std::map<ConfigKey, wp<PullUidProvider>> mPullUidProviders;
+
+ bool PullLocked(int tagId, const ConfigKey& configKey, vector<std::shared_ptr<LogEvent>>* data,
+ bool useUids = false);
+
+ bool PullLocked(int tagId, const vector<int32_t>& uids, vector<std::shared_ptr<LogEvent>>* data,
+ bool useUids);
// locks for data receiver and StatsCompanionService changes
- Mutex mLock;
+ std::mutex mLock;
void updateAlarmLocked();
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index df810aa..25794c8 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -119,6 +119,8 @@
const static int kMaxLogSourceCount = 50;
+ const static int kMaxPullAtomPackages = 100;
+
// Max memory allowed for storing metrics per configuration. If this limit is exceeded, statsd
// drops the metrics data in memory.
static const size_t kMaxMetricsBytesPerConfig = 2 * 1024 * 1024;
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index b515d0a..3b3d0b6 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -504,12 +504,12 @@
typeInfo = readNextValue<uint8_t>();
if (getTypeId(typeInfo) != INT64_TYPE) mValid = false;
mElapsedTimestampNs = readNextValue<int64_t>();
- parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
numElements--;
typeInfo = readNextValue<uint8_t>();
if (getTypeId(typeInfo) != INT32_TYPE) mValid = false;
mTagId = readNextValue<int32_t>();
+ parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
numElements--;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 5c606bc..42bbd8e 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -75,11 +75,9 @@
const int atomId, const int64_t timeBaseNs, const int64_t startTimeNs,
const sp<StatsPullerManager>& pullerManager,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
- const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
- const vector<int>& slicedStateAtoms,
- const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
+ const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
- eventDeactivationMap, slicedStateAtoms, stateGroupMap),
+ eventDeactivationMap, /*slicedStateAtoms=*/{}, /*stateGroupMap=*/{}),
mWhatMatcherIndex(whatMatcherIndex),
mEventMatcherWizard(matcherWizard),
mPullerManager(pullerManager),
@@ -135,15 +133,12 @@
flushIfNeededLocked(startTimeNs);
// Kicks off the puller immediately.
if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
- mPullerManager->RegisterReceiver(mPullTagId, this, getCurrentBucketEndTimeNs(),
+ mPullerManager->RegisterReceiver(mPullTagId, mConfigKey, this, getCurrentBucketEndTimeNs(),
mBucketSizeNs);
}
// Adjust start for partial first bucket and then pull if needed
mCurrentBucketStartTimeNs = startTimeNs;
- if (mIsActive && mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
- pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
- }
VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
(long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs,
@@ -153,7 +148,7 @@
GaugeMetricProducer::~GaugeMetricProducer() {
VLOG("~GaugeMetricProducer() called");
if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
- mPullerManager->UnRegisterReceiver(mPullTagId, this);
+ mPullerManager->UnRegisterReceiver(mPullTagId, mConfigKey, this);
}
}
@@ -298,6 +293,11 @@
}
}
+void GaugeMetricProducer::prepareFirstBucketLocked() {
+ if (mIsActive && mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
+ pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
+ }
+}
void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
bool triggerPuller = false;
@@ -323,7 +323,7 @@
return;
}
vector<std::shared_ptr<LogEvent>> allData;
- if (!mPullerManager->Pull(mPullTagId, &allData)) {
+ if (!mPullerManager->Pull(mPullTagId, mConfigKey, &allData)) {
ALOGE("Gauge Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
return;
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 284bcc5..79ec711 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -64,9 +64,7 @@
const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
- eventDeactivationMap = {},
- const vector<int>& slicedStateAtoms = {},
- const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap = {});
+ eventDeactivationMap = {});
virtual ~GaugeMetricProducer();
@@ -129,6 +127,8 @@
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
+ void prepareFirstBucketLocked() override;
+
void pullAndMatchEventsLocked(const int64_t timestampNs);
const int mWhatMatcherIndex;
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index d721514..4c4cd89 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -207,6 +207,11 @@
return clearPastBucketsLocked(dumpTimeNs);
}
+ void prepareFirstBucket() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ prepareFirstBucketLocked();
+ }
+
// Returns the memory in bytes currently used to store this metric's data. Does not change
// state.
size_t byteSize() const {
@@ -344,6 +349,7 @@
std::set<string> *str_set,
android::util::ProtoOutputStream* protoOutput) = 0;
virtual void clearPastBucketsLocked(const int64_t dumpTimeNs) = 0;
+ virtual void prepareFirstBucketLocked(){};
virtual size_t byteSizeLocked() const = 0;
virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
virtual void dropDataLocked(const int64_t dropTimeNs) = 0;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index fca48f9..8ed0cbc 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -70,6 +70,7 @@
mTtlEndNs(-1),
mLastReportTimeNs(currentTimeNs),
mLastReportWallClockNs(getWallClockNs()),
+ mPullerManager(pullerManager),
mShouldPersistHistory(config.persist_locally()) {
// Init the ttl end timestamp.
refreshTtl(timeBaseNs);
@@ -86,6 +87,7 @@
mVersionStringsInReport = config.version_strings_in_metric_report();
mInstallerInReport = config.installer_in_metric_report();
+ // Init allowed pushed atom uids.
if (config.allowed_log_source_size() == 0) {
mConfigValid = false;
ALOGE("Log source whitelist is empty! This config won't get any data. Suggest adding at "
@@ -108,6 +110,40 @@
}
}
+ // Init default allowed pull atom uids.
+ int numPullPackages = 0;
+ for (const string& pullSource : config.default_pull_packages()) {
+ auto it = UidMap::sAidToUidMapping.find(pullSource);
+ if (it != UidMap::sAidToUidMapping.end()) {
+ numPullPackages++;
+ mDefaultPullUids.insert(it->second);
+ } else {
+ ALOGE("Default pull atom packages must be in sAidToUidMapping");
+ mConfigValid = false;
+ }
+ }
+ // Init per-atom pull atom packages.
+ for (const PullAtomPackages& pullAtomPackages : config.pull_atom_packages()) {
+ int32_t atomId = pullAtomPackages.atom_id();
+ for (const string& pullPackage : pullAtomPackages.packages()) {
+ numPullPackages++;
+ auto it = UidMap::sAidToUidMapping.find(pullPackage);
+ if (it != UidMap::sAidToUidMapping.end()) {
+ mPullAtomUids[atomId].insert(it->second);
+ } else {
+ mPullAtomPackages[atomId].insert(pullPackage);
+ }
+ }
+ }
+ if (numPullPackages > StatsdStats::kMaxPullAtomPackages) {
+ ALOGE("Too many sources in default_pull_packages and pull_atom_packages. This is likely to "
+ "be an error in the config");
+ mConfigValid = false;
+ } else {
+ initPullAtomSources();
+ }
+ mPullerManager->RegisterPullUidProvider(mConfigKey, this);
+
// Store the sub-configs used.
for (const auto& annotation : config.annotation()) {
mAnnotations.emplace_back(annotation.field_int64(), annotation.field_int32());
@@ -153,6 +189,7 @@
StateManager::getInstance().unregisterListener(atomId, it);
}
}
+ mPullerManager->UnregisterPullUidProvider(mConfigKey);
VLOG("~MetricsManager()");
}
@@ -173,6 +210,20 @@
}
}
+void MetricsManager::initPullAtomSources() {
+ std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex);
+ mCombinedPullAtomUids.clear();
+ for (const auto& [atomId, uids] : mPullAtomUids) {
+ mCombinedPullAtomUids[atomId].insert(uids.begin(), uids.end());
+ }
+ for (const auto& [atomId, packages] : mPullAtomPackages) {
+ for (const string& pkg : packages) {
+ set<int32_t> uids = mUidMap->getAppUid(pkg);
+ mCombinedPullAtomUids[atomId].insert(uids.begin(), uids.end());
+ }
+ }
+}
+
bool MetricsManager::isConfigValid() const {
return mConfigValid;
}
@@ -184,12 +235,18 @@
it->notifyAppUpgrade(eventTimeNs, apk, uid, version);
}
// check if we care this package
- if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) == mAllowedPkg.end()) {
- return;
+ if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) != mAllowedPkg.end()) {
+ // We will re-initialize the whole list because we don't want to keep the multi mapping of
+ // UID<->pkg inside MetricsManager to reduce the memory usage.
+ initLogSourceWhiteList();
}
- // We will re-initialize the whole list because we don't want to keep the multi mapping of
- // UID<->pkg inside MetricsManager to reduce the memory usage.
- initLogSourceWhiteList();
+
+ for (const auto& it : mPullAtomPackages) {
+ if (it.second.find(apk) != it.second.end()) {
+ initPullAtomSources();
+ return;
+ }
+ }
}
void MetricsManager::notifyAppRemoved(const int64_t& eventTimeNs, const string& apk,
@@ -199,24 +256,49 @@
it->notifyAppRemoved(eventTimeNs, apk, uid);
}
// check if we care this package
- if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) == mAllowedPkg.end()) {
- return;
+ if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) != mAllowedPkg.end()) {
+ // We will re-initialize the whole list because we don't want to keep the multi mapping of
+ // UID<->pkg inside MetricsManager to reduce the memory usage.
+ initLogSourceWhiteList();
}
- // We will re-initialize the whole list because we don't want to keep the multi mapping of
- // UID<->pkg inside MetricsManager to reduce the memory usage.
- initLogSourceWhiteList();
+
+ for (const auto& it : mPullAtomPackages) {
+ if (it.second.find(apk) != it.second.end()) {
+ initPullAtomSources();
+ return;
+ }
+ }
}
void MetricsManager::onUidMapReceived(const int64_t& eventTimeNs) {
// Purposefully don't inform metric producers on a new snapshot
// because we don't need to flush partial buckets.
// This occurs if a new user is added/removed or statsd crashes.
+ initPullAtomSources();
+
if (mAllowedPkg.size() == 0) {
return;
}
initLogSourceWhiteList();
}
+void MetricsManager::init() {
+ for (const auto& producer : mAllMetricProducers) {
+ producer->prepareFirstBucket();
+ }
+}
+
+vector<int32_t> MetricsManager::getPullAtomUids(int32_t atomId) {
+ std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex);
+ vector<int32_t> uids;
+ const auto& it = mCombinedPullAtomUids.find(atomId);
+ if (it != mCombinedPullAtomUids.end()) {
+ uids.insert(uids.end(), it->second.begin(), it->second.end());
+ }
+ uids.insert(uids.end(), mDefaultPullUids.begin(), mDefaultPullUids.end());
+ return uids;
+}
+
void MetricsManager::dumpStates(FILE* out, bool verbose) {
fprintf(out, "ConfigKey %s, allowed source:", mConfigKey.ToString().c_str());
{
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 7500ec9..291f97b 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -35,7 +35,7 @@
namespace statsd {
// A MetricsManager is responsible for managing metrics from one single config source.
-class MetricsManager : public virtual android::RefBase {
+class MetricsManager : public virtual android::RefBase, public virtual PullUidProvider {
public:
MetricsManager(const ConfigKey& configKey, const StatsdConfig& config, const int64_t timeBaseNs,
const int64_t currentTimeNs, const sp<UidMap>& uidMap,
@@ -69,6 +69,10 @@
void onUidMapReceived(const int64_t& eventTimeNs);
+ void init();
+
+ vector<int32_t> getPullAtomUids(int32_t atomId) override;
+
bool shouldWriteToDisk() const {
return mNoReportMetricIds.size() != mAllMetricProducers.size();
}
@@ -159,6 +163,8 @@
int64_t mLastReportTimeNs;
int64_t mLastReportWallClockNs;
+ sp<StatsPullerManager> mPullerManager;
+
// The uid log sources from StatsdConfig.
std::vector<int32_t> mAllowedUid;
@@ -169,13 +175,27 @@
// Logs from uids that are not in the list will be ignored to avoid spamming.
std::set<int32_t> mAllowedLogSources;
+ // To guard access to mAllowedLogSources
+ mutable std::mutex mAllowedLogSourcesMutex;
+
+ // We can pull any atom from these uids.
+ std::set<int32_t> mDefaultPullUids;
+
+ // Uids that specific atoms can pull from.
+ // This is a map<atom id, set<uids>>
+ std::map<int32_t, std::set<int32_t>> mPullAtomUids;
+
+ // Packages that specific atoms can be pulled from.
+ std::map<int32_t, std::set<std::string>> mPullAtomPackages;
+
+ // All uids to pull for this atom. NOTE: Does not include the default uids for memory.
+ std::map<int32_t, std::set<int32_t>> mCombinedPullAtomUids;
+
// Contains the annotations passed in with StatsdConfig.
std::list<std::pair<const int64_t, const int32_t>> mAnnotations;
const bool mShouldPersistHistory;
- // To guard access to mAllowedLogSources
- mutable std::mutex mAllowedLogSourcesMutex;
// All event tags that are interesting to my metrics.
std::set<int> mTagIds;
@@ -238,6 +258,8 @@
void initLogSourceWhiteList();
+ void initPullAtomSources();
+
// The metrics that don't need to be uploaded or even reported.
std::set<int64_t> mNoReportMetricIds;
@@ -275,6 +297,8 @@
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);
+ FRIEND_TEST(MetricsManagerTest, TestLogSources);
+
FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index dc9b413..f34423a 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -156,7 +156,7 @@
flushIfNeededLocked(startTimeNs);
if (mIsPulled) {
- mPullerManager->RegisterReceiver(mPullTagId, this, getCurrentBucketEndTimeNs(),
+ mPullerManager->RegisterReceiver(mPullTagId, mConfigKey, this, getCurrentBucketEndTimeNs(),
mBucketSizeNs);
}
@@ -166,10 +166,6 @@
mCurrentBucketStartTimeNs = startTimeNs;
mConditionTimer.newBucketStart(mCurrentBucketStartTimeNs);
- // Kicks off the puller immediately if condition is true and diff based.
- if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
- pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
- }
// Now that activations are processed, start the condition timer if needed.
mConditionTimer.onConditionChanged(mIsActive && mCondition == ConditionState::kTrue,
mCurrentBucketStartTimeNs);
@@ -181,7 +177,7 @@
ValueMetricProducer::~ValueMetricProducer() {
VLOG("~ValueMetricProducer() called");
if (mIsPulled) {
- mPullerManager->UnRegisterReceiver(mPullTagId, this);
+ mPullerManager->UnRegisterReceiver(mPullTagId, mConfigKey, this);
}
}
@@ -503,9 +499,16 @@
mConditionTimer.onConditionChanged(mCondition, eventTimeNs);
}
+void ValueMetricProducer::prepareFirstBucketLocked() {
+ // Kicks off the puller immediately if condition is true and diff based.
+ if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
+ pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
+ }
+}
+
void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
vector<std::shared_ptr<LogEvent>> allData;
- if (!mPullerManager->Pull(mPullTagId, &allData)) {
+ if (!mPullerManager->Pull(mPullTagId, mConfigKey, &allData)) {
ALOGE("Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
invalidateCurrentBucket(timestampNs, BucketDropReason::PULL_FAILED);
return;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 50317b3..e9273dc 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -122,6 +122,8 @@
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
+ void prepareFirstBucketLocked() override;
+
void dropDataLocked(const int64_t dropTimeNs) override;
// Calculate previous bucket end time based on current time.
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index e5fe87a..3810c48 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -803,9 +803,8 @@
if (!success) return false;
sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
- key, metric, conditionIndex, wizard,
- trackerIndex, matcherWizard, pullTagId, triggerAtomId, atomTagId,
- timeBaseTimeNs, currentTimeNs, pullerManager,
+ key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId,
+ triggerAtomId, atomTagId, timeBaseTimeNs, currentTimeNs, pullerManager,
eventActivationMap, eventDeactivationMap);
allMetricProducers.push_back(gaugeProducer);
}
@@ -964,6 +963,7 @@
ALOGE("initConditionTrackers failed");
return false;
}
+
if (!initStates(config, stateAtomIdMap, allStateGroupMaps)) {
ALOGE("initStates failed");
return false;
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index ab0e86e..acf40c8 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -545,7 +545,15 @@
{"AID_LMKD", 1069},
{"AID_LLKD", 1070},
{"AID_IORAPD", 1071},
+ {"AID_GPU_SERVICE", 1072},
{"AID_NETWORK_STACK", 1073},
+ {"AID_GSID", 1074},
+ {"AID_FSVERITY_CERT", 1075},
+ {"AID_CREDSTORE", 1076},
+ {"AID_EXTERNAL_STORAGE", 1077},
+ {"AID_EXT_DATA_RW", 1078},
+ {"AID_EXT_OBB_RW", 1079},
+ {"AID_CONTEXT_HUB", 1080},
{"AID_SHELL", 2000},
{"AID_CACHE", 2001},
{"AID_DIAG", 2002}};
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 02fe7b1..22250ae 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -149,7 +149,7 @@
// Get currently cached value of memory used by UID map.
size_t getBytesUsed() const;
- std::set<int32_t> getAppUid(const string& package) const;
+ virtual std::set<int32_t> getAppUid(const string& package) const;
// Write current PackageInfoSnapshot to ProtoOutputStream.
// interestingUids: If not empty, only write the package info for these uids. If empty, write
diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp
index c677222..1cee4d9 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.cpp
+++ b/cmds/statsd/src/shell/ShellSubscriber.cpp
@@ -108,7 +108,21 @@
if (minInterval < 0 || pulled.freq_millis() < minInterval) {
minInterval = pulled.freq_millis();
}
- subscriptionInfo->mPulledInfo.emplace_back(pulled.matcher(), pulled.freq_millis());
+
+ vector<string> packages;
+ vector<int32_t> uids;
+ for (const string& pkg : pulled.packages()) {
+ auto it = UidMap::sAidToUidMapping.find(pkg);
+ if (it != UidMap::sAidToUidMapping.end()) {
+ uids.push_back(it->second);
+ } else {
+ packages.push_back(pkg);
+ }
+ }
+
+ subscriptionInfo->mPulledInfo.emplace_back(pulled.matcher(), pulled.freq_millis(), packages,
+ uids);
+ VLOG("adding matcher for pulled atom %d", pulled.matcher().atom_id());
}
subscriptionInfo->mPullIntervalMin = minInterval;
@@ -127,7 +141,15 @@
for (auto& pullInfo : mSubscriptionInfo->mPulledInfo) {
if (pullInfo.mPrevPullElapsedRealtimeMs + pullInfo.mInterval < nowMillis) {
vector<std::shared_ptr<LogEvent>> data;
- mPullerMgr->Pull(pullInfo.mPullerMatcher.atom_id(), &data);
+ vector<int32_t> uids;
+ uids.insert(uids.end(), pullInfo.mPullUids.begin(), pullInfo.mPullUids.end());
+ // This is slow. Consider storing the uids per app and listening to uidmap updates.
+ for (const string& pkg : pullInfo.mPullPackages) {
+ set<int32_t> uidsForPkg = mUidMap->getAppUid(pkg);
+ uids.insert(uids.end(), uidsForPkg.begin(), uidsForPkg.end());
+ }
+ uids.push_back(DEFAULT_PULL_UID);
+ mPullerMgr->Pull(pullInfo.mPullerMatcher.atom_id(), uids, &data);
VLOG("pulled %zu atoms with id %d", data.size(), pullInfo.mPullerMatcher.atom_id());
// TODO(b/150969574): Don't write to a pipe while holding a lock.
diff --git a/cmds/statsd/src/shell/ShellSubscriber.h b/cmds/statsd/src/shell/ShellSubscriber.h
index 2f9b61a..61457d8 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.h
+++ b/cmds/statsd/src/shell/ShellSubscriber.h
@@ -16,15 +16,17 @@
#pragma once
-#include "logd/LogEvent.h"
-
#include <android/util/ProtoOutputStream.h>
+#include <private/android_filesystem_config.h>
+
#include <condition_variable>
#include <mutex>
#include <thread>
+
#include "external/StatsPullerManager.h"
#include "frameworks/base/cmds/statsd/src/shell/shell_config.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "logd/LogEvent.h"
#include "packages/UidMap.h"
namespace android {
@@ -66,12 +68,19 @@
private:
struct PullInfo {
- PullInfo(const SimpleAtomMatcher& matcher, int64_t interval)
- : mPullerMatcher(matcher), mInterval(interval), mPrevPullElapsedRealtimeMs(0) {
+ PullInfo(const SimpleAtomMatcher& matcher, int64_t interval,
+ const std::vector<std::string>& packages, const std::vector<int32_t>& uids)
+ : mPullerMatcher(matcher),
+ mInterval(interval),
+ mPrevPullElapsedRealtimeMs(0),
+ mPullPackages(packages),
+ mPullUids(uids) {
}
SimpleAtomMatcher mPullerMatcher;
int64_t mInterval;
int64_t mPrevPullElapsedRealtimeMs;
+ std::vector<std::string> mPullPackages;
+ std::vector<int32_t> mPullUids;
};
struct SubscriptionInfo {
@@ -109,6 +118,8 @@
std::shared_ptr<SubscriptionInfo> mSubscriptionInfo = nullptr;
int mToken = 0;
+
+ const int32_t DEFAULT_PULL_UID = AID_SYSTEM;
};
} // namespace statsd
diff --git a/cmds/statsd/src/shell/shell_config.proto b/cmds/statsd/src/shell/shell_config.proto
index 73cb49a..07d0310 100644
--- a/cmds/statsd/src/shell/shell_config.proto
+++ b/cmds/statsd/src/shell/shell_config.proto
@@ -28,6 +28,9 @@
/* gap between two pulls in milliseconds */
optional int32 freq_millis = 2;
+
+ /* Packages that the pull is requested from */
+ repeated string packages = 3;
}
message ShellSubscription {
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 736aa9b..83d9484 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -428,6 +428,12 @@
repeated EventActivation event_activation = 2;
}
+message PullAtomPackages {
+ optional int32 atom_id = 1;
+
+ repeated string packages = 2;
+}
+
message StatsdConfig {
optional int64 id = 1;
@@ -475,6 +481,10 @@
repeated State state = 21;
+ repeated string default_pull_packages = 22;
+
+ repeated PullAtomPackages pull_atom_packages = 23;
+
// Field number 1000 is reserved for later use.
reserved 1000;
}
diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp
index 356e40b..1075fe4 100644
--- a/cmds/statsd/tests/MetricsManager_test.cpp
+++ b/cmds/statsd/tests/MetricsManager_test.cpp
@@ -13,7 +13,15 @@
// limitations under the License.
#include <gtest/gtest.h>
+#include <private/android_filesystem_config.h>
+#include <stdio.h>
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "metrics/metrics_test_helper.h"
#include "src/condition/ConditionTracker.h"
#include "src/matchers/LogMatchingTracker.h"
#include "src/metrics/CountMetricProducer.h"
@@ -23,22 +31,21 @@
#include "src/metrics/metrics_manager_util.h"
#include "statsd_test_util.h"
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-
-#include <stdio.h>
-#include <set>
-#include <unordered_map>
-#include <vector>
-
-using namespace android::os::statsd;
+using namespace testing;
using android::sp;
+using android::os::statsd::Predicate;
+using std::map;
using std::set;
using std::unordered_map;
using std::vector;
-using android::os::statsd::Predicate;
#ifdef __ANDROID__
+namespace android {
+namespace os {
+namespace statsd {
+
+namespace {
const ConfigKey kConfigKey(0, 12345);
const long kAlertId = 3;
@@ -268,6 +275,11 @@
return config;
}
+bool isSubset(const set<int32_t>& set1, const set<int32_t>& set2) {
+ return std::includes(set2.begin(), set2.end(), set1.begin(), set1.end());
+}
+} // anonymous namespace
+
TEST(MetricsManagerTest, TestGoodConfig) {
UidMap uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
@@ -488,6 +500,101 @@
noReportMetricIds));
}
+TEST(MetricsManagerTest, TestLogSources) {
+ string app1 = "app1";
+ set<int32_t> app1Uids = {1111, 11111};
+ string app2 = "app2";
+ set<int32_t> app2Uids = {2222};
+ string app3 = "app3";
+ set<int32_t> app3Uids = {3333, 1111};
+
+ map<string, set<int32_t>> pkgToUids;
+ pkgToUids[app1] = app1Uids;
+ pkgToUids[app2] = app2Uids;
+ pkgToUids[app3] = app3Uids;
+
+ int32_t atom1 = 10;
+ int32_t atom2 = 20;
+ int32_t atom3 = 30;
+ sp<MockUidMap> uidMap = new StrictMock<MockUidMap>();
+ EXPECT_CALL(*uidMap, getAppUid(_))
+ .Times(4)
+ .WillRepeatedly(Invoke([&pkgToUids](const string& pkg) {
+ const auto& it = pkgToUids.find(pkg);
+ if (it != pkgToUids.end()) {
+ return it->second;
+ }
+ return set<int32_t>();
+ }));
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1);
+ EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey)).Times(1);
+
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+
+ StatsdConfig config = buildGoodConfig();
+ config.add_allowed_log_source("AID_SYSTEM");
+ config.add_allowed_log_source(app1);
+ config.add_default_pull_packages("AID_SYSTEM");
+ config.add_default_pull_packages("AID_ROOT");
+
+ const set<int32_t> defaultPullUids = {AID_SYSTEM, AID_ROOT};
+
+ PullAtomPackages* pullAtomPackages = config.add_pull_atom_packages();
+ pullAtomPackages->set_atom_id(atom1);
+ pullAtomPackages->add_packages(app1);
+ pullAtomPackages->add_packages(app3);
+
+ pullAtomPackages = config.add_pull_atom_packages();
+ pullAtomPackages->set_atom_id(atom2);
+ pullAtomPackages->add_packages(app2);
+ pullAtomPackages->add_packages("AID_STATSD");
+
+ MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
+ pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
+
+ EXPECT_TRUE(metricsManager.isConfigValid());
+
+ ASSERT_EQ(metricsManager.mAllowedUid.size(), 1);
+ EXPECT_EQ(metricsManager.mAllowedUid[0], AID_SYSTEM);
+
+ ASSERT_EQ(metricsManager.mAllowedPkg.size(), 1);
+ EXPECT_EQ(metricsManager.mAllowedPkg[0], app1);
+
+ ASSERT_EQ(metricsManager.mAllowedLogSources.size(), 3);
+ EXPECT_TRUE(isSubset({AID_SYSTEM}, metricsManager.mAllowedLogSources));
+ EXPECT_TRUE(isSubset(app1Uids, metricsManager.mAllowedLogSources));
+
+ ASSERT_EQ(metricsManager.mDefaultPullUids.size(), 2);
+ EXPECT_TRUE(isSubset(defaultPullUids, metricsManager.mDefaultPullUids));
+ ;
+
+ vector<int32_t> atom1Uids = metricsManager.getPullAtomUids(atom1);
+ ASSERT_EQ(atom1Uids.size(), 5);
+ set<int32_t> expectedAtom1Uids;
+ expectedAtom1Uids.insert(defaultPullUids.begin(), defaultPullUids.end());
+ expectedAtom1Uids.insert(app1Uids.begin(), app1Uids.end());
+ expectedAtom1Uids.insert(app3Uids.begin(), app3Uids.end());
+ EXPECT_TRUE(isSubset(expectedAtom1Uids, set<int32_t>(atom1Uids.begin(), atom1Uids.end())));
+
+ vector<int32_t> atom2Uids = metricsManager.getPullAtomUids(atom2);
+ ASSERT_EQ(atom2Uids.size(), 4);
+ set<int32_t> expectedAtom2Uids;
+ expectedAtom1Uids.insert(defaultPullUids.begin(), defaultPullUids.end());
+ expectedAtom1Uids.insert(app2Uids.begin(), app2Uids.end());
+ expectedAtom1Uids.insert(AID_STATSD);
+ EXPECT_TRUE(isSubset(expectedAtom2Uids, set<int32_t>(atom2Uids.begin(), atom2Uids.end())));
+
+ vector<int32_t> atom3Uids = metricsManager.getPullAtomUids(atom3);
+ ASSERT_EQ(atom3Uids.size(), 2);
+ EXPECT_TRUE(isSubset(defaultPullUids, set<int32_t>(atom3Uids.begin(), atom3Uids.end())));
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index ca4de6d..c234b14 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -38,6 +38,7 @@
bool useCondition = true) {
StatsdConfig config;
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
auto atomMatcher = CreateSimpleAtomMatcher("TestMatcher", ATOM_TAG);
*config.add_atom_matcher() = atomMatcher;
*config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 371a346..b173ee0 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -71,6 +71,7 @@
StatsdConfig MakeValueMetricConfig(int64_t minTime) {
StatsdConfig config;
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
auto pulledAtomMatcher =
CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
@@ -94,6 +95,7 @@
StatsdConfig MakeGaugeMetricConfig(int64_t minTime) {
StatsdConfig config;
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
auto pulledAtomMatcher =
CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index a5ef733..0c4a7c6 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -36,6 +36,7 @@
StatsdConfig CreateStatsdConfig(bool useCondition = true) {
StatsdConfig config;
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
auto pulledAtomMatcher =
CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
*config.add_atom_matcher() = pulledAtomMatcher;
diff --git a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
index 1ff6621..6aff9ef 100644
--- a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
+++ b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
@@ -187,15 +187,16 @@
pullDelayNs = 500000000; // 500 ms.
pullTimeoutNs = 10000; // 10 microsseconds.
int64_t value = 4321;
+ int32_t uid = 123;
values.push_back(value);
StatsPullerManager pullerManager;
- pullerManager.RegisterPullAtomCallback(/*uid=*/-1, pullTagId, pullCoolDownNs, pullTimeoutNs,
+ pullerManager.RegisterPullAtomCallback(uid, pullTagId, pullCoolDownNs, pullTimeoutNs,
vector<int32_t>(), cb);
vector<shared_ptr<LogEvent>> dataHolder;
int64_t startTimeNs = getElapsedRealtimeNs();
// Returns false, since StatsPuller code will evaluate the timeout.
- EXPECT_FALSE(pullerManager.Pull(pullTagId, &dataHolder));
+ EXPECT_FALSE(pullerManager.Pull(pullTagId, {uid}, &dataHolder));
int64_t endTimeNs = getElapsedRealtimeNs();
int64_t actualPullDurationNs = endTimeNs - startTimeNs;
diff --git a/cmds/statsd/tests/external/StatsPullerManager_test.cpp b/cmds/statsd/tests/external/StatsPullerManager_test.cpp
new file mode 100644
index 0000000..6b3f4cc
--- /dev/null
+++ b/cmds/statsd/tests/external/StatsPullerManager_test.cpp
@@ -0,0 +1,150 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/external/StatsPullerManager.h"
+
+#include <aidl/android/os/IPullAtomResultReceiver.h>
+#include <aidl/android/util/StatsEventParcel.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "stats_event.h"
+#include "tests/statsd_test_util.h"
+
+using aidl::android::util::StatsEventParcel;
+using ::ndk::SharedRefBase;
+using std::make_shared;
+using std::shared_ptr;
+using std::vector;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+namespace {
+
+int pullTagId1 = 10101;
+int pullTagId2 = 10102;
+int uid1 = 9999;
+int uid2 = 8888;
+ConfigKey configKey(50, 12345);
+ConfigKey badConfigKey(60, 54321);
+int unregisteredUid = 98765;
+int64_t coolDownNs = NS_PER_SEC;
+int64_t timeoutNs = NS_PER_SEC / 2;
+
+AStatsEvent* createSimpleEvent(int32_t atomId, int32_t value) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, atomId);
+ AStatsEvent_writeInt32(event, value);
+ AStatsEvent_build(event);
+ return event;
+}
+
+class FakePullAtomCallback : public BnPullAtomCallback {
+public:
+ FakePullAtomCallback(int32_t uid) : mUid(uid){};
+ Status onPullAtom(int atomTag,
+ const shared_ptr<IPullAtomResultReceiver>& resultReceiver) override {
+ vector<StatsEventParcel> parcels;
+ AStatsEvent* event = createSimpleEvent(atomTag, mUid);
+ size_t size;
+ uint8_t* buffer = AStatsEvent_getBuffer(event, &size);
+
+ StatsEventParcel p;
+ // vector.assign() creates a copy, but this is inevitable unless
+ // stats_event.h/c uses a vector as opposed to a buffer.
+ p.buffer.assign(buffer, buffer + size);
+ parcels.push_back(std::move(p));
+ AStatsEvent_release(event);
+ resultReceiver->pullFinished(atomTag, /*success*/ true, parcels);
+ return Status::ok();
+ }
+ int32_t mUid;
+};
+
+class FakePullUidProvider : public PullUidProvider {
+public:
+ vector<int32_t> getPullAtomUids(int atomId) override {
+ if (atomId == pullTagId1) {
+ return {uid2, uid1};
+ } else if (atomId == pullTagId2) {
+ return {uid2};
+ }
+ return {};
+ }
+};
+
+sp<StatsPullerManager> createPullerManagerAndRegister() {
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ shared_ptr<FakePullAtomCallback> cb1 = SharedRefBase::make<FakePullAtomCallback>(uid1);
+ pullerManager->RegisterPullAtomCallback(uid1, pullTagId1, coolDownNs, timeoutNs, {}, cb1, true);
+ shared_ptr<FakePullAtomCallback> cb2 = SharedRefBase::make<FakePullAtomCallback>(uid2);
+ pullerManager->RegisterPullAtomCallback(uid2, pullTagId1, coolDownNs, timeoutNs, {}, cb2, true);
+ pullerManager->RegisterPullAtomCallback(uid1, pullTagId2, coolDownNs, timeoutNs, {}, cb1, true);
+ return pullerManager;
+}
+} // anonymous namespace
+
+TEST(StatsPullerManagerTest, TestPullInvalidUid) {
+ sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
+
+ vector<shared_ptr<LogEvent>> data;
+ EXPECT_FALSE(pullerManager->Pull(pullTagId1, {unregisteredUid}, &data, true));
+}
+
+TEST(StatsPullerManagerTest, TestPullChoosesCorrectUid) {
+ sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
+
+ vector<shared_ptr<LogEvent>> data;
+ EXPECT_TRUE(pullerManager->Pull(pullTagId1, {uid1}, &data, true));
+ ASSERT_EQ(data.size(), 1);
+ EXPECT_EQ(data[0]->GetTagId(), pullTagId1);
+ ASSERT_EQ(data[0]->getValues().size(), 1);
+ EXPECT_EQ(data[0]->getValues()[0].mValue.int_value, uid1);
+}
+
+TEST(StatsPullerManagerTest, TestPullInvalidConfigKey) {
+ sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
+ sp<FakePullUidProvider> uidProvider = new FakePullUidProvider();
+ pullerManager->RegisterPullUidProvider(configKey, uidProvider);
+
+ vector<shared_ptr<LogEvent>> data;
+ EXPECT_FALSE(pullerManager->Pull(pullTagId1, badConfigKey, &data, true));
+}
+
+TEST(StatsPullerManagerTest, TestPullConfigKeyGood) {
+ sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
+ sp<FakePullUidProvider> uidProvider = new FakePullUidProvider();
+ pullerManager->RegisterPullUidProvider(configKey, uidProvider);
+
+ vector<shared_ptr<LogEvent>> data;
+ EXPECT_TRUE(pullerManager->Pull(pullTagId1, configKey, &data, true));
+ EXPECT_EQ(data[0]->GetTagId(), pullTagId1);
+ ASSERT_EQ(data[0]->getValues().size(), 1);
+ EXPECT_EQ(data[0]->getValues()[0].mValue.int_value, uid2);
+}
+
+TEST(StatsPullerManagerTest, TestPullConfigKeyNoPullerWithUid) {
+ sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
+ sp<FakePullUidProvider> uidProvider = new FakePullUidProvider();
+ pullerManager->RegisterPullUidProvider(configKey, uidProvider);
+
+ vector<shared_ptr<LogEvent>> data;
+ EXPECT_FALSE(pullerManager->Pull(pullTagId2, configKey, &data, true));
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index d372ffd..2fe05a4 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -105,6 +105,7 @@
logEventMatcherIndex, eventMatcherWizard,
-1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2,
pullerManager);
+ gaugeProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, gaugeProducer.mCurrentBucketNum);
@@ -132,10 +133,11 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(makeLogEvent(tagId, bucketStartTimeNs + 10, 3, "some value", 11));
return true;
@@ -144,6 +146,7 @@
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -222,6 +225,7 @@
logEventMatcherIndex, eventMatcherWizard,
-1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
@@ -287,19 +291,21 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Return(false))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, eventUpgradeTimeNs, 2));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, eventUpgradeTimeNs, 2));
+ return true;
+ }));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
@@ -351,13 +357,14 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
@@ -399,10 +406,11 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 100));
return true;
@@ -411,6 +419,7 @@
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
@@ -481,10 +490,11 @@
}));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 10, 1000, 100));
return true;
@@ -493,6 +503,7 @@
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
@@ -517,9 +528,9 @@
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false));
GaugeMetric metric;
metric.set_id(metricId);
@@ -539,6 +550,7 @@
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
Alert alert;
alert.set_id(101);
@@ -616,13 +628,15 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 4));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 5));
return true;
@@ -633,6 +647,7 @@
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, triggerId,
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
@@ -682,18 +697,21 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 3, 3, 4));
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 3, 3, 4));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 10, 4, 5));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20, 4, 6));
return true;
@@ -704,6 +722,7 @@
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, triggerId,
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
LogEvent triggerEvent(/*uid=*/0, /*pid=*/0);
CreateNoValuesLogEvent(&triggerEvent, triggerId, bucketStartTimeNs + 3);
@@ -752,18 +771,20 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Bucket start.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 10));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 10));
+ return true;
+ }));
int triggerId = 5;
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, triggerId,
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
LogEvent triggerEvent(/*uid=*/0, /*pid=*/0);
CreateNoValuesLogEvent(&triggerEvent, triggerId, bucketStartTimeNs + 3);
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index c1d4693..b623a09 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -90,12 +90,15 @@
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
+ .WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
+ .WillRepeatedly(Return());
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -108,12 +111,15 @@
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
+ .WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
+ .WillRepeatedly(Return());
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer->prepareFirstBucket();
valueProducer->mCondition = ConditionState::kFalse;
return valueProducer;
}
@@ -127,12 +133,15 @@
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
+ .WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
+ .WillRepeatedly(Return());
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -147,12 +156,15 @@
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
+ .WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
+ .WillRepeatedly(Return());
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
{}, slicedStateAtoms, stateGroupMap);
+ valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -200,6 +212,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
22, pullerManager);
+ valueProducer.prepareFirstBucket();
EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
@@ -229,6 +242,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1, 5,
600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
+ valueProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
@@ -241,12 +255,13 @@
TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -313,15 +328,17 @@
TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialize bucket.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
return true;
}))
// Partial bucket.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
return true;
@@ -369,18 +386,20 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
- return true;
- }));
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer->prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -440,7 +459,7 @@
metric.set_use_absolute_value_on_reset(true);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -499,7 +518,7 @@
TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -554,18 +573,21 @@
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 130));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 180));
return true;
@@ -631,6 +653,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -666,11 +689,12 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Return(true))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 149, 120));
return true;
@@ -678,6 +702,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -714,12 +739,13 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -737,13 +763,15 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 120));
return true;
@@ -781,6 +809,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -823,6 +852,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -891,6 +921,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
@@ -947,7 +978,7 @@
TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -1008,15 +1039,17 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
}))
// condition becomes false
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
return true;
@@ -1065,21 +1098,24 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
}))
// condition becomes false
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
return true;
}))
// condition becomes true again
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 25, 130));
return true;
@@ -1156,6 +1192,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -1198,6 +1235,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -1242,6 +1280,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -1289,6 +1328,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -1331,6 +1371,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -1400,6 +1441,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateThreeValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10, 20);
@@ -1496,12 +1538,13 @@
metric.set_use_zero_default_base(true);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
- return true;
- }));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -1571,12 +1614,13 @@
metric.set_use_zero_default_base(true);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
- return true;
- }));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -1675,12 +1719,13 @@
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
- return true;
- }));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -1772,8 +1817,9 @@
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
// Used by onConditionChanged.
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
@@ -1804,8 +1850,9 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
@@ -1840,13 +1887,15 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50));
- return false;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50));
+ return false;
+ }))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
@@ -1878,8 +1927,9 @@
metric.set_max_pull_delay_sec(0);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 120));
return true;
@@ -1906,12 +1956,13 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucket2StartTimeNs,
bucket2StartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
// Event should be skipped since it is from previous bucket.
@@ -1924,8 +1975,9 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
return true;
@@ -1956,11 +2008,12 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
.WillOnce(Return(false))
// Second onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
return true;
@@ -2032,9 +2085,10 @@
metric.set_condition(StringToId("SCREEN_ON"));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
for (int i = 0; i < 2000; i++) {
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
}
@@ -2088,15 +2142,17 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
return true;
}))
// Second onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
return true;
@@ -2164,15 +2220,17 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
return true;
}))
// Second onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
return true;
@@ -2234,13 +2292,14 @@
TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Start bucket.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -2266,17 +2325,19 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2304,23 +2365,26 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
+ return true;
+ }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2360,13 +2424,14 @@
metric.set_condition(StringToId("SCREEN_ON"));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2400,15 +2465,17 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialization.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
// notifyAppUpgrade.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(
tagId, bucketStartTimeNs + bucketSizeNs / 2, 10));
@@ -2430,15 +2497,17 @@
TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Second onConditionChanged.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
return true;
}))
// Third onConditionChanged.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 10, 7));
return true;
@@ -2495,13 +2564,14 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialization.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -2522,15 +2592,17 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialization.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
// notifyAppUpgrade.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 2, 10));
return true;
@@ -2549,19 +2621,21 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First on condition changed.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
// Second on condition changed.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2588,25 +2662,28 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First condition change.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
// 2nd condition change.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
+ return true;
+ }))
// 3rd condition change.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2642,12 +2719,13 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initial pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
return true;
@@ -2656,6 +2734,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
ProtoOutputStream output;
std::set<string> strSet;
@@ -2678,12 +2757,13 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initial pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
return true;
@@ -2692,6 +2772,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -2720,17 +2801,19 @@
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initial pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10, tagId, 3, 3));
@@ -2740,6 +2823,7 @@
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
ProtoOutputStream output;
std::set<string> strSet;
@@ -2773,15 +2857,17 @@
metric.set_use_diff(false);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
return true;
}))
// condition becomes false
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 20));
return true;
@@ -2818,9 +2904,10 @@
metric.set_use_diff(false);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
return true;
@@ -2867,9 +2954,10 @@
metric.set_use_diff(false);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
return true;
@@ -2905,9 +2993,10 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 10));
return true;
@@ -2949,9 +3038,10 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
return true;
@@ -3001,15 +3091,17 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 100, 15));
return true;
@@ -3062,15 +3154,17 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 100, 15));
return true;
@@ -3114,9 +3208,10 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
return true;
@@ -3161,15 +3256,17 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1000, 15));
return true;
@@ -3215,15 +3312,17 @@
metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 9000000, 15));
@@ -3266,9 +3365,10 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
return true;
@@ -3316,9 +3416,10 @@
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First condition change event.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
for (int i = 0; i < 2000; i++) {
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
}
@@ -3333,7 +3434,8 @@
.WillOnce(Return(false))
.WillOnce(Return(false))
.WillOnce(Return(false))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 220, 10));
return true;
@@ -3431,33 +3533,38 @@
// Set up ValueMetricProducer.
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// ValueMetricProducer initialized.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }))
// Screen state change to ON.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5));
return true;
}))
// Screen state change to OFF.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9));
return true;
}))
// Screen state change to ON.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30));
return true;
@@ -3582,33 +3689,38 @@
// Set up ValueMetricProducer.
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// ValueMetricProducer initialized.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }))
// Screen state change to ON.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5));
return true;
}))
// Screen state change to VR.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9));
return true;
}))
// Screen state change to OFF.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30));
return true;
@@ -3748,16 +3860,18 @@
*fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// ValueMetricProducer initialized.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 2 /*uid*/, 7));
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1 /*uid*/, 3));
return true;
}))
// Uid 1 process state change from kStateUnknown -> Foreground
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20, 1 /*uid*/, 6));
@@ -3768,7 +3882,8 @@
return true;
}))
// Uid 2 process state change from kStateUnknown -> Background
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 40, 2 /*uid*/, 9));
@@ -3779,7 +3894,8 @@
return true;
}))
// Uid 1 process state change from Foreground -> Background
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 20, 1 /*uid*/, 13));
@@ -3790,7 +3906,8 @@
return true;
}))
// Uid 1 process state change from Background -> Foreground
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 40, 1 /*uid*/, 17));
@@ -3801,7 +3918,8 @@
return true;
}))
// Dump report pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 50, 2 /*uid*/, 20));
diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.h b/cmds/statsd/tests/metrics/metrics_test_helper.h
index 09c4d9e..69f7e3f 100644
--- a/cmds/statsd/tests/metrics/metrics_test_helper.h
+++ b/cmds/statsd/tests/metrics/metrics_test_helper.h
@@ -33,15 +33,24 @@
class MockStatsPullerManager : public StatsPullerManager {
public:
- MOCK_METHOD4(RegisterReceiver, void(int tagId, wp<PullDataReceiver> receiver,
- int64_t nextPulltimeNs, int64_t intervalNs));
- MOCK_METHOD2(UnRegisterReceiver, void(int tagId, wp<PullDataReceiver> receiver));
- MOCK_METHOD2(Pull, bool(const int pullCode, vector<std::shared_ptr<LogEvent>>* data));
+ MOCK_METHOD5(RegisterReceiver,
+ void(int tagId, const ConfigKey& key, wp<PullDataReceiver> receiver,
+ int64_t nextPulltimeNs, int64_t intervalNs));
+ MOCK_METHOD3(UnRegisterReceiver,
+ void(int tagId, const ConfigKey& key, wp<PullDataReceiver> receiver));
+ MOCK_METHOD4(Pull, bool(const int pullCode, const ConfigKey& key,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids));
+ MOCK_METHOD4(Pull, bool(const int pullCode, const vector<int32_t>& uids,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids));
+ MOCK_METHOD2(RegisterPullUidProvider,
+ void(const ConfigKey& configKey, wp<PullUidProvider> provider));
+ MOCK_METHOD1(UnregisterPullUidProvider, void(const ConfigKey& configKey));
};
class MockUidMap : public UidMap {
public:
MOCK_CONST_METHOD1(getHostUidOrSelf, int(int uid));
+ MOCK_CONST_METHOD1(getAppUid, std::set<int32_t>(const string& package));
};
HashableDimensionKey getMockedDimensionKey(int tagId, int key, std::string value);
diff --git a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
index 5eef92e..ac3ad69 100644
--- a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
+++ b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
@@ -187,8 +187,10 @@
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(10016, _))
- .WillRepeatedly(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ const vector<int32_t> uids = {AID_SYSTEM};
+ EXPECT_CALL(*pullerManager, Pull(10016, uids, _, _))
+ .WillRepeatedly(Invoke([](int tagId, const vector<int32_t>&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(makeCpuActiveTimeAtom(/*uid=*/kUid1, /*timeMillis=*/kCpuTime1));
data->push_back(makeCpuActiveTimeAtom(/*uid=*/kUid2, /*timeMillis=*/kCpuTime2));
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
index c97f035..75518a3 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
@@ -19,6 +19,7 @@
import com.android.internal.os.StatsdConfigProto.EventMetric;
import com.android.internal.os.StatsdConfigProto.FieldFilter;
import com.android.internal.os.StatsdConfigProto.GaugeMetric;
+import com.android.internal.os.StatsdConfigProto.PullAtomPackages;
import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
import com.android.internal.os.StatsdConfigProto.StatsdConfig;
import com.android.internal.os.StatsdConfigProto.TimeUnit;
@@ -33,6 +34,7 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -49,19 +51,22 @@
private static final int VENDOR_PULLED_ATOM_START_TAG = 150000;
private static final long CONFIG_ID = 54321;
private static final String[] ALLOWED_LOG_SOURCES = {
- "AID_GRAPHICS",
- "AID_INCIDENTD",
- "AID_STATSD",
- "AID_RADIO",
- "com.android.systemui",
- "com.android.vending",
- "AID_SYSTEM",
- "AID_ROOT",
- "AID_BLUETOOTH",
- "AID_LMKD",
- "com.android.managedprovisioning",
- "AID_MEDIA",
- "AID_NETWORK_STACK"
+ "AID_GRAPHICS",
+ "AID_INCIDENTD",
+ "AID_STATSD",
+ "AID_RADIO",
+ "com.android.systemui",
+ "com.android.vending",
+ "AID_SYSTEM",
+ "AID_ROOT",
+ "AID_BLUETOOTH",
+ "AID_LMKD",
+ "com.android.managedprovisioning",
+ "AID_MEDIA",
+ "AID_NETWORK_STACK"
+ };
+ private static final String[] DEFAULT_PULL_SOURCES = {
+ "AID_SYSTEM",
};
private static final Logger LOGGER = Logger.getLogger(TestDrive.class.getName());
@@ -158,6 +163,16 @@
StatsdConfig.Builder builder = StatsdConfig.newBuilder();
builder
.addAllAllowedLogSource(allowedSources)
+ .addAllDefaultPullPackages(Arrays.asList(DEFAULT_PULL_SOURCES))
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(Atom.GPU_STATS_GLOBAL_INFO_FIELD_NUMBER)
+ .addPackages("AID_GPU_SERVICE"))
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(Atom.GPU_STATS_APP_INFO_FIELD_NUMBER)
+ .addPackages("AID_GPU_SERVICE"))
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(Atom.TRAIN_INFO_FIELD_NUMBER)
+ .addPackages("AID_STATSD"))
.setHashStringsInMetricReport(false);
if (hasPulledAtom(atomIds)) {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index f926075..39fc18d 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -394,4 +394,29 @@
*/
// TODO: remove this toast after feature development is done
public abstract void showWhileInUseDebugToast(int uid, int op, int mode);
+
+
+ /** Is this a device owner app? */
+ public abstract boolean isDeviceOwner(int uid);
+
+ /**
+ * Called by DevicePolicyManagerService to set the uid of the device owner.
+ */
+ public abstract void setDeviceOwnerUid(int uid);
+
+ /**
+ * Sends a broadcast, assuming the caller to be the system and allowing the inclusion of an
+ * approved whitelist of app Ids >= {@link android.os.Process#FIRST_APPLICATION_UID} that the
+ * broadcast my be sent to; any app Ids < {@link android.os.Process#FIRST_APPLICATION_UID} are
+ * automatically whitelisted.
+ *
+ * @see com.android.server.am.ActivityManagerService#broadcastIntentWithFeature(
+ * IApplicationThread, String, Intent, String, IIntentReceiver, int, String, Bundle,
+ * String[], int, Bundle, boolean, boolean, int)
+ */
+ public abstract int broadcastIntent(Intent intent,
+ IIntentReceiver resultTo,
+ String[] requiredPermissions, boolean serialized,
+ int userId, int[] appIdWhitelist);
+
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index a5dcefc..46b06fb 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -990,7 +990,7 @@
/** @hide Control whether an application is allowed to run in the background. */
@UnsupportedAppUsage
public static final int OP_RUN_IN_BACKGROUND =
- AppProtoEnums.APP_OP_RUN_ANY_IN_BACKGROUND;
+ AppProtoEnums.APP_OP_RUN_IN_BACKGROUND;
/** @hide */
@UnsupportedAppUsage
public static final int OP_AUDIO_ACCESSIBILITY_VOLUME =
@@ -1496,8 +1496,6 @@
OP_MANAGE_EXTERNAL_STORAGE,
OP_INTERACT_ACROSS_PROFILES,
OP_LOADER_USAGE_STATS,
- OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
- OP_AUTO_REVOKE_MANAGED_BY_INSTALLER,
};
/**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 17fd4ef..bb64c34 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1763,7 +1763,6 @@
return bindServiceCommon(service, conn, flags, instanceName, null, executor, getUser());
}
- /** @hide */
@Override
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
@@ -1920,7 +1919,9 @@
return SystemServiceRegistry.getSystemServiceName(serviceClass);
}
- private boolean isUiContext() {
+ /** @hide */
+ @Override
+ public boolean isUiContext() {
return mIsSystemOrSystemUiContext || mIsUiContext || isSystemOrSystemUI();
}
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 8b8ebe8..e476993 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -298,13 +298,6 @@
void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration,
in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations);
- /**
- * Dismisses PiP
- * @param animate True if the dismissal should be animated.
- * @param animationDuration The duration of the resize animation in milliseconds or -1 if the
- * default animation duration should be used.
- */
- void dismissPip(boolean animate, int animationDuration);
void suppressResizeConfigChanges(boolean suppress);
void moveTasksToFullscreenStack(int fromStackId, boolean onTop);
boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds);
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 392c05a..d00366b 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -214,11 +214,10 @@
for (int i = mCachedApkAssets.size() - 1; i >= 0; i--) {
final ApkKey key = mCachedApkAssets.keyAt(i);
if (key.path.equals(path)) {
- WeakReference<ApkAssets> apkAssetsRef = mCachedApkAssets.remove(key);
+ WeakReference<ApkAssets> apkAssetsRef = mCachedApkAssets.removeAt(i);
if (apkAssetsRef != null && apkAssetsRef.get() != null) {
apkAssetsRef.get().close();
}
- mCachedApkAssets.remove(key);
}
}
}
@@ -774,19 +773,21 @@
* Rebases a key's override config on top of the Activity's base override.
*/
private void rebaseKeyForActivity(IBinder activityToken, ResourcesKey key) {
- final ActivityResources activityResources =
- getOrCreateActivityResourcesStructLocked(activityToken);
+ synchronized (this) {
+ final ActivityResources activityResources =
+ getOrCreateActivityResourcesStructLocked(activityToken);
- // Clean up any dead references so they don't pile up.
- ArrayUtils.unstableRemoveIf(activityResources.activityResources,
- sEmptyReferencePredicate);
+ // Clean up any dead references so they don't pile up.
+ ArrayUtils.unstableRemoveIf(activityResources.activityResources,
+ sEmptyReferencePredicate);
- // Rebase the key's override config on top of the Activity's base override.
- if (key.hasOverrideConfiguration()
- && !activityResources.overrideConfig.equals(Configuration.EMPTY)) {
- final Configuration temp = new Configuration(activityResources.overrideConfig);
- temp.updateFrom(key.mOverrideConfiguration);
- key.mOverrideConfiguration.setTo(temp);
+ // Rebase the key's override config on top of the Activity's base override.
+ if (key.hasOverrideConfiguration()
+ && !activityResources.overrideConfig.equals(Configuration.EMPTY)) {
+ final Configuration temp = new Configuration(activityResources.overrideConfig);
+ temp.updateFrom(key.mOverrideConfiguration);
+ key.mOverrideConfiguration.setTo(temp);
+ }
}
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 1aabd24..054e5e0 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1310,7 +1310,7 @@
throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(
Context.FILE_INTEGRITY_SERVICE);
- return new FileIntegrityManager(
+ return new FileIntegrityManager(ctx.getOuterContext(),
IFileIntegrityService.Stub.asInterface(b));
}});
//CHECKSTYLE:ON IndentationCheck
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2fe935e..e21a31e 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -6103,4 +6103,13 @@
+ "get a UI context from ActivityThread#getSystemUiContext()");
}
}
+
+ /**
+ * Indicates if this context is a visual context such as {@link android.app.Activity} or
+ * a context created from {@link #createWindowContext(int, Bundle)}.
+ * @hide
+ */
+ public boolean isUiContext() {
+ throw new RuntimeException("Not implemented. Must override in a subclass.");
+ }
}
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index d389d2a..5dc41e4 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1145,4 +1145,12 @@
mBase.setContentCaptureOptions(options);
}
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean isUiContext() {
+ return mBase.isUiContext();
+ }
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 1e0b2e3..85a3986 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -72,7 +72,6 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
-import java.util.stream.Collectors;
/**
* Offers the ability to install, upgrade, and remove applications on the
@@ -589,9 +588,15 @@
* * {@link SessionInfo#isStagedSessionActive()}.
*/
public @NonNull List<SessionInfo> getActiveStagedSessions() {
- return getStagedSessions().stream()
- .filter(s -> s.isStagedSessionActive())
- .collect(Collectors.toList());
+ final List<SessionInfo> activeStagedSessions = new ArrayList<>();
+ final List<SessionInfo> stagedSessions = getStagedSessions();
+ for (int i = 0; i < stagedSessions.size(); i++) {
+ final SessionInfo sessionInfo = stagedSessions.get(i);
+ if (sessionInfo.isStagedSessionActive()) {
+ activeStagedSessions.add(sessionInfo);
+ }
+ }
+ return activeStagedSessions;
}
/**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 370469e..f48d78a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1031,6 +1031,27 @@
*/
public static final int INSTALL_REASON_ROLLBACK = 5;
+ /** @hide */
+ @IntDef(prefix = { "UNINSTALL_REASON_" }, value = {
+ UNINSTALL_REASON_UNKNOWN,
+ UNINSTALL_REASON_USER_TYPE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UninstallReason {}
+
+ /**
+ * Code indicating that the reason for uninstalling this package is unknown.
+ * @hide
+ */
+ public static final int UNINSTALL_REASON_UNKNOWN = 0;
+
+ /**
+ * Code indicating that this package was uninstalled due to the type of user.
+ * See UserSystemPackageInstaller
+ * @hide
+ */
+ public static final int UNINSTALL_REASON_USER_TYPE = 1;
+
/**
* @hide
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 20ddba4..1dadbda 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1837,6 +1837,12 @@
pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
+ final boolean isolatedSplits = sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false);
+ if (isolatedSplits) {
+ pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
+ }
+
pkg.mCompileSdkVersion = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
@@ -1912,10 +1918,6 @@
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
}
- if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
- pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
- }
-
// Resource boolean are -1, so 1 means we don't know the value.
int supportsSmallScreens = 1;
int supportsNormalScreens = 1;
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 30cf4e7..61b1553 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -74,6 +74,7 @@
public int appLinkGeneration;
public int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED;
public int installReason;
+ public @PackageManager.UninstallReason int uninstallReason;
public String harmfulAppWarning;
public ArraySet<String> disabledComponents;
@@ -92,6 +93,7 @@
domainVerificationStatus =
PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
installReason = PackageManager.INSTALL_REASON_UNKNOWN;
+ uninstallReason = PackageManager.UNINSTALL_REASON_UNKNOWN;
}
@VisibleForTesting
@@ -112,6 +114,7 @@
appLinkGeneration = o.appLinkGeneration;
categoryHint = o.categoryHint;
installReason = o.installReason;
+ uninstallReason = o.uninstallReason;
disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
overlayPaths =
@@ -353,6 +356,9 @@
if (installReason != oldState.installReason) {
return false;
}
+ if (uninstallReason != oldState.uninstallReason) {
+ return false;
+ }
if ((disabledComponents == null && oldState.disabledComponents != null)
|| (disabledComponents != null && oldState.disabledComponents == null)) {
return false;
@@ -407,6 +413,7 @@
hashCode = 31 * hashCode + appLinkGeneration;
hashCode = 31 * hashCode + categoryHint;
hashCode = 31 * hashCode + installReason;
+ hashCode = 31 * hashCode + uninstallReason;
hashCode = 31 * hashCode + Objects.hashCode(disabledComponents);
hashCode = 31 * hashCode + Objects.hashCode(enabledComponents);
hashCode = 31 * hashCode + Objects.hashCode(harmfulAppWarning);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 079a470..894ad55 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -433,6 +433,10 @@
R.styleable.AndroidManifest_compileSdkVersion, 0));
setCompileSdkVersionCodename(manifestArray.getNonConfigurationString(
R.styleable.AndroidManifest_compileSdkVersionCodename, 0));
+
+ setIsolatedSplitLoading(manifestArray.getBoolean(
+ R.styleable.AndroidManifest_isolatedSplits, false));
+
}
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index ec77128..e90ccdf 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -386,15 +386,14 @@
return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME);
}
- TypedArray manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest);
+ final TypedArray manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest);
try {
- boolean isCoreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
-
- ParsingPackage pkg = mCallback.startParsingPackage(pkgName, apkPath, codePath,
- manifestArray, isCoreApp);
-
- ParseResult<ParsingPackage> result = parseBaseApkTags(input, pkg, manifestArray,
- res, parser, flags);
+ final boolean isCoreApp =
+ parser.getAttributeBooleanValue(null, "coreApp", false);
+ final ParsingPackage pkg = mCallback.startParsingPackage(
+ pkgName, apkPath, codePath, manifestArray, isCoreApp);
+ final ParseResult<ParsingPackage> result =
+ parseBaseApkTags(input, pkg, manifestArray, res, parser, flags);
if (result.isError()) {
return result;
}
@@ -620,14 +619,12 @@
return sharedUserResult;
}
- pkg.setInstallLocation(anInt(PackageParser.PARSE_DEFAULT_INSTALL_LOCATION,
+ pkg.setInstallLocation(anInteger(PackageParser.PARSE_DEFAULT_INSTALL_LOCATION,
R.styleable.AndroidManifest_installLocation, sa))
- .setTargetSandboxVersion(anInt(PackageParser.PARSE_DEFAULT_TARGET_SANDBOX,
+ .setTargetSandboxVersion(anInteger(PackageParser.PARSE_DEFAULT_TARGET_SANDBOX,
R.styleable.AndroidManifest_targetSandboxVersion, sa))
/* Set the global "on SD card" flag */
- .setExternalStorage((flags & PackageParser.PARSE_EXTERNAL_STORAGE) != 0)
- .setIsolatedSplitLoading(
- bool(false, R.styleable.AndroidManifest_isolatedSplits, sa));
+ .setExternalStorage((flags & PackageParser.PARSE_EXTERNAL_STORAGE) != 0);
boolean foundApp = false;
final int depth = parser.getDepth();
@@ -2658,6 +2655,10 @@
return sa.getInt(attribute, defaultValue);
}
+ private static int anInteger(int defaultValue, @StyleableRes int attribute, TypedArray sa) {
+ return sa.getInteger(attribute, defaultValue);
+ }
+
private static int anInt(@StyleableRes int attribute, TypedArray sa) {
return sa.getInt(attribute, 0);
}
@@ -2688,6 +2689,6 @@
boolean hasFeature(String feature);
ParsingPackage startParsingPackage(String packageName, String baseCodePath, String codePath,
- TypedArray manifestArray, boolean isCoreApp);
+ @NonNull TypedArray manifestArray, boolean isCoreApp);
}
}
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index acdd47a..f40d60d 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -57,8 +57,6 @@
import com.android.internal.util.GrowingArrayUtils;
-import libcore.io.IoUtils;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -818,27 +816,6 @@
}
/**
- * Loads a Drawable from an encoded image stream, or null.
- *
- * This call will handle closing the {@link InputStream}.
- */
- @Nullable
- private Drawable decodeImageDrawable(@NonNull InputStream inputStream,
- @NonNull Resources wrapper, @NonNull TypedValue value) {
- ImageDecoder.Source src = ImageDecoder.createSource(wrapper, inputStream, value.density);
- try {
- return ImageDecoder.decodeDrawable(src, (decoder, info, s) ->
- decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE));
- } catch (IOException ignored) {
- // This is okay. This may be something that ImageDecoder does not
- // support, like SVG.
- return null;
- } finally {
- IoUtils.closeQuietly(inputStream);
- }
- }
-
- /**
* Loads a drawable from XML or resources stream.
*
* @return Drawable, or null if Drawable cannot be decoded.
@@ -902,12 +879,8 @@
} else {
final InputStream is = mAssets.openNonAsset(
value.assetCookie, file, AssetManager.ACCESS_STREAMING);
- if (is instanceof AssetInputStream) {
- AssetInputStream ais = (AssetInputStream) is;
- dr = decodeImageDrawable(ais, wrapper, value);
- } else {
- dr = decodeImageDrawable(is, wrapper, value);
- }
+ final AssetInputStream ais = (AssetInputStream) is;
+ dr = decodeImageDrawable(ais, wrapper, value);
}
} finally {
stack.pop();
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 796cfdc..bcb3934 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -28,6 +28,7 @@
import android.os.Trace;
import android.util.Log;
import android.util.LruCache;
+import android.util.Pair;
import android.util.Printer;
import dalvik.system.BlockGuard;
@@ -230,6 +231,7 @@
setAutoCheckpointInterval();
setLocaleFromConfiguration();
setCustomFunctionsFromConfiguration();
+ executePerConnectionSqlFromConfiguration(0);
}
private void dispose(boolean finalized) {
@@ -468,6 +470,24 @@
}
}
+ private void executePerConnectionSqlFromConfiguration(int startIndex) {
+ for (int i = startIndex; i < mConfiguration.perConnectionSql.size(); i++) {
+ final Pair<String, Object[]> statement = mConfiguration.perConnectionSql.get(i);
+ final int type = DatabaseUtils.getSqlStatementType(statement.first);
+ switch (type) {
+ case DatabaseUtils.STATEMENT_SELECT:
+ executeForString(statement.first, statement.second, null);
+ break;
+ case DatabaseUtils.STATEMENT_PRAGMA:
+ execute(statement.first, statement.second, null);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Unsupported configuration statement: " + statement);
+ }
+ }
+ }
+
private void checkDatabaseWiped() {
if (!SQLiteGlobal.checkDbWipe()) {
return;
@@ -513,6 +533,9 @@
.equals(mConfiguration.customScalarFunctions);
boolean customAggregateFunctionsChanged = !configuration.customAggregateFunctions
.equals(mConfiguration.customAggregateFunctions);
+ final int oldSize = mConfiguration.perConnectionSql.size();
+ final int newSize = configuration.perConnectionSql.size();
+ boolean perConnectionSqlChanged = newSize > oldSize;
// Update configuration parameters.
mConfiguration.updateParametersFrom(configuration);
@@ -532,6 +555,9 @@
if (customScalarFunctionsChanged || customAggregateFunctionsChanged) {
setCustomFunctionsFromConfiguration();
}
+ if (perConnectionSqlChanged) {
+ executePerConnectionSqlFromConfiguration(oldSize);
+ }
}
// Called by SQLiteConnectionPool only.
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 458914e..24ac152 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1047,6 +1047,40 @@
}
/**
+ * Execute the given SQL statement on all connections to this database.
+ * <p>
+ * This statement will be immediately executed on all existing connections,
+ * and will be automatically executed on all future connections.
+ * <p>
+ * Some example usages are changes like {@code PRAGMA trusted_schema=OFF} or
+ * functions like {@code SELECT icu_load_collation()}. If you execute these
+ * statements using {@link #execSQL} then they will only apply to a single
+ * database connection; using this method will ensure that they are
+ * uniformly applied to all current and future connections.
+ *
+ * @param sql The SQL statement to be executed. Multiple statements
+ * separated by semicolons are not supported.
+ * @param bindArgs The arguments that should be bound to the SQL statement.
+ */
+ public void execPerConnectionSQL(@NonNull String sql, @Nullable Object[] bindArgs)
+ throws SQLException {
+ Objects.requireNonNull(sql);
+
+ synchronized (mLock) {
+ throwIfNotOpenLocked();
+
+ final int index = mConfigurationLocked.perConnectionSql.size();
+ mConfigurationLocked.perConnectionSql.add(Pair.create(sql, bindArgs));
+ try {
+ mConnectionPoolLocked.reconfigure(mConfigurationLocked);
+ } catch (RuntimeException ex) {
+ mConfigurationLocked.perConnectionSql.remove(index);
+ throw ex;
+ }
+ }
+ }
+
+ /**
* Gets the database version.
*
* @return the database version
@@ -1788,6 +1822,12 @@
* using "PRAGMA journal_mode'<value>" statement if your app is using
* {@link #enableWriteAheadLogging()}
* </p>
+ * <p>
+ * Note that {@code PRAGMA} values which apply on a per-connection basis
+ * should <em>not</em> be configured using this method; you should instead
+ * use {@link #execPerConnectionSQL} to ensure that they are uniformly
+ * applied to all current and future connections.
+ * </p>
*
* @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
* not supported.
@@ -1834,6 +1874,12 @@
* using "PRAGMA journal_mode'<value>" statement if your app is using
* {@link #enableWriteAheadLogging()}
* </p>
+ * <p>
+ * Note that {@code PRAGMA} values which apply on a per-connection basis
+ * should <em>not</em> be configured using this method; you should instead
+ * use {@link #execPerConnectionSQL} to ensure that they are uniformly
+ * applied to all current and future connections.
+ * </p>
*
* @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
* not supported.
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index b11942a..21c21c9 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -18,9 +18,10 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
+import android.util.Pair;
+import java.util.ArrayList;
import java.util.Locale;
-import java.util.Map;
import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;
import java.util.regex.Pattern;
@@ -102,6 +103,11 @@
= new ArrayMap<>();
/**
+ * The statements to execute to initialize each connection.
+ */
+ public final ArrayList<Pair<String, Object[]>> perConnectionSql = new ArrayList<>();
+
+ /**
* The size in bytes of each lookaside slot
*
* <p>If negative, the default lookaside configuration will be used
@@ -194,6 +200,8 @@
customScalarFunctions.putAll(other.customScalarFunctions);
customAggregateFunctions.clear();
customAggregateFunctions.putAll(other.customAggregateFunctions);
+ perConnectionSql.clear();
+ perConnectionSql.addAll(other.perConnectionSql);
lookasideSlotSize = other.lookasideSlotSize;
lookasideSlotCount = other.lookasideSlotCount;
idleConnectionTimeoutMs = other.idleConnectionTimeoutMs;
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index add67aa..8e3f809 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -204,4 +204,18 @@
* @hide
*/
int BIOMETRIC_ACQUIRED_VENDOR_BASE = 1000;
+
+ //
+ // Internal messages.
+ //
+
+ /**
+ * See {@link BiometricPrompt.Builder#setReceiveSystemEvents(boolean)}. This message is sent
+ * immediately when the user cancels authentication for example by tapping the back button or
+ * tapping the scrim. This is before {@link #BIOMETRIC_ERROR_USER_CANCELED}, which is sent when
+ * dismissal animation completes.
+ * @hide
+ */
+ int BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL = 1;
+
}
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index a3aa258..5af7cef 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -63,6 +63,7 @@
/**
* @hide
*/
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_USE_DEFAULT_TITLE = "use_default_title";
/**
* @hide
@@ -75,14 +76,17 @@
/**
* @hide
*/
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_DEVICE_CREDENTIAL_TITLE = "device_credential_title";
/**
* @hide
*/
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_DEVICE_CREDENTIAL_SUBTITLE = "device_credential_subtitle";
/**
* @hide
*/
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_DEVICE_CREDENTIAL_DESCRIPTION = "device_credential_description";
/**
* @hide
@@ -106,7 +110,15 @@
* If this is set, check the Device Policy Manager for allowed biometrics.
* @hide
*/
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm";
+ /**
+ * Request to receive system events, such as back gesture/button. See
+ * {@link AuthenticationCallback#onSystemEvent(int)}
+ * @hide
+ */
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public static final String KEY_RECEIVE_SYSTEM_EVENTS = "receive_system_events";
/**
* Error/help message will show for this amount of time.
@@ -384,6 +396,18 @@
}
/**
+ * If set, receive internal events via {@link AuthenticationCallback#onSystemEvent(int)}
+ * @param set
+ * @return This builder.
+ * @hide
+ */
+ @NonNull
+ public Builder setReceiveSystemEvents(boolean set) {
+ mBundle.putBoolean(KEY_RECEIVE_SYSTEM_EVENTS, set);
+ return this;
+ }
+
+ /**
* Creates a {@link BiometricPrompt}.
*
* @return An instance of {@link BiometricPrompt}.
@@ -493,6 +517,13 @@
});
}
}
+
+ @Override
+ public void onSystemEvent(int event) throws RemoteException {
+ mExecutor.execute(() -> {
+ mAuthenticationCallback.onSystemEvent(event);
+ });
+ }
};
private BiometricPrompt(Context context, Bundle bundle,
@@ -732,6 +763,12 @@
*/
@Override
public void onAuthenticationAcquired(int acquireInfo) {}
+
+ /**
+ * Receiver for internal system events. See {@link Builder#setReceiveSystemEvents(boolean)}
+ * @hide
+ */
+ public void onSystemEvent(int event) {}
}
/**
diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
index 1d43aa6..b0cddfd 100644
--- a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
@@ -30,4 +30,6 @@
void onAcquired(int acquiredInfo, String message);
// Notifies that the SystemUI dialog has been dismissed.
void onDialogDismissed(int reason);
+ // Notifies the client that an internal event, e.g. back button has occurred.
+ void onSystemEvent(int event);
}
diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
index e7219ca..e57abd5 100644
--- a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
@@ -42,4 +42,6 @@
void onTryAgainPressed();
// Notifies that the user has pressed the "use password" button on SystemUI
void onDeviceCredentialPressed();
+ // Notifies the client that an internal event, e.g. back button has occurred.
+ void onSystemEvent(int event);
}
diff --git a/core/java/android/hardware/soundtrigger/ConversionUtil.java b/core/java/android/hardware/soundtrigger/ConversionUtil.java
index 3d763e6..425218a 100644
--- a/core/java/android/hardware/soundtrigger/ConversionUtil.java
+++ b/core/java/android/hardware/soundtrigger/ConversionUtil.java
@@ -106,11 +106,11 @@
public static SoundModel api2aidlSoundModel(SoundTrigger.SoundModel apiModel) {
SoundModel aidlModel = new SoundModel();
- aidlModel.type = apiModel.type;
- aidlModel.uuid = api2aidlUuid(apiModel.uuid);
- aidlModel.vendorUuid = api2aidlUuid(apiModel.vendorUuid);
- aidlModel.data = byteArrayToSharedMemory(apiModel.data, "SoundTrigger SoundModel");
- aidlModel.dataSize = apiModel.data.length;
+ aidlModel.type = apiModel.getType();
+ aidlModel.uuid = api2aidlUuid(apiModel.getUuid());
+ aidlModel.vendorUuid = api2aidlUuid(apiModel.getVendorUuid());
+ aidlModel.data = byteArrayToSharedMemory(apiModel.getData(), "SoundTrigger SoundModel");
+ aidlModel.dataSize = apiModel.getData().length;
return aidlModel;
}
@@ -122,20 +122,20 @@
SoundTrigger.KeyphraseSoundModel apiModel) {
PhraseSoundModel aidlModel = new PhraseSoundModel();
aidlModel.common = api2aidlSoundModel(apiModel);
- aidlModel.phrases = new Phrase[apiModel.keyphrases.length];
- for (int i = 0; i < apiModel.keyphrases.length; ++i) {
- aidlModel.phrases[i] = api2aidlPhrase(apiModel.keyphrases[i]);
+ aidlModel.phrases = new Phrase[apiModel.getKeyphrases().length];
+ for (int i = 0; i < apiModel.getKeyphrases().length; ++i) {
+ aidlModel.phrases[i] = api2aidlPhrase(apiModel.getKeyphrases()[i]);
}
return aidlModel;
}
public static Phrase api2aidlPhrase(SoundTrigger.Keyphrase apiPhrase) {
Phrase aidlPhrase = new Phrase();
- aidlPhrase.id = apiPhrase.id;
- aidlPhrase.recognitionModes = api2aidlRecognitionModes(apiPhrase.recognitionModes);
- aidlPhrase.users = Arrays.copyOf(apiPhrase.users, apiPhrase.users.length);
- aidlPhrase.locale = apiPhrase.locale.toLanguageTag();
- aidlPhrase.text = apiPhrase.text;
+ aidlPhrase.id = apiPhrase.getId();
+ aidlPhrase.recognitionModes = api2aidlRecognitionModes(apiPhrase.getRecognitionModes());
+ aidlPhrase.users = Arrays.copyOf(apiPhrase.getUsers(), apiPhrase.getUsers().length);
+ aidlPhrase.locale = apiPhrase.getLocale().toLanguageTag();
+ aidlPhrase.text = apiPhrase.getText();
return aidlPhrase;
}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index a74871d2..98c4f61 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -104,76 +104,37 @@
/**
* If set the underlying module supports AEC.
- * Describes bit field {@link ModuleProperties#audioCapabilities}
+ * Describes bit field {@link ModuleProperties#mAudioCapabilities}
*/
public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 0x1;
/**
* If set, the underlying module supports noise suppression.
- * Describes bit field {@link ModuleProperties#audioCapabilities}
+ * Describes bit field {@link ModuleProperties#mAudioCapabilities}
*/
public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 0x2;
- /** Unique module ID provided by the native service */
- public final int id;
-
- /** human readable voice detection engine implementor */
+ private final int mId;
@NonNull
- public final String implementor;
-
- /** human readable voice detection engine description */
+ private final String mImplementor;
@NonNull
- public final String description;
-
- /** Unique voice engine Id (changes with each version) */
+ private final String mDescription;
@NonNull
- public final UUID uuid;
-
- /** Voice detection engine version */
- public final int version;
-
- /**
- * String naming the architecture used for running the supported models.
- * (eg. a platform running models on a DSP could implement this string to convey the DSP
- * architecture used)
- */
+ private final UUID mUuid;
+ private final int mVersion;
@NonNull
- public final String supportedModelArch;
-
- /** Maximum number of active sound models */
- public final int maxSoundModels;
-
- /** Maximum number of key phrases */
- public final int maxKeyphrases;
-
- /** Maximum number of users per key phrase */
- public final int maxUsers;
-
- /** Supported recognition modes (bit field, RECOGNITION_MODE_VOICE_TRIGGER ...) */
+ private final String mSupportedModelArch;
+ private final int mMaxSoundModels;
+ private final int mMaxKeyphrases;
+ private final int mMaxUsers;
@RecognitionModes
- public final int recognitionModes;
-
- /** Supports seamless transition to capture mode after recognition */
- public final boolean supportsCaptureTransition;
-
- /** Maximum buffering capacity in ms if supportsCaptureTransition() is true */
- public final int maxBufferMs;
-
- /** Supports capture by other use cases while detection is active */
- public final boolean supportsConcurrentCapture;
-
- /** Rated power consumption when detection is active with TDB silence/sound/speech ratio */
- public final int powerConsumptionMw;
-
- /** Returns the trigger (key phrase) capture in the binary data of the
- * recognition callback event */
- public final boolean returnsTriggerInEvent;
-
- /**
- * Bit field encoding of the AudioCapabilities
- * supported by the firmware.
- */
+ private final int mRecognitionModes;
+ private final boolean mSupportsCaptureTransition;
+ private final int mMaxBufferMillis;
+ private final boolean mSupportsConcurrentCapture;
+ private final int mPowerConsumptionMw;
+ private final boolean mReturnsTriggerInEvent;
@AudioCapabilities
- public final int audioCapabilities;
+ private final int mAudioCapabilities;
ModuleProperties(int id, @NonNull String implementor, @NonNull String description,
@NonNull String uuid, int version, @NonNull String supportedModelArch,
@@ -181,22 +142,116 @@
@RecognitionModes int recognitionModes, boolean supportsCaptureTransition,
int maxBufferMs, boolean supportsConcurrentCapture, int powerConsumptionMw,
boolean returnsTriggerInEvent, int audioCapabilities) {
- this.id = id;
- this.implementor = requireNonNull(implementor);
- this.description = requireNonNull(description);
- this.uuid = UUID.fromString(requireNonNull(uuid));
- this.version = version;
- this.supportedModelArch = requireNonNull(supportedModelArch);
- this.maxSoundModels = maxSoundModels;
- this.maxKeyphrases = maxKeyphrases;
- this.maxUsers = maxUsers;
- this.recognitionModes = recognitionModes;
- this.supportsCaptureTransition = supportsCaptureTransition;
- this.maxBufferMs = maxBufferMs;
- this.supportsConcurrentCapture = supportsConcurrentCapture;
- this.powerConsumptionMw = powerConsumptionMw;
- this.returnsTriggerInEvent = returnsTriggerInEvent;
- this.audioCapabilities = audioCapabilities;
+ this.mId = id;
+ this.mImplementor = requireNonNull(implementor);
+ this.mDescription = requireNonNull(description);
+ this.mUuid = UUID.fromString(requireNonNull(uuid));
+ this.mVersion = version;
+ this.mSupportedModelArch = requireNonNull(supportedModelArch);
+ this.mMaxSoundModels = maxSoundModels;
+ this.mMaxKeyphrases = maxKeyphrases;
+ this.mMaxUsers = maxUsers;
+ this.mRecognitionModes = recognitionModes;
+ this.mSupportsCaptureTransition = supportsCaptureTransition;
+ this.mMaxBufferMillis = maxBufferMs;
+ this.mSupportsConcurrentCapture = supportsConcurrentCapture;
+ this.mPowerConsumptionMw = powerConsumptionMw;
+ this.mReturnsTriggerInEvent = returnsTriggerInEvent;
+ this.mAudioCapabilities = audioCapabilities;
+ }
+
+ /** Unique module ID provided by the native service */
+ public int getId() {
+ return mId;
+ }
+
+ /** human readable voice detection engine implementor */
+ @NonNull
+ public String getImplementor() {
+ return mImplementor;
+ }
+
+ /** human readable voice detection engine description */
+ @NonNull
+ public String getDescription() {
+ return mDescription;
+ }
+
+ /** Unique voice engine Id (changes with each version) */
+ @NonNull
+ public UUID getUuid() {
+ return mUuid;
+ }
+
+ /** Voice detection engine version */
+ public int getVersion() {
+ return mVersion;
+ }
+
+ /**
+ * String naming the architecture used for running the supported models.
+ * (eg. a platform running models on a DSP could implement this string to convey the DSP
+ * architecture used)
+ */
+ @NonNull
+ public String getSupportedModelArch() {
+ return mSupportedModelArch;
+ }
+
+ /** Maximum number of active sound models */
+ public int getMaxSoundModels() {
+ return mMaxSoundModels;
+ }
+
+ /** Maximum number of key phrases */
+ public int getMaxKeyphrases() {
+ return mMaxKeyphrases;
+ }
+
+ /** Maximum number of users per key phrase */
+ public int getMaxUsers() {
+ return mMaxUsers;
+ }
+
+ /** Supported recognition modes (bit field, RECOGNITION_MODE_VOICE_TRIGGER ...) */
+ @RecognitionModes
+ public int getRecognitionModes() {
+ return mRecognitionModes;
+ }
+
+ /** Supports seamless transition to capture mode after recognition */
+ public boolean isCaptureTransitionSupported() {
+ return mSupportsCaptureTransition;
+ }
+
+ /** Maximum buffering capacity in ms if supportsCaptureTransition() is true */
+ public int getMaxBufferMillis() {
+ return mMaxBufferMillis;
+ }
+
+ /** Supports capture by other use cases while detection is active */
+ public boolean isConcurrentCaptureSupported() {
+ return mSupportsConcurrentCapture;
+ }
+
+ /** Rated power consumption when detection is active with TDB silence/sound/speech ratio */
+ public int getPowerConsumptionMw() {
+ return mPowerConsumptionMw;
+ }
+
+ /** Returns the trigger (key phrase) capture in the binary data of the
+ * recognition callback event */
+ public boolean isTriggerReturnedInEvent() {
+ return mReturnsTriggerInEvent;
+ }
+
+ /**
+ * Bit field encoding of the AudioCapabilities
+ * supported by the firmware.
+ */
+ @AudioCapabilities
+ public int getAudioCapabilities() {
+ return mAudioCapabilities;
}
public static final @android.annotation.NonNull Parcelable.Creator<ModuleProperties> CREATOR
@@ -235,22 +290,22 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(id);
- dest.writeString(implementor);
- dest.writeString(description);
- dest.writeString(uuid.toString());
- dest.writeInt(version);
- dest.writeString(supportedModelArch);
- dest.writeInt(maxSoundModels);
- dest.writeInt(maxKeyphrases);
- dest.writeInt(maxUsers);
- dest.writeInt(recognitionModes);
- dest.writeByte((byte) (supportsCaptureTransition ? 1 : 0));
- dest.writeInt(maxBufferMs);
- dest.writeByte((byte) (supportsConcurrentCapture ? 1 : 0));
- dest.writeInt(powerConsumptionMw);
- dest.writeByte((byte) (returnsTriggerInEvent ? 1 : 0));
- dest.writeInt(audioCapabilities);
+ dest.writeInt(getId());
+ dest.writeString(getImplementor());
+ dest.writeString(getDescription());
+ dest.writeString(getUuid().toString());
+ dest.writeInt(getVersion());
+ dest.writeString(getSupportedModelArch());
+ dest.writeInt(getMaxSoundModels());
+ dest.writeInt(getMaxKeyphrases());
+ dest.writeInt(getMaxUsers());
+ dest.writeInt(getRecognitionModes());
+ dest.writeByte((byte) (isCaptureTransitionSupported() ? 1 : 0));
+ dest.writeInt(getMaxBufferMillis());
+ dest.writeByte((byte) (isConcurrentCaptureSupported() ? 1 : 0));
+ dest.writeInt(getPowerConsumptionMw());
+ dest.writeByte((byte) (isTriggerReturnedInEvent() ? 1 : 0));
+ dest.writeInt(getAudioCapabilities());
}
@Override
@@ -260,16 +315,17 @@
@Override
public String toString() {
- return "ModuleProperties [id=" + id + ", implementor=" + implementor + ", description="
- + description + ", uuid=" + uuid + ", version=" + version
- + " , supportedModelArch=" + supportedModelArch + ", maxSoundModels="
- + maxSoundModels + ", maxKeyphrases=" + maxKeyphrases + ", maxUsers="
- + maxUsers + ", recognitionModes=" + recognitionModes
- + ", supportsCaptureTransition=" + supportsCaptureTransition + ", maxBufferMs="
- + maxBufferMs + ", supportsConcurrentCapture=" + supportsConcurrentCapture
- + ", powerConsumptionMw=" + powerConsumptionMw
- + ", returnsTriggerInEvent=" + returnsTriggerInEvent
- + ", audioCapabilities=" + audioCapabilities + "]";
+ return "ModuleProperties [id=" + getId() + ", implementor=" + getImplementor()
+ + ", description=" + getDescription() + ", uuid=" + getUuid()
+ + ", version=" + getVersion() + " , supportedModelArch="
+ + getSupportedModelArch() + ", maxSoundModels=" + getMaxSoundModels()
+ + ", maxKeyphrases=" + getMaxKeyphrases() + ", maxUsers=" + getMaxUsers()
+ + ", recognitionModes=" + getRecognitionModes() + ", supportsCaptureTransition="
+ + isCaptureTransitionSupported() + ", maxBufferMs=" + getMaxBufferMillis()
+ + ", supportsConcurrentCapture=" + isConcurrentCaptureSupported()
+ + ", powerConsumptionMw=" + getPowerConsumptionMw()
+ + ", returnsTriggerInEvent=" + isTriggerReturnedInEvent()
+ + ", audioCapabilities=" + getAudioCapabilities() + "]";
}
}
@@ -305,44 +361,64 @@
*/
public static final int TYPE_GENERIC_SOUND = 1;
- /** Unique sound model identifier */
@NonNull
- public final UUID uuid;
-
- /** Sound model type (e.g. TYPE_KEYPHRASE); */
+ private final UUID mUuid;
@SoundModelType
- public final int type;
-
- /** Unique sound model vendor identifier */
+ private final int mType;
@NonNull
- public final UUID vendorUuid;
-
- /** vendor specific version number of the model */
- public final int version;
-
- /** Opaque data. For use by vendor implementation and enrollment application */
+ private final UUID mVendorUuid;
+ private final int mVersion;
@NonNull
- public final byte[] data;
+ private final byte[] mData;
/** @hide */
public SoundModel(@NonNull UUID uuid, @Nullable UUID vendorUuid, @SoundModelType int type,
@Nullable byte[] data, int version) {
- this.uuid = requireNonNull(uuid);
- this.vendorUuid = vendorUuid != null ? vendorUuid : new UUID(0, 0);
- this.type = type;
- this.version = version;
- this.data = data != null ? data : new byte[0];
+ this.mUuid = requireNonNull(uuid);
+ this.mVendorUuid = vendorUuid != null ? vendorUuid : new UUID(0, 0);
+ this.mType = type;
+ this.mVersion = version;
+ this.mData = data != null ? data : new byte[0];
+ }
+
+ /** Unique sound model identifier */
+ @NonNull
+ public UUID getUuid() {
+ return mUuid;
+ }
+
+ /** Sound model type (e.g. TYPE_KEYPHRASE); */
+ @SoundModelType
+ public int getType() {
+ return mType;
+ }
+
+ /** Unique sound model vendor identifier */
+ @NonNull
+ public UUID getVendorUuid() {
+ return mVendorUuid;
+ }
+
+ /** vendor specific version number of the model */
+ public int getVersion() {
+ return mVersion;
+ }
+
+ /** Opaque data. For use by vendor implementation and enrollment application */
+ @NonNull
+ public byte[] getData() {
+ return mData;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + version;
- result = prime * result + Arrays.hashCode(data);
- result = prime * result + type;
- result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
- result = prime * result + ((vendorUuid == null) ? 0 : vendorUuid.hashCode());
+ result = prime * result + getVersion();
+ result = prime * result + Arrays.hashCode(getData());
+ result = prime * result + getType();
+ result = prime * result + ((getUuid() == null) ? 0 : getUuid().hashCode());
+ result = prime * result + ((getVendorUuid() == null) ? 0 : getVendorUuid().hashCode());
return result;
}
@@ -358,27 +434,27 @@
return false;
}
SoundModel other = (SoundModel) obj;
- if (type != other.type) {
+ if (getType() != other.getType()) {
return false;
}
- if (uuid == null) {
- if (other.uuid != null) {
+ if (getUuid() == null) {
+ if (other.getUuid() != null) {
return false;
}
- } else if (!uuid.equals(other.uuid)) {
+ } else if (!getUuid().equals(other.getUuid())) {
return false;
}
- if (vendorUuid == null) {
- if (other.vendorUuid != null) {
+ if (getVendorUuid() == null) {
+ if (other.getVendorUuid() != null) {
return false;
}
- } else if (!vendorUuid.equals(other.vendorUuid)) {
+ } else if (!getVendorUuid().equals(other.getVendorUuid())) {
return false;
}
- if (!Arrays.equals(data, other.data)) {
+ if (!Arrays.equals(getData(), other.getData())) {
return false;
}
- if (version != other.version) {
+ if (getVersion() != other.getVersion()) {
return false;
}
return true;
@@ -390,34 +466,16 @@
* {@link KeyphraseSoundModel}
*/
public static final class Keyphrase implements Parcelable {
- /** Unique identifier for this keyphrase */
- public final int id;
- /**
- * Recognition modes supported for this key phrase in the model
- *
- * @see #RECOGNITION_MODE_VOICE_TRIGGER
- * @see #RECOGNITION_MODE_USER_IDENTIFICATION
- * @see #RECOGNITION_MODE_USER_AUTHENTICATION
- * @see #RECOGNITION_MODE_GENERIC
- */
+ private final int mId;
@RecognitionModes
- public final int recognitionModes;
-
- /** Locale of the keyphrase. */
+ private final int mRecognitionModes;
@NonNull
- public final Locale locale;
-
- /** Key phrase text */
+ private final Locale mLocale;
@NonNull
- public final String text;
-
- /**
- * Users this key phrase has been trained for. countains sound trigger specific user IDs
- * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}.
- */
+ private final String mText;
@NonNull
- public final int[] users;
+ private final int[] mUsers;
/**
* Constructor for Keyphrase describes a key phrase that can be detected by a
@@ -432,11 +490,50 @@
*/
public Keyphrase(int id, @RecognitionModes int recognitionModes, @NonNull Locale locale,
@NonNull String text, @Nullable int[] users) {
- this.id = id;
- this.recognitionModes = recognitionModes;
- this.locale = requireNonNull(locale);
- this.text = requireNonNull(text);
- this.users = users != null ? users : new int[0];
+ this.mId = id;
+ this.mRecognitionModes = recognitionModes;
+ this.mLocale = requireNonNull(locale);
+ this.mText = requireNonNull(text);
+ this.mUsers = users != null ? users : new int[0];
+ }
+
+ /** Unique identifier for this keyphrase */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Recognition modes supported for this key phrase in the model
+ *
+ * @see #RECOGNITION_MODE_VOICE_TRIGGER
+ * @see #RECOGNITION_MODE_USER_IDENTIFICATION
+ * @see #RECOGNITION_MODE_USER_AUTHENTICATION
+ * @see #RECOGNITION_MODE_GENERIC
+ */
+ @RecognitionModes
+ public int getRecognitionModes() {
+ return mRecognitionModes;
+ }
+
+ /** Locale of the keyphrase. */
+ @NonNull
+ public Locale getLocale() {
+ return mLocale;
+ }
+
+ /** Key phrase text */
+ @NonNull
+ public String getText() {
+ return mText;
+ }
+
+ /**
+ * Users this key phrase has been trained for. countains sound trigger specific user IDs
+ * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}.
+ */
+ @NonNull
+ public int[] getUsers() {
+ return mUsers;
}
public static final @NonNull Parcelable.Creator<Keyphrase> CREATOR =
@@ -472,13 +569,13 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(id);
- dest.writeInt(recognitionModes);
- dest.writeString(locale.toLanguageTag());
- dest.writeString(text);
- if (users != null) {
- dest.writeInt(users.length);
- dest.writeIntArray(users);
+ dest.writeInt(getId());
+ dest.writeInt(getRecognitionModes());
+ dest.writeString(getLocale().toLanguageTag());
+ dest.writeString(getText());
+ if (getUsers() != null) {
+ dest.writeInt(getUsers().length);
+ dest.writeIntArray(getUsers());
} else {
dest.writeInt(-1);
}
@@ -494,11 +591,11 @@
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((text == null) ? 0 : text.hashCode());
- result = prime * result + id;
- result = prime * result + ((locale == null) ? 0 : locale.hashCode());
- result = prime * result + recognitionModes;
- result = prime * result + Arrays.hashCode(users);
+ result = prime * result + ((getText() == null) ? 0 : getText().hashCode());
+ result = prime * result + getId();
+ result = prime * result + ((getLocale() == null) ? 0 : getLocale().hashCode());
+ result = prime * result + getRecognitionModes();
+ result = prime * result + Arrays.hashCode(getUsers());
return result;
}
@@ -514,27 +611,27 @@
return false;
}
Keyphrase other = (Keyphrase) obj;
- if (text == null) {
- if (other.text != null) {
+ if (getText() == null) {
+ if (other.getText() != null) {
return false;
}
- } else if (!text.equals(other.text)) {
+ } else if (!getText().equals(other.getText())) {
return false;
}
- if (id != other.id) {
+ if (getId() != other.getId()) {
return false;
}
- if (locale == null) {
- if (other.locale != null) {
+ if (getLocale() == null) {
+ if (other.getLocale() != null) {
return false;
}
- } else if (!locale.equals(other.locale)) {
+ } else if (!getLocale().equals(other.getLocale())) {
return false;
}
- if (recognitionModes != other.recognitionModes) {
+ if (getRecognitionModes() != other.getRecognitionModes()) {
return false;
}
- if (!Arrays.equals(users, other.users)) {
+ if (!Arrays.equals(getUsers(), other.getUsers())) {
return false;
}
return true;
@@ -542,9 +639,9 @@
@Override
public String toString() {
- return "Keyphrase [id=" + id + ", recognitionModes=" + recognitionModes
- + ", locale=" + locale.toLanguageTag() + ", text=" + text
- + ", users=" + Arrays.toString(users) + "]";
+ return "Keyphrase [id=" + getId() + ", recognitionModes=" + getRecognitionModes()
+ + ", locale=" + getLocale().toLanguageTag() + ", text=" + getText()
+ + ", users=" + Arrays.toString(getUsers()) + "]";
}
}
@@ -554,15 +651,15 @@
* and the list of corresponding {@link Keyphrase} descriptors.
*/
public static final class KeyphraseSoundModel extends SoundModel implements Parcelable {
- /** Key phrases in this sound model */
+
@NonNull
- public final Keyphrase[] keyphrases; // keyword phrases in model
+ private final Keyphrase[] mKeyphrases;
public KeyphraseSoundModel(
@NonNull UUID uuid, @NonNull UUID vendorUuid, @Nullable byte[] data,
@Nullable Keyphrase[] keyphrases, int version) {
super(uuid, vendorUuid, TYPE_KEYPHRASE, data, version);
- this.keyphrases = keyphrases != null ? keyphrases : new Keyphrase[0];
+ this.mKeyphrases = keyphrases != null ? keyphrases : new Keyphrase[0];
}
public KeyphraseSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
@@ -570,6 +667,12 @@
this(uuid, vendorUuid, data, keyphrases, -1);
}
+ /** Key phrases in this sound model */
+ @NonNull
+ public Keyphrase[] getKeyphrases() {
+ return mKeyphrases;
+ }
+
public static final @NonNull Parcelable.Creator<KeyphraseSoundModel> CREATOR =
new Parcelable.Creator<KeyphraseSoundModel>() {
@NonNull
@@ -608,32 +711,32 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(uuid.toString());
- if (vendorUuid == null) {
+ dest.writeString(getUuid().toString());
+ if (getVendorUuid() == null) {
dest.writeInt(-1);
} else {
- dest.writeInt(vendorUuid.toString().length());
- dest.writeString(vendorUuid.toString());
+ dest.writeInt(getVendorUuid().toString().length());
+ dest.writeString(getVendorUuid().toString());
}
- dest.writeInt(version);
- dest.writeBlob(data);
- dest.writeTypedArray(keyphrases, flags);
+ dest.writeInt(getVersion());
+ dest.writeBlob(getData());
+ dest.writeTypedArray(getKeyphrases(), flags);
}
@Override
public String toString() {
- return "KeyphraseSoundModel [keyphrases=" + Arrays.toString(keyphrases)
- + ", uuid=" + uuid + ", vendorUuid=" + vendorUuid
- + ", type=" + type
- + ", data=" + (data == null ? 0 : data.length)
- + ", version=" + version + "]";
+ return "KeyphraseSoundModel [keyphrases=" + Arrays.toString(getKeyphrases())
+ + ", uuid=" + getUuid() + ", vendorUuid=" + getVendorUuid()
+ + ", type=" + getType()
+ + ", data=" + (getData() == null ? 0 : getData().length)
+ + ", version=" + getVersion() + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
- result = prime * result + Arrays.hashCode(keyphrases);
+ result = prime * result + Arrays.hashCode(getKeyphrases());
return result;
}
@@ -649,7 +752,7 @@
return false;
}
KeyphraseSoundModel other = (KeyphraseSoundModel) obj;
- if (!Arrays.equals(keyphrases, other.keyphrases)) {
+ if (!Arrays.equals(getKeyphrases(), other.getKeyphrases())) {
return false;
}
return true;
@@ -706,23 +809,23 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(uuid.toString());
- if (vendorUuid == null) {
+ dest.writeString(getUuid().toString());
+ if (getVendorUuid() == null) {
dest.writeInt(-1);
} else {
- dest.writeInt(vendorUuid.toString().length());
- dest.writeString(vendorUuid.toString());
+ dest.writeInt(getVendorUuid().toString().length());
+ dest.writeString(getVendorUuid().toString());
}
- dest.writeBlob(data);
- dest.writeInt(version);
+ dest.writeBlob(getData());
+ dest.writeInt(getVersion());
}
@Override
public String toString() {
- return "GenericSoundModel [uuid=" + uuid + ", vendorUuid=" + vendorUuid
- + ", type=" + type
- + ", data=" + (data == null ? 0 : data.length)
- + ", version=" + version + "]";
+ return "GenericSoundModel [uuid=" + getUuid() + ", vendorUuid=" + getVendorUuid()
+ + ", type=" + getType()
+ + ", data=" + (getData() == null ? 0 : getData().length)
+ + ", version=" + getVersion() + "]";
}
}
@@ -1825,7 +1928,7 @@
/**
* Get an interface on a hardware module to control sound models and recognition on
* this module.
- * @param moduleId Sound module system identifier {@link ModuleProperties#id}. mandatory.
+ * @param moduleId Sound module system identifier {@link ModuleProperties#mId}. mandatory.
* @param listener {@link StatusListener} interface. Mandatory.
* @param handler the Handler that will receive the callabcks. Can be null if default handler
* is OK.
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 8119df9..fe90a84 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -36,6 +36,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -47,7 +48,7 @@
* An agent manages the life cycle of a network. A network starts its
* life cycle when {@link register} is called on NetworkAgent. The network
* is then connecting. When full L3 connectivity has been established,
- * the agent shoud call {@link setConnected} to inform the system that
+ * the agent shoud call {@link markConnected} to inform the system that
* this network is ready to use. When the network disconnects its life
* ends and the agent should call {@link unregister}, at which point the
* system will clean up and free resources.
@@ -503,7 +504,8 @@
break;
}
case CMD_START_SOCKET_KEEPALIVE: {
- onStartSocketKeepalive(msg.arg1 /* slot */, msg.arg2 /* interval */,
+ onStartSocketKeepalive(msg.arg1 /* slot */,
+ Duration.ofSeconds(msg.arg2) /* interval */,
(KeepalivePacketData) msg.obj /* packet */);
break;
}
@@ -617,10 +619,10 @@
* Inform ConnectivityService that this agent has now connected.
* Call {@link #unregister} to disconnect.
*/
- public void setConnected() {
+ public void markConnected() {
if (mIsLegacy) {
throw new UnsupportedOperationException(
- "Legacy agents can't call setConnected.");
+ "Legacy agents can't call markConnected.");
}
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
@@ -798,8 +800,8 @@
* {@code VALIDATION_STATUS_VALID} if Internet connectivity was validated,
* {@code VALIDATION_STATUS_NOT_VALID} if Internet connectivity was not validated.
*
- * This may be called multiple times as network status changes, or if there are multiple
- * subsequent attempts to validate connectivity that fail.
+ * This is guaranteed to be called again when the network status changes, but the system
+ * may also call this multiple times even if the status does not change.
*
* @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}.
* @param redirectUri If Internet connectivity is being redirected (e.g., on a captive portal),
@@ -832,18 +834,25 @@
* Requests that the network hardware send the specified packet at the specified interval.
*
* @param slot the hardware slot on which to start the keepalive.
- * @param intervalSeconds the interval between packets
+ * @param interval the interval between packets, between 10 and 3600. Note that this API
+ * does not support sub-second precision and will round off the request.
* @param packet the packet to send.
*/
// seconds is from SocketKeepalive.MIN_INTERVAL_SEC to MAX_INTERVAL_SEC, but these should
// not be exposed as constants because they may change in the future (API guideline 4.8)
// and should have getters if exposed at all. Getters can't be used in the annotation,
// so the values unfortunately need to be copied.
- public void onStartSocketKeepalive(int slot,
- @IntRange(from = 10, to = 3600) int intervalSeconds,
+ public void onStartSocketKeepalive(int slot, @NonNull Duration interval,
@NonNull KeepalivePacketData packet) {
- Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, intervalSeconds,
- packet);
+ final long intervalSeconds = interval.getSeconds();
+ if (intervalSeconds < SocketKeepalive.MIN_INTERVAL_SEC
+ || intervalSeconds > SocketKeepalive.MAX_INTERVAL_SEC) {
+ throw new IllegalArgumentException("Interval needs to be comprised between "
+ + SocketKeepalive.MIN_INTERVAL_SEC + " and " + SocketKeepalive.MAX_INTERVAL_SEC
+ + " but was " + intervalSeconds);
+ }
+ final Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot,
+ (int) intervalSeconds, packet);
startSocketKeepalive(msg);
msg.recycle();
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index af9414c..91ef911 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -1122,7 +1122,7 @@
}
private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
- return mNetworkSpecifier == null || mNetworkSpecifier.satisfiedBy(nc.mNetworkSpecifier)
+ return mNetworkSpecifier == null || mNetworkSpecifier.canBeSatisfiedBy(nc.mNetworkSpecifier)
|| nc.mNetworkSpecifier instanceof MatchAllNetworkSpecifier;
}
diff --git a/core/java/android/net/NetworkProvider.java b/core/java/android/net/NetworkProvider.java
index 418d691..75086cf 100644
--- a/core/java/android/net/NetworkProvider.java
+++ b/core/java/android/net/NetworkProvider.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -33,8 +34,8 @@
* {@link NetworkAgent}s. The networks can then provide connectivity to apps and can be interacted
* with via networking APIs such as {@link ConnectivityManager}.
*
- * Subclasses should implement {@link #onNetworkRequested} and {@link #onRequestWithdrawn} to
- * receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the
+ * Subclasses should implement {@link #onNetworkRequested} and {@link #onNetworkRequestWithdrawn}
+ * to receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the
* best (highest-scoring) network for any request is generally not used by the system, and torn
* down.
*
@@ -77,7 +78,7 @@
* Constructs a new NetworkProvider.
*
* @param looper the Looper on which to run {@link #onNetworkRequested} and
- * {@link #onRequestWithdrawn}.
+ * {@link #onNetworkRequestWithdrawn}.
* @param name the name of the listener, used only for debugging.
*
* @hide
@@ -94,7 +95,7 @@
onNetworkRequested((NetworkRequest) m.obj, m.arg1, m.arg2);
break;
case CMD_CANCEL_REQUEST:
- onRequestWithdrawn((NetworkRequest) m.obj);
+ onNetworkRequestWithdrawn((NetworkRequest) m.obj);
break;
default:
Log.e(mName, "Unhandled message: " + m.what);
@@ -142,14 +143,15 @@
* @hide
*/
@SystemApi
- public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {}
+ public void onNetworkRequested(@NonNull NetworkRequest request,
+ @IntRange(from = 0, to = 99) int score, int providerId) {}
/**
* Called when a NetworkRequest is withdrawn.
* @hide
*/
@SystemApi
- public void onRequestWithdrawn(@NonNull NetworkRequest request) {}
+ public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {}
/**
* Asserts that no provider will ever be able to satisfy the specified request. The provider
@@ -157,7 +159,7 @@
* satisfying this request, and that the request cannot be satisfied. The application filing the
* request will receive an {@link NetworkCallback#onUnavailable()} callback.
*
- * @param request the request that cannot be fulfilled
+ * @param request the request that permanently cannot be fulfilled
* @hide
*/
@SystemApi
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 798856d..a6bd74a 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -474,7 +474,7 @@
* @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not
* satisfy any request.
*/
- public boolean satisfiedBy(@Nullable NetworkCapabilities nc) {
+ public boolean canBeSatisfiedBy(@Nullable NetworkCapabilities nc) {
return networkCapabilities.satisfiedByNetworkCapabilities(nc);
}
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index 2dd0c4e..160259e 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -35,7 +35,9 @@
* @hide
*/
@SystemApi
- public abstract boolean satisfiedBy(@Nullable NetworkSpecifier other);
+ public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) {
+ return false;
+ }
/**
* Optional method which can be overridden by concrete implementations of NetworkSpecifier to
diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java
index 8ff8f4c..46aef10 100644
--- a/core/java/android/net/SocketKeepalive.java
+++ b/core/java/android/net/SocketKeepalive.java
@@ -115,7 +115,8 @@
SUCCESS,
ERROR_INVALID_LENGTH,
ERROR_UNSUPPORTED,
- ERROR_INSUFFICIENT_RESOURCES
+ ERROR_INSUFFICIENT_RESOURCES,
+ ERROR_HARDWARE_UNSUPPORTED
})
public @interface KeepaliveEvent {}
diff --git a/core/java/android/net/StringNetworkSpecifier.java b/core/java/android/net/StringNetworkSpecifier.java
index 6ae5971..3f2aa17 100644
--- a/core/java/android/net/StringNetworkSpecifier.java
+++ b/core/java/android/net/StringNetworkSpecifier.java
@@ -40,7 +40,7 @@
/** @hide */
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
return equals(other);
}
diff --git a/core/java/android/net/TelephonyNetworkSpecifier.java b/core/java/android/net/TelephonyNetworkSpecifier.java
index 726f770..aafebd7 100644
--- a/core/java/android/net/TelephonyNetworkSpecifier.java
+++ b/core/java/android/net/TelephonyNetworkSpecifier.java
@@ -97,7 +97,7 @@
/** @hide */
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
// Any generic requests should be satisfied by a specific telephony network.
// For simplicity, we treat null same as MatchAllNetworkSpecifier
return equals(other) || other == null || other instanceof MatchAllNetworkSpecifier;
diff --git a/core/java/android/os/BasicShellCommandHandler.java b/core/java/android/os/BasicShellCommandHandler.java
index 5bd5d61..52273cb 100644
--- a/core/java/android/os/BasicShellCommandHandler.java
+++ b/core/java/android/os/BasicShellCommandHandler.java
@@ -264,6 +264,16 @@
}
/**
+ * Returns number of arguments that haven't been processed yet.
+ */
+ public int getRemainingArgsCount() {
+ if (mArgPos >= mArgs.length) {
+ return 0;
+ }
+ return mArgs.length - mArgPos;
+ }
+
+ /**
* Return the next argument on the command line, whatever it is; if there are
* no arguments left, throws an IllegalArgumentException to report this to the user.
*/
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 5d2c9d1..b7b3c4f 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -607,9 +607,6 @@
* started.
* @param pkgDataInfoMap Map from related package names to private data directory
* volume UUID and inode number.
- * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
- * volume UUID and inode number.
- * @param bindMountAppsData whether zygote needs to mount CE and DE data.
* @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
* @param zygoteArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
@@ -634,17 +631,13 @@
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
- @Nullable Map<String, Pair<String, Long>>
- whitelistedDataInfoMap,
- boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
zygotePolicyFlags, isTopApp, disabledCompatChanges,
- pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
- bindMountAppStorageDirs, zygoteArgs);
+ pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs);
}
/** @hide */
@@ -668,8 +661,7 @@
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false,
- disabledCompatChanges, /* pkgDataInfoMap */ null,
- /* whitelistedDataInfoMap */ null, false, false, zygoteArgs);
+ disabledCompatChanges, /* pkgDataInfoMap */ null, false, zygoteArgs);
}
/**
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index a4c99c0..5f3f14f 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -333,9 +333,6 @@
* started.
* @param pkgDataInfoMap Map from related package names to private data directory
* volume UUID and inode number.
- * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
- * volume UUID and inode number.
- * @param bindMountAppsData whether zygote needs to mount CE and DE data.
* @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
*
* @param zygoteArgs Additional arguments to supply to the Zygote process.
@@ -358,9 +355,6 @@
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
- @Nullable Map<String, Pair<String, Long>>
- whitelistedDataInfoMap,
- boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
// TODO (chriswailes): Is there a better place to check this value?
@@ -373,8 +367,7 @@
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
- pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
- bindMountAppStorageDirs, zygoteArgs);
+ pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -615,9 +608,6 @@
* @param disabledCompatChanges a list of disabled compat changes for the process being started.
* @param pkgDataInfoMap Map from related package names to private data directory volume UUID
* and inode number.
- * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
- * volume UUID and inode number.
- * @param bindMountAppsData whether zygote needs to mount CE and DE data.
* @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
* @param extraArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
@@ -641,9 +631,6 @@
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
- @Nullable Map<String, Pair<String, Long>>
- whitelistedDataInfoMap,
- boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
@@ -741,33 +728,11 @@
}
argsForZygote.add(sb.toString());
}
- if (whitelistedDataInfoMap != null && whitelistedDataInfoMap.size() > 0) {
- StringBuilder sb = new StringBuilder();
- sb.append(Zygote.WHITELISTED_DATA_INFO_MAP);
- sb.append("=");
- boolean started = false;
- for (Map.Entry<String, Pair<String, Long>> entry : whitelistedDataInfoMap.entrySet()) {
- if (started) {
- sb.append(',');
- }
- started = true;
- sb.append(entry.getKey());
- sb.append(',');
- sb.append(entry.getValue().first);
- sb.append(',');
- sb.append(entry.getValue().second);
- }
- argsForZygote.add(sb.toString());
- }
if (bindMountAppStorageDirs) {
argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS);
}
- if (bindMountAppsData) {
- argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS);
- }
-
if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--disabled-compat-changes=");
@@ -1326,7 +1291,6 @@
true /* startChildZygote */, null /* packageName */,
ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */,
null /* disabledCompatChanges */, null /* pkgDataInfoMap */,
- null /* whitelistedDataInfoMap */, false /* bindMountAppsData*/,
/* bindMountAppStorageDirs */ false, extraArgs);
} catch (ZygoteStartFailedEx ex) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d2a03f0..78bc079 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8571,6 +8571,16 @@
public static final String QS_TILES = "sysui_qs_tiles";
/**
+ * Whether this user has enabled Quick controls.
+ *
+ * 0 indicates disabled and 1 indicates enabled. A non existent value should be treated as
+ * enabled.
+ *
+ * @hide
+ */
+ public static final String CONTROLS_ENABLED = "controls_enabled";
+
+ /**
* Specifies whether the web action API is enabled.
*
* @hide
@@ -9639,14 +9649,6 @@
"location_ignore_settings_package_whitelist";
/**
- * Maximum staleness allowed for last location when returned to clients with only foreground
- * location permissions.
- * @hide
- */
- public static final String LOCATION_LAST_LOCATION_MAX_AGE_MILLIS =
- "location_last_location_max_age_millis";
-
- /**
* Whether TV will switch to MHL port when a mobile device is plugged in.
* (0 = false, 1 = true)
* @hide
@@ -13058,6 +13060,18 @@
"chained_battery_attribution_enabled";
/**
+ * Toggle to enable/disable the incremental ADB installation by default.
+ * If not set, default adb installations are incremental; set to zero to use full ones.
+ * Note: only ADB uses it, no usages in the Framework code.
+ * <p>
+ * Type: int (0 to disable, 1 to enable)
+ *
+ * @hide
+ */
+ public static final String ENABLE_ADB_INCREMENTAL_INSTALL_DEFAULT =
+ "enable_adb_incremental_install_default";
+
+ /**
* The packages whitelisted to be run in autofill compatibility mode. The list
* of packages is {@code ":"} colon delimited, and each entry has the name of the
* package and an optional list of url bar resource ids (the list is delimited by
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 1eb53aa..b34268d 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1332,7 +1332,6 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public static final String ACTION_SMS_MMS_DB_LOST =
"android.provider.action.SMS_MMS_DB_LOST";
diff --git a/core/java/android/security/FileIntegrityManager.java b/core/java/android/security/FileIntegrityManager.java
index cdd6584..266046e 100644
--- a/core/java/android/security/FileIntegrityManager.java
+++ b/core/java/android/security/FileIntegrityManager.java
@@ -31,9 +31,11 @@
@SystemService(Context.FILE_INTEGRITY_SERVICE)
public final class FileIntegrityManager {
@NonNull private final IFileIntegrityService mService;
+ @NonNull private final Context mContext;
/** @hide */
- public FileIntegrityManager(@NonNull IFileIntegrityService service) {
+ public FileIntegrityManager(@NonNull Context context, @NonNull IFileIntegrityService service) {
+ mContext = context;
mService = service;
}
@@ -69,7 +71,8 @@
public boolean isAppSourceCertificateTrusted(@NonNull X509Certificate certificate)
throws CertificateEncodingException {
try {
- return mService.isAppSourceCertificateTrusted(certificate.getEncoded());
+ return mService.isAppSourceCertificateTrusted(
+ certificate.getEncoded(), mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/security/IFileIntegrityService.aidl b/core/java/android/security/IFileIntegrityService.aidl
index ebb8bcb..dff347e 100644
--- a/core/java/android/security/IFileIntegrityService.aidl
+++ b/core/java/android/security/IFileIntegrityService.aidl
@@ -22,5 +22,5 @@
*/
interface IFileIntegrityService {
boolean isApkVeritySupported();
- boolean isAppSourceCertificateTrusted(in byte[] certificateBytes);
+ boolean isAppSourceCertificateTrusted(in byte[] certificateBytes, in String packageName);
}
diff --git a/core/java/android/service/autofill/InlinePresentation.java b/core/java/android/service/autofill/InlinePresentation.java
index b6a8ced..cb03d21 100644
--- a/core/java/android/service/autofill/InlinePresentation.java
+++ b/core/java/android/service/autofill/InlinePresentation.java
@@ -21,7 +21,7 @@
import android.app.slice.Slice;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.inline.InlinePresentationSpec;
+import android.widget.inline.InlinePresentationSpec;
import com.android.internal.util.DataClass;
@@ -233,7 +233,7 @@
time = 1582753782651L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/service/autofill/InlinePresentation.java",
- inputSignatures = "private final @android.annotation.NonNull android.app.slice.Slice mSlice\nprivate final @android.annotation.NonNull android.view.inline.InlinePresentationSpec mInlinePresentationSpec\nprivate final boolean mPinned\npublic @android.annotation.NonNull @android.annotation.Size(min=0L) java.lang.String[] getAutofillHints()\nclass InlinePresentation extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)")
+ inputSignatures = "private final @android.annotation.NonNull android.app.slice.Slice mSlice\nprivate final @android.annotation.NonNull android.widget.inline.InlinePresentationSpec mInlinePresentationSpec\nprivate final boolean mPinned\npublic @android.annotation.NonNull @android.annotation.Size(min=0L) java.lang.String[] getAutofillHints()\nclass InlinePresentation extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index cecfe24..ef55f06 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -18,7 +18,7 @@
import static android.view.contentcapture.ContentCaptureHelper.sDebug;
import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
import static android.view.contentcapture.ContentCaptureHelper.toList;
-import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
@@ -60,7 +60,9 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -119,6 +121,9 @@
*/
public static final String SERVICE_META_DATA = "android.content_capture";
+ private final LocalDataShareAdapterResourceManager mDataShareAdapterResourceManager =
+ new LocalDataShareAdapterResourceManager();
+
private Handler mHandler;
private IContentCaptureServiceCallback mCallback;
@@ -546,7 +551,8 @@
Preconditions.checkNotNull(executor);
DataShareReadAdapterDelegate delegate =
- new DataShareReadAdapterDelegate(executor, adapter);
+ new DataShareReadAdapterDelegate(executor, adapter,
+ mDataShareAdapterResourceManager);
try {
callback.accept(delegate);
@@ -653,16 +659,17 @@
private static class DataShareReadAdapterDelegate extends IDataShareReadAdapter.Stub {
+ private final WeakReference<LocalDataShareAdapterResourceManager> mResourceManagerReference;
private final Object mLock = new Object();
- private final WeakReference<DataShareReadAdapter> mAdapterReference;
- private final WeakReference<Executor> mExecutorReference;
- DataShareReadAdapterDelegate(Executor executor, DataShareReadAdapter adapter) {
+ DataShareReadAdapterDelegate(Executor executor, DataShareReadAdapter adapter,
+ LocalDataShareAdapterResourceManager resourceManager) {
Preconditions.checkNotNull(executor);
Preconditions.checkNotNull(adapter);
+ Preconditions.checkNotNull(resourceManager);
- mExecutorReference = new WeakReference<>(executor);
- mAdapterReference = new WeakReference<>(adapter);
+ resourceManager.initializeForDelegate(this, adapter, executor);
+ mResourceManagerReference = new WeakReference<>(resourceManager);
}
@Override
@@ -670,6 +677,10 @@
throws RemoteException {
synchronized (mLock) {
executeAdapterMethodLocked(adapter -> adapter.onStart(fd), "onStart");
+
+ // Client app and Service successfully connected, so this object would be kept alive
+ // until the session has finished.
+ clearHardReferences();
}
}
@@ -678,16 +689,23 @@
synchronized (mLock) {
executeAdapterMethodLocked(
adapter -> adapter.onError(errorCode), "onError");
+ clearHardReferences();
}
}
private void executeAdapterMethodLocked(Consumer<DataShareReadAdapter> adapterFn,
String methodName) {
- DataShareReadAdapter adapter = mAdapterReference.get();
- Executor executor = mExecutorReference.get();
+ LocalDataShareAdapterResourceManager resourceManager = mResourceManagerReference.get();
+ if (resourceManager == null) {
+ Slog.w(TAG, "Can't execute " + methodName + "(), resource manager has been GC'ed");
+ return;
+ }
+
+ DataShareReadAdapter adapter = resourceManager.getAdapter(this);
+ Executor executor = resourceManager.getExecutor(this);
if (adapter == null || executor == null) {
- Slog.w(TAG, "Can't execute " + methodName + "(), references have been GC'ed");
+ Slog.w(TAG, "Can't execute " + methodName + "(), references are null");
return;
}
@@ -698,5 +716,51 @@
Binder.restoreCallingIdentity(identity);
}
}
+
+ private void clearHardReferences() {
+ LocalDataShareAdapterResourceManager resourceManager = mResourceManagerReference.get();
+ if (resourceManager == null) {
+ Slog.w(TAG, "Can't clear references, resource manager has been GC'ed");
+ return;
+ }
+
+ resourceManager.clearHardReferences(this);
+ }
+ }
+
+ /**
+ * Wrapper class making sure dependencies on the current application stay in the application
+ * context.
+ */
+ private static class LocalDataShareAdapterResourceManager {
+
+ // Keeping hard references to the remote objects in the current process (static context)
+ // to prevent them to be gc'ed during the lifetime of the application. This is an
+ // artifact of only operating with weak references remotely: there has to be at least 1
+ // hard reference in order for this to not be killed.
+ private Map<DataShareReadAdapterDelegate, DataShareReadAdapter>
+ mDataShareReadAdapterHardReferences = new HashMap<>();
+ private Map<DataShareReadAdapterDelegate, Executor> mExecutorHardReferences =
+ new HashMap<>();
+
+
+ void initializeForDelegate(DataShareReadAdapterDelegate delegate,
+ DataShareReadAdapter adapter, Executor executor) {
+ mDataShareReadAdapterHardReferences.put(delegate, adapter);
+ mExecutorHardReferences.remove(delegate, executor);
+ }
+
+ Executor getExecutor(DataShareReadAdapterDelegate delegate) {
+ return mExecutorHardReferences.get(delegate);
+ }
+
+ DataShareReadAdapter getAdapter(DataShareReadAdapterDelegate delegate) {
+ return mDataShareReadAdapterHardReferences.get(delegate);
+ }
+
+ void clearHardReferences(DataShareReadAdapterDelegate delegate) {
+ mDataShareReadAdapterHardReferences.remove(delegate);
+ mExecutorHardReferences.remove(delegate);
+ }
}
}
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index 9accf5b..4262c40 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -304,12 +304,11 @@
Preconditions.checkNotNull(context);
Preconditions.checkNotNull(componentName);
Preconditions.checkNotNull(control);
- final ComponentName sysuiComponent = ComponentName.unflattenFromString(
- context.getResources().getString(
- com.android.internal.R.string.config_systemUIServiceComponent));
+ final String controlsPackage = context.getString(
+ com.android.internal.R.string.config_controlsPackage);
Intent intent = new Intent(ACTION_ADD_CONTROL);
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, componentName);
- intent.setPackage(sysuiComponent.getPackageName());
+ intent.setPackage(controlsPackage);
if (isStatelessControl(control)) {
intent.putExtra(EXTRA_CONTROL, control);
} else {
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index e70311f..c9be1c1 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -15,8 +15,6 @@
*/
package android.service.dreams;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
-
import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.NonNull;
@@ -1071,7 +1069,6 @@
private void onWindowCreated(Window w) {
mWindow = w;
mWindow.setCallback(this);
- mWindow.setType(TYPE_DREAM);
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
WindowManager.LayoutParams lp = mWindow.getAttributes();
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index f8265d6..97cd760 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -487,7 +487,7 @@
ModuleProperties properties =
mModelManagementService.getDspModuleProperties();
if (properties != null) {
- return properties.audioCapabilities;
+ return properties.getAudioCapabilities();
}
return 0;
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index f6d56ee..c36a33f 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -21,6 +21,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.compat.annotation.ChangeId;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Build;
@@ -65,6 +66,43 @@
private static final boolean DBG = false; // STOPSHIP if true
/**
+ * Experiment flag to set the per-pid registration limit for PhoneStateListeners
+ *
+ * Limit on registrations of {@link PhoneStateListener}s on a per-pid
+ * basis. When this limit is exceeded, any calls to {@link TelephonyManager#listen} will fail
+ * with an {@link IllegalStateException}.
+ *
+ * {@link android.os.Process#PHONE_UID}, {@link android.os.Process#SYSTEM_UID}, and the uid that
+ * TelephonyRegistry runs under are exempt from this limit.
+ *
+ * If the value of the flag is less than 1, enforcement of the limit will be disabled.
+ * @hide
+ */
+ public static final String FLAG_PER_PID_REGISTRATION_LIMIT =
+ "phone_state_listener_per_pid_registration_limit";
+
+ /**
+ * Default value for the per-pid registation limit.
+ * See {@link #FLAG_PER_PID_REGISTRATION_LIMIT}.
+ * @hide
+ */
+ public static final int DEFAULT_PER_PID_REGISTRATION_LIMIT = 50;
+
+ /**
+ * This change enables a limit on the number of {@link PhoneStateListener} objects any process
+ * may register via {@link TelephonyManager#listen}. The default limit is 50, which may change
+ * via remote device config updates.
+ *
+ * This limit is enforced via an {@link IllegalStateException} thrown from
+ * {@link TelephonyManager#listen} when the offending process attempts to register one too many
+ * listeners.
+ *
+ * @hide
+ */
+ @ChangeId
+ public static final long PHONE_STATE_LISTENER_LIMIT_CHANGE_ID = 150880553L;
+
+ /**
* Stop listening for updates.
*
* The PhoneStateListener is not tied to any subscription and unregistered for any update.
diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl
index 596d55a..071c259 100644
--- a/core/java/android/view/IPinnedStackListener.aidl
+++ b/core/java/android/view/IPinnedStackListener.aidl
@@ -60,20 +60,12 @@
void onActionsChanged(in ParceledListSlice actions);
/**
- * Called by the window manager to notify the listener to save the reentry fraction and size,
- * typically when an Activity leaves PiP (picture-in-picture) mode to fullscreen.
- * {@param componentName} represents the application component of PiP window
- * while {@param bounds} is the current PiP bounds used to calculate the
- * reentry snap fraction and size.
- */
- void onSaveReentryBounds(in ComponentName componentName, in Rect bounds);
-
- /**
- * Called by the window manager to notify the listener to reset saved reentry fraction and size,
- * typically when an Activity enters PiP (picture-in-picture) mode from fullscreen.
+ * Called by the window manager to notify the listener that Activity (was or is in pinned mode)
+ * is hidden (either stopped or removed). This is generally used as a signal to reset saved
+ * reentry fraction and size.
* {@param componentName} represents the application component of PiP window.
*/
- void onResetReentryBounds(in ComponentName componentName);
+ void onActivityHidden(in ComponentName componentName);
/**
* Called when the window manager has detected change on DisplayInfo, or
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index e6bd843..ae115f6 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.toInternalType;
import static android.view.InsetsState.toPublicType;
@@ -367,6 +368,7 @@
private int mLastLegacySystemUiFlags;
private DisplayCutout mLastDisplayCutout;
private boolean mStartingAnimation;
+ private int mCaptionInsetsHeight = 0;
private SyncRtSurfaceTransactionApplier mApplier;
@@ -454,13 +456,19 @@
return mState;
}
+ @Override
+ public boolean isRequestedVisible(int type) {
+ return getSourceConsumer(type).isRequestedVisible();
+ }
+
public InsetsState getLastDispatchedState() {
return mLastDispachedState;
}
@VisibleForTesting
public boolean onStateChanged(InsetsState state) {
- boolean localStateChanged = !mState.equals(state);
+ boolean localStateChanged = !mState.equals(state, true /* excludingCaptionInsets */)
+ || !captionInsetsUnchanged();
if (!localStateChanged && mLastDispachedState.equals(state)) {
return false;
}
@@ -470,7 +478,7 @@
if (localStateChanged) {
mViewRoot.notifyInsetsChanged();
}
- if (!mState.equals(mLastDispachedState)) {
+ if (!mState.equals(mLastDispachedState, true /* excludingCaptionInsets */)) {
sendStateToWindowManager();
}
return true;
@@ -488,6 +496,23 @@
mState.removeSource(source.getType());
}
}
+ if (mCaptionInsetsHeight != 0) {
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
+ mFrame.right, mFrame.top + mCaptionInsetsHeight));
+ }
+ }
+
+ private boolean captionInsetsUnchanged() {
+ if (mState.peekSource(ITYPE_CAPTION_BAR) == null
+ && mCaptionInsetsHeight == 0) {
+ return true;
+ }
+ if (mState.peekSource(ITYPE_CAPTION_BAR) != null
+ && mCaptionInsetsHeight
+ == mState.peekSource(ITYPE_CAPTION_BAR).getFrame().height()) {
+ return true;
+ }
+ return false;
}
/**
@@ -964,6 +989,7 @@
InsetsState tmpState = new InsetsState();
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
+ if (consumer.getType() == ITYPE_CAPTION_BAR) continue;
if (consumer.getControl() != null) {
tmpState.addSource(mState.getSource(consumer.getType()));
}
@@ -1105,6 +1131,11 @@
}
@Override
+ public void setCaptionInsetsHeight(int height) {
+ mCaptionInsetsHeight = height;
+ }
+
+ @Override
public void setSystemBarsBehavior(@Behavior int behavior) {
mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
if (mViewRoot.mWindowAttributes.insetsFlags.behavior != behavior) {
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 294faaf..033ccef 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import android.annotation.NonNull;
@@ -118,6 +119,12 @@
if (!getIntersection(frame, relativeFrame, mTmpFrame)) {
return Insets.NONE;
}
+ // During drag-move and drag-resizing, the caption insets position may not get updated
+ // before the app frame get updated. To layout the app content correctly during drag events,
+ // we always return the insets with the corresponding height covering the top.
+ if (getType() == ITYPE_CAPTION_BAR) {
+ return Insets.of(0, frame.height(), 0, 0);
+ }
// TODO: Currently, non-floating IME always intersects at bottom due to issues with cutout.
// However, we should let the policy decide from the server.
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index f36621c..360195d 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -112,12 +112,12 @@
hideTypes[0] |= toPublicType(getType());
}
} else {
- // We are gaining control, but don't need to run an animation.
- // However make sure that the leash visibility is still up to date.
- if (applyLocalVisibilityOverride()) {
- mController.notifyVisibilityChanged();
- }
- applyHiddenToControl();
+ // We are gaining control, but don't need to run an animation.
+ // However make sure that the leash visibility is still up to date.
+ if (applyLocalVisibilityOverride()) {
+ mController.notifyVisibilityChanged();
+ applyHiddenToControl();
+ }
}
}
if (lastControl != null) {
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 40e6f57..c515466 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -45,6 +45,8 @@
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -498,6 +500,19 @@
@Override
public boolean equals(Object o) {
+ return equals(o, false);
+ }
+
+ /**
+ * An equals method can exclude the caption insets. This is useful because we assemble the
+ * caption insets information on the client side, and when we communicate with server, it's
+ * excluded.
+ * @param excludingCaptionInsets {@code true} if we want to compare two InsetsState objects but
+ * ignore the caption insets source value.
+ * @return {@code true} if the two InsetsState objects are equal, {@code false} otherwise.
+ */
+ @VisibleForTesting
+ public boolean equals(Object o, boolean excludingCaptionInsets) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
@@ -506,11 +521,24 @@
if (!mDisplayFrame.equals(state.mDisplayFrame)) {
return false;
}
- if (mSources.size() != state.mSources.size()) {
+ int size = mSources.size();
+ int otherSize = state.mSources.size();
+ if (excludingCaptionInsets) {
+ if (mSources.get(ITYPE_CAPTION_BAR) != null) {
+ size--;
+ }
+ if (state.mSources.get(ITYPE_CAPTION_BAR) != null) {
+ otherSize--;
+ }
+ }
+ if (size != otherSize) {
return false;
}
for (int i = mSources.size() - 1; i >= 0; i--) {
InsetsSource source = mSources.valueAt(i);
+ if (excludingCaptionInsets) {
+ if (source.getType() == ITYPE_CAPTION_BAR) continue;
+ }
InsetsSource otherSource = state.mSources.get(source.getType());
if (otherSource == null) {
return false;
diff --git a/core/java/android/view/PendingInsetsController.java b/core/java/android/view/PendingInsetsController.java
index 229ee03..0283ada 100644
--- a/core/java/android/view/PendingInsetsController.java
+++ b/core/java/android/view/PendingInsetsController.java
@@ -42,6 +42,7 @@
private InsetsController mReplayedInsetsController;
private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
= new ArrayList<>();
+ private int mCaptionInsetsHeight = 0;
@Override
public void show(int types) {
@@ -80,6 +81,11 @@
}
@Override
+ public void setCaptionInsetsHeight(int height) {
+ mCaptionInsetsHeight = height;
+ }
+
+ @Override
public void setSystemBarsBehavior(int behavior) {
if (mReplayedInsetsController != null) {
mReplayedInsetsController.setSystemBarsBehavior(behavior);
@@ -102,6 +108,14 @@
}
@Override
+ public boolean isRequestedVisible(int type) {
+
+ // Method is only used once real insets controller is attached, so no need to traverse
+ // requests here.
+ return InsetsState.getDefaultVisibility(type);
+ }
+
+ @Override
public void addOnControllableInsetsChangedListener(
OnControllableInsetsChangedListener listener) {
if (mReplayedInsetsController != null) {
@@ -134,6 +148,9 @@
if (mAppearanceMask != 0) {
controller.setSystemBarsAppearance(mAppearance, mAppearanceMask);
}
+ if (mCaptionInsetsHeight != 0) {
+ controller.setCaptionInsetsHeight(mCaptionInsetsHeight);
+ }
int size = mRequests.size();
for (int i = 0; i < size; i++) {
mRequests.get(i).replay(controller);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 13d6dd6..d12ca73 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -871,24 +871,24 @@
/**
* Sets the intended frame rate for this surface.
*
- * On devices that are capable of running the display at different refresh rates, the
- * system may choose a display refresh rate to better match this surface's frame
+ * <p>On devices that are capable of running the display at different refresh rates,
+ * the system may choose a display refresh rate to better match this surface's frame
* rate. Usage of this API won't introduce frame rate throttling, or affect other
* aspects of the application's frame production pipeline. However, because the system
* may change the display refresh rate, calls to this function may result in changes
* to Choreographer callback timings, and changes to the time interval at which the
- * system releases buffers back to the application.
+ * system releases buffers back to the application.</p>
*
- * Note that this only has an effect for surfaces presented on the display. If this
+ * <p>Note that this only has an effect for surfaces presented on the display. If this
* surface is consumed by something other than the system compositor, e.g. a media
- * codec, this call has no effect.
+ * codec, this call has no effect.</p>
*
* @param frameRate The intended frame rate of this surface, in frames per second. 0
* is a special value that indicates the app will accept the system's choice for the
* display frame rate, which is the default behavior if this function isn't
- * called. The frameRate param does *not* need to be a valid refresh rate for this
- * device's display - e.g., it's fine to pass 30fps to a device that can only run the
- * display at 60fps.
+ * called. The frameRate param does <em>not</em> need to be a valid refresh rate for
+ * this device's display - e.g., it's fine to pass 30fps to a device that can only run
+ * the display at 60fps.
*
* @param compatibility The frame rate compatibility of this surface. The
* compatibility value may influence the system's choice of display frame rate. See
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index c87808b..a37c1cb 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -2738,7 +2738,7 @@
/**
* Sets the intended frame rate for the surface {@link SurfaceControl}.
- *
+ * <p>
* On devices that are capable of running the display at different refresh rates, the system
* may choose a display refresh rate to better match this surface's frame rate. Usage of
* this API won't directly affect the application's frame production pipeline. However,
@@ -2750,9 +2750,9 @@
* @param frameRate The intended frame rate for this surface, in frames per second. 0 is a
* special value that indicates the app will accept the system's choice for
* the display frame rate, which is the default behavior if this function
- * isn't called. The frameRate param does *not* need to be a valid refresh
- * rate for this device's display - e.g., it's fine to pass 30fps to a
- * device that can only run the display at 60fps.
+ * isn't called. The frameRate param does <em>not</em> need to be a valid
+ * refresh rate for this device's display - e.g., it's fine to pass 30fps
+ * to a device that can only run the display at 60fps.
* @param compatibility The frame rate compatibility of this surface. The compatibility
* value may influence the system's choice of display frame rate. See
* the Surface.FRAME_RATE_COMPATIBILITY_* values for more info.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4922917..da18608 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -28768,6 +28768,11 @@
publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
final Rect mStableInsets = new Rect();
+ /**
+ * Current caption insets to the display coordinate.
+ */
+ final Rect mCaptionInsets = new Rect();
+
final DisplayCutout.ParcelableWrapper mDisplayCutout =
new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 4bea623..69d37ab 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -16,8 +16,11 @@
package android.view;
+import static android.os.StrictMode.vmIncorrectContextUseEnabled;
+
import android.annotation.FloatRange;
import android.annotation.TestApi;
+import android.app.Activity;
import android.app.AppGlobals;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -25,9 +28,12 @@
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Build;
+import android.os.Bundle;
import android.os.RemoteException;
+import android.os.StrictMode;
import android.provider.Settings;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
@@ -35,6 +41,8 @@
* Contains methods to standard constants used in the UI for timeouts, sizes, and distances.
*/
public class ViewConfiguration {
+ private static final String TAG = "ViewConfiguration";
+
/**
* Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in
* dips
@@ -372,11 +380,13 @@
}
/**
- * Creates a new configuration for the specified context. The configuration depends on
- * various parameters of the context, like the dimension of the display or the density
- * of the display.
+ * Creates a new configuration for the specified visual {@link Context}. The configuration
+ * depends on various parameters of the {@link Context}, like the dimension of the display or
+ * the density of the display.
*
- * @param context The application context used to initialize this view configuration.
+ * @param context A visual {@link Context} used to initialize the view configuration. It must
+ * be {@link Activity} or other {@link Context} created with
+ * {@link Context#createWindowContext(int, Bundle)}.
*
* @see #get(android.content.Context)
* @see android.util.DisplayMetrics
@@ -480,13 +490,27 @@
}
/**
- * Returns a configuration for the specified context. The configuration depends on
- * various parameters of the context, like the dimension of the display or the
+ * Returns a configuration for the specified visual {@link Context}. The configuration depends
+ * on various parameters of the {@link Context}, like the dimension of the display or the
* density of the display.
*
- * @param context The application context used to initialize the view configuration.
+ * @param context A visual {@link Context} used to initialize the view configuration. It must
+ * be {@link Activity} or other {@link Context} created with
+ * {@link Context#createWindowContext(int, Bundle)}.
*/
public static ViewConfiguration get(Context context) {
+ if (!context.isUiContext() && vmIncorrectContextUseEnabled()) {
+ final String errorMessage = "Tried to access UI constants from a non-visual Context.";
+ final String message = "UI constants, such as display metrics or window metrics, "
+ + "must be accessed from Activity or other visual Context. "
+ + "Use an Activity or a Context created with "
+ + "Context#createWindowContext(int, Bundle), which are adjusted to the "
+ + "configuration and visual bounds of an area on screen.";
+ final Exception exception = new IllegalArgumentException(errorMessage);
+ StrictMode.onIncorrectContextUsed(message, exception);
+ Log.e(TAG, errorMessage + message, exception);
+ }
+
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
final int density = (int) (100.0f * metrics.density);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 50202ae..51304dc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -158,6 +158,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IResultReceiver;
import com.android.internal.os.SomeArgs;
+import com.android.internal.policy.DecorView;
import com.android.internal.policy.PhoneFallbackEventHandler;
import com.android.internal.util.Preconditions;
import com.android.internal.view.BaseSurfaceHolder;
@@ -2221,6 +2222,19 @@
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
+ private boolean updateCaptionInsets() {
+ if (!(mView instanceof DecorView)) return false;
+ final int captionInsetsHeight = ((DecorView) mView).getCaptionInsetsHeight();
+ final Rect captionFrame = new Rect();
+ if (captionInsetsHeight != 0) {
+ captionFrame.set(mWinFrame.left, mWinFrame.top, mWinFrame.right,
+ mWinFrame.top + captionInsetsHeight);
+ }
+ if (mAttachInfo.mCaptionInsets.equals(captionFrame)) return false;
+ mAttachInfo.mCaptionInsets.set(captionFrame);
+ return true;
+ }
+
private boolean shouldDispatchCutout() {
return mWindowAttributes.layoutInDisplayCutoutMode
== LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
@@ -2592,6 +2606,9 @@
mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars;
dispatchApplyInsets = true;
}
+ if (updateCaptionInsets()) {
+ dispatchApplyInsets = true;
+ }
if (dispatchApplyInsets || mLastSystemUiVisibility !=
mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested) {
mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0c5c183..ae9afaba 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -49,9 +49,6 @@
import android.transition.TransitionManager;
import android.util.Pair;
import android.view.View.OnApplyWindowInsetsListener;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowInsets.Side.InsetsSide;
-import android.view.WindowInsets.Type.InsetsType;
import android.view.accessibility.AccessibilityEvent;
import java.util.Collections;
@@ -323,7 +320,7 @@
@UnsupportedAppUsage
private boolean mDestroyed;
- private boolean mOverlayWithDecorCaptionEnabled = false;
+ private boolean mOverlayWithDecorCaptionEnabled = true;
private boolean mCloseOnSwipeEnabled = false;
// The current window attributes.
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index fde184c..9b2a6cb 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -17,6 +17,7 @@
package android.view;
+import static android.view.WindowInsets.Type.CAPTION_BAR;
import static android.view.WindowInsets.Type.DISPLAY_CUTOUT;
import static android.view.WindowInsets.Type.FIRST;
import static android.view.WindowInsets.Type.IME;
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index 0282eca..3d348ef 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -22,6 +22,7 @@
import android.graphics.Insets;
import android.inputmethodservice.InputMethodService;
import android.os.CancellationSignal;
+import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
import android.view.animation.Interpolator;
@@ -196,6 +197,15 @@
@Appearance int getSystemBarsAppearance();
/**
+ * Notify the caption insets height change. The information will be used on the client side to,
+ * make sure the InsetsState has the correct caption insets.
+ *
+ * @param height the height of caption bar insets.
+ * @hide
+ */
+ void setCaptionInsetsHeight(int height);
+
+ /**
* Controls the behavior of system bars.
*
* @param behavior Determines how the bars behave when being hidden by the application.
@@ -217,6 +227,13 @@
InsetsState getState();
/**
+ * @return Whether the specified insets source is currently requested to be visible by the
+ * application.
+ * @hide
+ */
+ boolean isRequestedVisible(@InternalInsetsType int type);
+
+ /**
* Adds a {@link OnControllableInsetsChangedListener} to the window insets controller.
*
* @param listener The listener to add.
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 77ce5c1..cc380f3 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -781,8 +781,6 @@
to = "BOOT_PROGRESS"),
@ViewDebug.IntToString(from = TYPE_INPUT_CONSUMER,
to = "INPUT_CONSUMER"),
- @ViewDebug.IntToString(from = TYPE_DREAM,
- to = "DREAM"),
@ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL,
to = "NAVIGATION_BAR_PANEL"),
@ViewDebug.IntToString(from = TYPE_DISPLAY_OVERLAY,
@@ -1105,13 +1103,6 @@
public static final int TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22;
/**
- * Window type: Dreams (screen saver) window, just above keyguard.
- * In multiuser systems shows only on the owning user's window.
- * @hide
- */
- public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23;
-
- /**
* Window type: Navigation bar panel (when navigation bar is distinct from status bar)
* In multiuser systems shows on all users' windows.
* @hide
@@ -1180,8 +1171,9 @@
public static final int TYPE_QS_DIALOG = FIRST_SYSTEM_WINDOW+35;
/**
- * Window type: shares similar characteristics with {@link #TYPE_DREAM}. The layer is
+ * Window type: shows directly above the keyguard. The layer is
* reserved for screenshot region selection. These windows must not take input focus.
+ * In multiuser systems shows only on the owning user's window.
* @hide
*/
public static final int TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36;
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 316a5f2..561ee60 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -36,6 +36,7 @@
import android.os.IBinder;
import android.os.RemoteException;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IResultReceiver;
import java.util.List;
@@ -69,7 +70,8 @@
public final class WindowManagerImpl implements WindowManager {
@UnsupportedAppUsage
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
- private final Context mContext;
+ @VisibleForTesting
+ public final Context mContext;
private final Window mParentWindow;
private IBinder mDefaultToken;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 267a5a6..83a7934 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -41,7 +41,9 @@
import android.metrics.LogMaker;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -63,6 +65,7 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.accessibility.AccessibilityWindowInfo;
+import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
@@ -2444,6 +2447,44 @@
}
}
+ private void requestShowSoftInput(@NonNull AutofillId id) {
+ if (sVerbose) Log.v(TAG, "requestShowSoftInput(" + id + ")");
+ final AutofillClient client = getClient();
+ if (client == null) {
+ return;
+ }
+ final View view = client.autofillClientFindViewByAutofillIdTraversal(id);
+ if (view == null) {
+ if (sVerbose) Log.v(TAG, "View is not found");
+ return;
+ }
+ final Handler handler = view.getHandler();
+ if (handler == null) {
+ if (sVerbose) Log.v(TAG, "Ignoring requestShowSoftInput due to no handler in view");
+ return;
+ }
+ if (handler.getLooper() != Looper.myLooper()) {
+ // The view is running on a different thread than our own, so we need to reschedule
+ // our work for over there.
+ if (sVerbose) Log.v(TAG, "Scheduling showSoftInput() on the view UI thread");
+ handler.post(() -> requestShowSoftInputInViewThread(view));
+ } else {
+ requestShowSoftInputInViewThread(view);
+ }
+ }
+
+ // This method must be called from within the View thread.
+ private static void requestShowSoftInputInViewThread(@NonNull View view) {
+ if (!view.isFocused()) {
+ Log.w(TAG, "Ignoring requestShowSoftInput() due to non-focused view");
+ return;
+ }
+ final InputMethodManager inputMethodManager = view.getContext().getSystemService(
+ InputMethodManager.class);
+ boolean ret = inputMethodManager.showSoftInput(view, /*flags=*/ 0);
+ if (sVerbose) Log.v(TAG, " InputMethodManager.showSoftInput returns " + ret);
+ }
+
/** @hide */
public void requestHideFillUi() {
requestHideFillUi(mIdShownFillUi, true);
@@ -3368,6 +3409,14 @@
afm.post(() -> afm.getAugmentedAutofillClient(result));
}
}
+
+ @Override
+ public void requestShowSoftInput(@NonNull AutofillId id) {
+ final AutofillManager afm = mAfm.get();
+ if (afm != null) {
+ afm.post(() -> afm.requestShowSoftInput(id));
+ }
+ }
}
private static final class AugmentedAutofillManagerClient
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 4371b3c..87d65c2 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -117,4 +117,9 @@
* Notifies disables autofill for the app or activity.
*/
void notifyDisableAutofill(long disableDuration, in ComponentName componentName);
+
+ /**
+ * Requests to show the soft input method if the focus is on the given id.
+ */
+ void requestShowSoftInput(in AutofillId id);
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 1692051..b84cb88 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -15,7 +15,7 @@
*/
package android.view.contentcapture;
-import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import android.annotation.IntDef;
import android.annotation.NonNull;
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index ea34d94..f49b1be 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -16,7 +16,7 @@
package android.view.contentcapture;
import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString;
-import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import android.annotation.IntDef;
import android.annotation.NonNull;
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index b988927..edc6b12 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -54,6 +54,8 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -235,6 +237,13 @@
public static final int RESULT_CODE_SECURITY_EXCEPTION = -1;
/**
+ * ID used to indicate that a session does not exist
+ * @hide
+ */
+ @SystemApi
+ public static final int NO_SESSION_ID = 0;
+
+ /**
* Timeout for calls to system_server.
*/
private static final int SYNC_CALLS_TIMEOUT_MS = 5000;
@@ -353,6 +362,9 @@
@NonNull
private final IContentCaptureManager mService;
+ @GuardedBy("mLock")
+ private final LocalDataShareAdapterResourceManager mDataShareAdapterResourceManager;
+
@NonNull
final ContentCaptureOptions mOptions;
@@ -392,6 +404,8 @@
// do, then we should optimize it to run the tests after the Choreographer finishes the most
// important steps of the frame.
mHandler = Handler.createAsync(Looper.getMainLooper());
+
+ mDataShareAdapterResourceManager = new LocalDataShareAdapterResourceManager();
}
/**
@@ -674,7 +688,8 @@
try {
mService.shareData(request,
- new DataShareAdapterDelegate(executor, dataShareWriteAdapter));
+ new DataShareAdapterDelegate(executor, dataShareWriteAdapter,
+ mDataShareAdapterResourceManager));
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
@@ -730,40 +745,53 @@
private static class DataShareAdapterDelegate extends IDataShareWriteAdapter.Stub {
- private final WeakReference<DataShareWriteAdapter> mAdapterReference;
- private final WeakReference<Executor> mExecutorReference;
+ private final WeakReference<LocalDataShareAdapterResourceManager> mResourceManagerReference;
- private DataShareAdapterDelegate(Executor executor, DataShareWriteAdapter adapter) {
+ private DataShareAdapterDelegate(Executor executor, DataShareWriteAdapter adapter,
+ LocalDataShareAdapterResourceManager resourceManager) {
Preconditions.checkNotNull(executor);
Preconditions.checkNotNull(adapter);
+ Preconditions.checkNotNull(resourceManager);
- mExecutorReference = new WeakReference<>(executor);
- mAdapterReference = new WeakReference<>(adapter);
+ resourceManager.initializeForDelegate(this, adapter, executor);
+ mResourceManagerReference = new WeakReference<>(resourceManager);
}
@Override
public void write(ParcelFileDescriptor destination)
throws RemoteException {
executeAdapterMethodLocked(adapter -> adapter.onWrite(destination), "onWrite");
+
+ // Client app and Service successfully connected, so this object would be kept alive
+ // until the session has finished.
+ clearHardReferences();
}
@Override
public void error(int errorCode) throws RemoteException {
executeAdapterMethodLocked(adapter -> adapter.onError(errorCode), "onError");
+ clearHardReferences();
}
@Override
public void rejected() throws RemoteException {
executeAdapterMethodLocked(DataShareWriteAdapter::onRejected, "onRejected");
+ clearHardReferences();
}
private void executeAdapterMethodLocked(Consumer<DataShareWriteAdapter> adapterFn,
String methodName) {
- DataShareWriteAdapter adapter = mAdapterReference.get();
- Executor executor = mExecutorReference.get();
+ LocalDataShareAdapterResourceManager resourceManager = mResourceManagerReference.get();
+ if (resourceManager == null) {
+ Slog.w(TAG, "Can't execute " + methodName + "(), resource manager has been GC'ed");
+ return;
+ }
+
+ DataShareWriteAdapter adapter = resourceManager.getAdapter(this);
+ Executor executor = resourceManager.getExecutor(this);
if (adapter == null || executor == null) {
- Slog.w(TAG, "Can't execute " + methodName + "(), references have been GC'ed");
+ Slog.w(TAG, "Can't execute " + methodName + "(), references are null");
return;
}
@@ -774,5 +802,50 @@
Binder.restoreCallingIdentity(identity);
}
}
+
+ private void clearHardReferences() {
+ LocalDataShareAdapterResourceManager resourceManager = mResourceManagerReference.get();
+ if (resourceManager == null) {
+ Slog.w(TAG, "Can't clear references, resource manager has been GC'ed");
+ return;
+ }
+
+ resourceManager.clearHardReferences(this);
+ }
+ }
+
+ /**
+ * Wrapper class making sure dependencies on the current application stay in the application
+ * context.
+ */
+ private static class LocalDataShareAdapterResourceManager {
+
+ // Keeping hard references to the remote objects in the current process (static context)
+ // to prevent them to be gc'ed during the lifetime of the application. This is an
+ // artifact of only operating with weak references remotely: there has to be at least 1
+ // hard reference in order for this to not be killed.
+ private Map<DataShareAdapterDelegate, DataShareWriteAdapter> mWriteAdapterHardReferences =
+ new HashMap<>();
+ private Map<DataShareAdapterDelegate, Executor> mExecutorHardReferences =
+ new HashMap<>();
+
+ void initializeForDelegate(DataShareAdapterDelegate delegate, DataShareWriteAdapter adapter,
+ Executor executor) {
+ mWriteAdapterHardReferences.put(delegate, adapter);
+ mExecutorHardReferences.remove(delegate, executor);
+ }
+
+ Executor getExecutor(DataShareAdapterDelegate delegate) {
+ return mExecutorHardReferences.get(delegate);
+ }
+
+ DataShareWriteAdapter getAdapter(DataShareAdapterDelegate delegate) {
+ return mWriteAdapterHardReferences.get(delegate);
+ }
+
+ void clearHardReferences(DataShareAdapterDelegate delegate) {
+ mWriteAdapterHardReferences.remove(delegate);
+ mExecutorHardReferences.remove(delegate);
+ }
}
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 012f5e6..39c7210 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -17,12 +17,12 @@
import static android.view.contentcapture.ContentCaptureHelper.sDebug;
import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.graphics.Insets;
import android.util.DebugUtils;
import android.util.Log;
@@ -53,13 +53,6 @@
private static final Random sIdGenerator = new Random();
/**
- * ID used to indicate that a session does not exist
- * @hide
- */
- @SystemApi
- public static final int NO_SESSION_ID = 0;
-
- /**
* Initial state, when there is no session.
*
* @hide
diff --git a/core/java/android/view/inline/InlineContentView.java b/core/java/android/view/inline/InlineContentView.java
index df5bc2fb..deb93a9 100644
--- a/core/java/android/view/inline/InlineContentView.java
+++ b/core/java/android/view/inline/InlineContentView.java
@@ -45,6 +45,9 @@
* under the hosting window which could be useful in some cases, e.g. animating transitions.
* At this point the inlined content will not be interactive and the touch events would
* be delivered to your app.
+ *
+ * @hide
+ * @removed
*/
public class InlineContentView extends ViewGroup {
diff --git a/core/java/android/view/inline/InlinePresentationSpec.aidl b/core/java/android/view/inline/InlinePresentationSpec.aidl
index efa46c8..680ee4e 100644
--- a/core/java/android/view/inline/InlinePresentationSpec.aidl
+++ b/core/java/android/view/inline/InlinePresentationSpec.aidl
@@ -16,4 +16,8 @@
package android.view.inline;
+/**
+ * @hide
+ * @removed
+ */
parcelable InlinePresentationSpec;
diff --git a/core/java/android/view/inline/InlinePresentationSpec.java b/core/java/android/view/inline/InlinePresentationSpec.java
index 3788e2b..60687fb 100644
--- a/core/java/android/view/inline/InlinePresentationSpec.java
+++ b/core/java/android/view/inline/InlinePresentationSpec.java
@@ -29,6 +29,9 @@
* should abide when constructing its UI. Since suggestions are inlined in a
* host application while provided by another source, they need to be consistent
* with the host's look at feel to allow building smooth and integrated UIs.
+ *
+ * @hide
+ * @removed
*/
@DataClass(genEqualsHashCode = true, genToString = true, genBuilder = true)
public final class InlinePresentationSpec implements Parcelable {
@@ -279,7 +282,7 @@
}
@DataClass.Generated(
- time = 1584067238741L,
+ time = 1585177087499L,
codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/view/inline/InlinePresentationSpec.java",
inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nprivate final @android.annotation.Nullable android.os.Bundle mStyle\nprivate static android.os.Bundle defaultStyle()\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
diff --git a/core/java/android/view/inputmethod/InlineSuggestion.java b/core/java/android/view/inputmethod/InlineSuggestion.java
index ab8f36d..f50f0dea 100644
--- a/core/java/android/view/inputmethod/InlineSuggestion.java
+++ b/core/java/android/view/inputmethod/InlineSuggestion.java
@@ -29,8 +29,7 @@
import android.util.Size;
import android.util.Slog;
import android.view.SurfaceControlViewHost;
-import android.view.inline.InlineContentView;
-import android.view.inline.InlinePresentationSpec;
+import android.widget.inline.InlineContentView;
import com.android.internal.util.DataClass;
import com.android.internal.util.Parcelling;
@@ -95,9 +94,10 @@
/**
* Inflates a view with the content of this suggestion at a specific size.
- * The size must be between the {@link InlinePresentationSpec#getMinSize() min size}
- * and the {@link InlinePresentationSpec#getMaxSize() max size} of the presentation
- * spec returned by {@link InlineSuggestionInfo#getPresentationSpec()}.
+ * The size must be between the
+ * {@link android.widget.inline.InlinePresentationSpec#getMinSize() min size} and the
+ * {@link android.widget.inline.InlinePresentationSpec#getMaxSize() max size} of the
+ * presentation spec returned by {@link InlineSuggestionInfo#getInlinePresentationSpec()}.
*
* <p> The caller can attach an {@link android.view.View.OnClickListener} and/or an
* {@link android.view.View.OnLongClickListener} to the view in the
@@ -113,8 +113,8 @@
public void inflate(@NonNull Context context, @NonNull Size size,
@NonNull @CallbackExecutor Executor callbackExecutor,
@NonNull Consumer<InlineContentView> callback) {
- final Size minSize = mInfo.getPresentationSpec().getMinSize();
- final Size maxSize = mInfo.getPresentationSpec().getMaxSize();
+ final Size minSize = mInfo.getInlinePresentationSpec().getMinSize();
+ final Size maxSize = mInfo.getInlinePresentationSpec().getMaxSize();
if (size.getHeight() < minSize.getHeight() || size.getHeight() > maxSize.getHeight()
|| size.getWidth() < minSize.getWidth() || size.getWidth() > maxSize.getWidth()) {
throw new IllegalArgumentException("size not between min:"
@@ -398,10 +398,10 @@
};
@DataClass.Generated(
- time = 1584679775946L,
+ time = 1585180783541L,
codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java",
- inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.view.inline.InlineContentView>)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.view.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
+ inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionInfo.java b/core/java/android/view/inputmethod/InlineSuggestionInfo.java
index cb0320e..fe2ce25 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionInfo.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionInfo.java
@@ -20,8 +20,9 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
+import android.os.Bundle;
import android.os.Parcelable;
-import android.view.inline.InlinePresentationSpec;
+import android.widget.inline.InlinePresentationSpec;
import com.android.internal.util.DataClass;
@@ -58,7 +59,7 @@
public static final @Type String TYPE_ACTION = "android:autofill:action";
/** The presentation spec to which the inflated suggestion view abides. */
- private final @NonNull InlinePresentationSpec mPresentationSpec;
+ private final @NonNull InlinePresentationSpec mInlinePresentationSpec;
/** The source from which the suggestion is provided. */
private final @NonNull @Source String mSource;
@@ -86,9 +87,26 @@
return new InlineSuggestionInfo(presentationSpec, source, autofillHints, type, isPinned);
}
+ /**
+ * The presentation spec to which the inflated suggestion view abides.
+ *
+ * @hide
+ * @removed
+ */
+ public @NonNull android.view.inline.InlinePresentationSpec getPresentationSpec() {
+ final android.view.inline.InlinePresentationSpec.Builder builder =
+ new android.view.inline.InlinePresentationSpec.Builder(
+ mInlinePresentationSpec.getMinSize(), mInlinePresentationSpec.getMaxSize());
+ final Bundle style = mInlinePresentationSpec.getStyle();
+ if (style != null) {
+ builder.setStyle(style);
+ }
+ return builder.build();
+ }
- // Code below generated by codegen v1.0.14.
+
+ // Code below generated by codegen v1.0.15.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -122,7 +140,7 @@
/**
* Creates a new InlineSuggestionInfo.
*
- * @param presentationSpec
+ * @param inlinePresentationSpec
* The presentation spec to which the inflated suggestion view abides.
* @param source
* The source from which the suggestion is provided.
@@ -136,14 +154,14 @@
*/
@DataClass.Generated.Member
public InlineSuggestionInfo(
- @NonNull InlinePresentationSpec presentationSpec,
+ @NonNull InlinePresentationSpec inlinePresentationSpec,
@NonNull @Source String source,
@Nullable String[] autofillHints,
@NonNull @Type String type,
boolean pinned) {
- this.mPresentationSpec = presentationSpec;
+ this.mInlinePresentationSpec = inlinePresentationSpec;
com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPresentationSpec);
+ NonNull.class, null, mInlinePresentationSpec);
this.mSource = source;
if (!(java.util.Objects.equals(mSource, SOURCE_AUTOFILL))
@@ -178,8 +196,8 @@
* The presentation spec to which the inflated suggestion view abides.
*/
@DataClass.Generated.Member
- public @NonNull InlinePresentationSpec getPresentationSpec() {
- return mPresentationSpec;
+ public @NonNull InlinePresentationSpec getInlinePresentationSpec() {
+ return mInlinePresentationSpec;
}
/**
@@ -221,7 +239,7 @@
// String fieldNameToString() { ... }
return "InlineSuggestionInfo { " +
- "presentationSpec = " + mPresentationSpec + ", " +
+ "inlinePresentationSpec = " + mInlinePresentationSpec + ", " +
"source = " + mSource + ", " +
"autofillHints = " + java.util.Arrays.toString(mAutofillHints) + ", " +
"type = " + mType + ", " +
@@ -242,7 +260,7 @@
InlineSuggestionInfo that = (InlineSuggestionInfo) o;
//noinspection PointlessBooleanExpression
return true
- && java.util.Objects.equals(mPresentationSpec, that.mPresentationSpec)
+ && java.util.Objects.equals(mInlinePresentationSpec, that.mInlinePresentationSpec)
&& java.util.Objects.equals(mSource, that.mSource)
&& java.util.Arrays.equals(mAutofillHints, that.mAutofillHints)
&& java.util.Objects.equals(mType, that.mType)
@@ -256,7 +274,7 @@
// int fieldNameHashCode() { ... }
int _hash = 1;
- _hash = 31 * _hash + java.util.Objects.hashCode(mPresentationSpec);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mInlinePresentationSpec);
_hash = 31 * _hash + java.util.Objects.hashCode(mSource);
_hash = 31 * _hash + java.util.Arrays.hashCode(mAutofillHints);
_hash = 31 * _hash + java.util.Objects.hashCode(mType);
@@ -274,7 +292,7 @@
if (mPinned) flg |= 0x10;
if (mAutofillHints != null) flg |= 0x4;
dest.writeByte(flg);
- dest.writeTypedObject(mPresentationSpec, flags);
+ dest.writeTypedObject(mInlinePresentationSpec, flags);
dest.writeString(mSource);
if (mAutofillHints != null) dest.writeStringArray(mAutofillHints);
dest.writeString(mType);
@@ -293,14 +311,14 @@
byte flg = in.readByte();
boolean pinned = (flg & 0x10) != 0;
- InlinePresentationSpec presentationSpec = (InlinePresentationSpec) in.readTypedObject(InlinePresentationSpec.CREATOR);
+ InlinePresentationSpec inlinePresentationSpec = (InlinePresentationSpec) in.readTypedObject(InlinePresentationSpec.CREATOR);
String source = in.readString();
String[] autofillHints = (flg & 0x4) == 0 ? null : in.createStringArray();
String type = in.readString();
- this.mPresentationSpec = presentationSpec;
+ this.mInlinePresentationSpec = inlinePresentationSpec;
com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPresentationSpec);
+ NonNull.class, null, mInlinePresentationSpec);
this.mSource = source;
if (!(java.util.Objects.equals(mSource, SOURCE_AUTOFILL))
@@ -346,10 +364,10 @@
};
@DataClass.Generated(
- time = 1582753084046L,
- codegenVersion = "1.0.14",
+ time = 1585528157244L,
+ codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionInfo.java",
- inputSignatures = "public static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_AUTOFILL\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_PLATFORM\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String TYPE_SUGGESTION\npublic static final @android.annotation.SuppressLint({\"IntentName\"}) @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String TYPE_ACTION\nprivate final @android.annotation.NonNull android.view.inline.InlinePresentationSpec mPresentationSpec\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String mSource\nprivate final @android.annotation.Nullable java.lang.String[] mAutofillHints\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String mType\nprivate final boolean mPinned\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo newInlineSuggestionInfo(android.view.inline.InlinePresentationSpec,java.lang.String,java.lang.String[],java.lang.String,boolean)\nclass InlineSuggestionInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
+ inputSignatures = "public static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_AUTOFILL\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_PLATFORM\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String TYPE_SUGGESTION\npublic static final @android.annotation.SuppressLint({\"IntentName\"}) @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String TYPE_ACTION\nprivate final @android.annotation.NonNull android.widget.inline.InlinePresentationSpec mInlinePresentationSpec\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String mSource\nprivate final @android.annotation.Nullable java.lang.String[] mAutofillHints\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String mType\nprivate final boolean mPinned\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo newInlineSuggestionInfo(android.widget.inline.InlinePresentationSpec,java.lang.String,java.lang.String[],java.lang.String,boolean)\npublic @android.annotation.NonNull android.view.inline.InlinePresentationSpec getPresentationSpec()\nclass InlineSuggestionInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index 2945a86..61997c1 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -25,7 +25,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.view.Display;
-import android.view.inline.InlinePresentationSpec;
+import android.widget.inline.InlinePresentationSpec;
import com.android.internal.util.DataClass;
import com.android.internal.util.Preconditions;
@@ -54,7 +54,7 @@
* count is larger than the number of specs in the list, then the last spec is used for the
* remainder of the suggestions. The list should not be empty.
*/
- private final @NonNull List<InlinePresentationSpec> mPresentationSpecs;
+ private final @NonNull List<InlinePresentationSpec> mInlinePresentationSpecs;
/**
* The package name of the app that requests for the inline suggestions and will host the
@@ -91,6 +91,32 @@
private int mHostDisplayId;
/**
+ * The {@link InlinePresentationSpec} for each suggestion in the response. If the max suggestion
+ * count is larger than the number of specs in the list, then the last spec is used for the
+ * remainder of the suggestions. The list should not be empty.
+ *
+ * @hide
+ * @removed
+ */
+ public @NonNull List<android.view.inline.InlinePresentationSpec> getPresentationSpecs() {
+ final ArrayList<android.view.inline.InlinePresentationSpec> convertedSpecs =
+ new ArrayList<>();
+ for (int i = 0; i < mInlinePresentationSpecs.size(); i++) {
+ final android.widget.inline.InlinePresentationSpec currSpec =
+ mInlinePresentationSpecs.get(i);
+ final android.view.inline.InlinePresentationSpec.Builder builder =
+ new android.view.inline.InlinePresentationSpec.Builder(
+ currSpec.getMinSize(), currSpec.getMaxSize());
+ final Bundle style = currSpec.getStyle();
+ if (style != null) {
+ builder.setStyle(style);
+ }
+ convertedSpecs.add(builder.build());
+ }
+ return convertedSpecs;
+ }
+
+ /**
* @hide
* @see {@link #mHostInputToken}.
*/
@@ -117,8 +143,8 @@
}
private void onConstructed() {
- Preconditions.checkState(!mPresentationSpecs.isEmpty());
- Preconditions.checkState(mMaxSuggestionCount >= mPresentationSpecs.size());
+ Preconditions.checkState(!mInlinePresentationSpecs.isEmpty());
+ Preconditions.checkState(mMaxSuggestionCount >= mInlinePresentationSpecs.size());
}
private static int defaultMaxSuggestionCount() {
@@ -148,11 +174,64 @@
return null;
}
-
-
/** @hide */
abstract static class BaseBuilder {
- abstract Builder setPresentationSpecs(@NonNull List<InlinePresentationSpec> value);
+ /**
+ * The {@link android.view.inline.InlinePresentationSpec} for each suggestion in the
+ * response. If the max suggestion count is larger than the number of specs in the list,
+ * then the last spec is used for the remainder of the suggestions.
+ * The list should not be empty.
+ *
+ * @hide
+ * @removed
+ */
+ @NonNull Builder setPresentationSpecs(
+ @NonNull List<android.view.inline.InlinePresentationSpec> specs) {
+ ((Builder) this).checkNotUsed();
+ ((Builder) this).mBuilderFieldsSet |= 0x2;
+ final ArrayList<android.widget.inline.InlinePresentationSpec> convertedSpecs =
+ new ArrayList<>();
+ for (int i = 0; i < specs.size(); i++) {
+ final android.view.inline.InlinePresentationSpec currSpec = specs.get(i);
+ final android.widget.inline.InlinePresentationSpec.Builder builder =
+ new android.widget.inline.InlinePresentationSpec.Builder(
+ currSpec.getMinSize(), currSpec.getMaxSize());
+ final Bundle style = currSpec.getStyle();
+ if (style != null) {
+ builder.setStyle(style);
+ }
+ convertedSpecs.add(builder.build());
+ }
+ ((Builder) this).mInlinePresentationSpecs = convertedSpecs;
+ return ((Builder) this);
+ }
+
+ /**
+ * @see #setPresentationSpecs
+ *
+ * @hide
+ * @removed
+ */
+ public @NonNull Builder addPresentationSpecs(
+ @NonNull android.view.inline.InlinePresentationSpec value) {
+ if (((Builder) this).mInlinePresentationSpecs == null) {
+ setPresentationSpecs(new ArrayList<>());
+ }
+
+ final android.widget.inline.InlinePresentationSpec.Builder builder =
+ new android.widget.inline.InlinePresentationSpec.Builder(
+ value.getMinSize(), value.getMaxSize());
+ final Bundle style = value.getStyle();
+ if (style != null) {
+ builder.setStyle(style);
+ }
+
+ ((Builder) this).mInlinePresentationSpecs.add(builder.build());
+ return ((Builder) this);
+ }
+
+ abstract Builder setInlinePresentationSpecs(
+ @NonNull List<android.widget.inline.InlinePresentationSpec> specs);
abstract Builder setHostPackageName(@Nullable String value);
@@ -179,16 +258,16 @@
@DataClass.Generated.Member
/* package-private */ InlineSuggestionsRequest(
int maxSuggestionCount,
- @NonNull List<InlinePresentationSpec> presentationSpecs,
+ @NonNull List<InlinePresentationSpec> inlinePresentationSpecs,
@NonNull String hostPackageName,
@NonNull LocaleList supportedLocales,
@Nullable Bundle extras,
@Nullable IBinder hostInputToken,
int hostDisplayId) {
this.mMaxSuggestionCount = maxSuggestionCount;
- this.mPresentationSpecs = presentationSpecs;
+ this.mInlinePresentationSpecs = inlinePresentationSpecs;
com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPresentationSpecs);
+ NonNull.class, null, mInlinePresentationSpecs);
this.mHostPackageName = hostPackageName;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mHostPackageName);
@@ -217,8 +296,8 @@
* remainder of the suggestions. The list should not be empty.
*/
@DataClass.Generated.Member
- public @NonNull List<InlinePresentationSpec> getPresentationSpecs() {
- return mPresentationSpecs;
+ public @NonNull List<InlinePresentationSpec> getInlinePresentationSpecs() {
+ return mInlinePresentationSpecs;
}
/**
@@ -278,7 +357,7 @@
return "InlineSuggestionsRequest { " +
"maxSuggestionCount = " + mMaxSuggestionCount + ", " +
- "presentationSpecs = " + mPresentationSpecs + ", " +
+ "inlinePresentationSpecs = " + mInlinePresentationSpecs + ", " +
"hostPackageName = " + mHostPackageName + ", " +
"supportedLocales = " + mSupportedLocales + ", " +
"extras = " + mExtras + ", " +
@@ -301,7 +380,7 @@
//noinspection PointlessBooleanExpression
return true
&& mMaxSuggestionCount == that.mMaxSuggestionCount
- && java.util.Objects.equals(mPresentationSpecs, that.mPresentationSpecs)
+ && java.util.Objects.equals(mInlinePresentationSpecs, that.mInlinePresentationSpecs)
&& java.util.Objects.equals(mHostPackageName, that.mHostPackageName)
&& java.util.Objects.equals(mSupportedLocales, that.mSupportedLocales)
&& java.util.Objects.equals(mExtras, that.mExtras)
@@ -317,7 +396,7 @@
int _hash = 1;
_hash = 31 * _hash + mMaxSuggestionCount;
- _hash = 31 * _hash + java.util.Objects.hashCode(mPresentationSpecs);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mInlinePresentationSpecs);
_hash = 31 * _hash + java.util.Objects.hashCode(mHostPackageName);
_hash = 31 * _hash + java.util.Objects.hashCode(mSupportedLocales);
_hash = 31 * _hash + java.util.Objects.hashCode(mExtras);
@@ -337,7 +416,7 @@
if (mHostInputToken != null) flg |= 0x20;
dest.writeByte(flg);
dest.writeInt(mMaxSuggestionCount);
- dest.writeParcelableList(mPresentationSpecs, flags);
+ dest.writeParcelableList(mInlinePresentationSpecs, flags);
dest.writeString(mHostPackageName);
dest.writeTypedObject(mSupportedLocales, flags);
if (mExtras != null) dest.writeBundle(mExtras);
@@ -358,8 +437,8 @@
byte flg = in.readByte();
int maxSuggestionCount = in.readInt();
- List<InlinePresentationSpec> presentationSpecs = new ArrayList<>();
- in.readParcelableList(presentationSpecs, InlinePresentationSpec.class.getClassLoader());
+ List<InlinePresentationSpec> inlinePresentationSpecs = new ArrayList<>();
+ in.readParcelableList(inlinePresentationSpecs, InlinePresentationSpec.class.getClassLoader());
String hostPackageName = in.readString();
LocaleList supportedLocales = (LocaleList) in.readTypedObject(LocaleList.CREATOR);
Bundle extras = (flg & 0x10) == 0 ? null : in.readBundle();
@@ -367,9 +446,9 @@
int hostDisplayId = in.readInt();
this.mMaxSuggestionCount = maxSuggestionCount;
- this.mPresentationSpecs = presentationSpecs;
+ this.mInlinePresentationSpecs = inlinePresentationSpecs;
com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPresentationSpecs);
+ NonNull.class, null, mInlinePresentationSpecs);
this.mHostPackageName = hostPackageName;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mHostPackageName);
@@ -405,7 +484,7 @@
public static final class Builder extends BaseBuilder {
private int mMaxSuggestionCount;
- private @NonNull List<InlinePresentationSpec> mPresentationSpecs;
+ private @NonNull List<InlinePresentationSpec> mInlinePresentationSpecs;
private @NonNull String mHostPackageName;
private @NonNull LocaleList mSupportedLocales;
private @Nullable Bundle mExtras;
@@ -417,16 +496,16 @@
/**
* Creates a new Builder.
*
- * @param presentationSpecs
+ * @param inlinePresentationSpecs
* The {@link InlinePresentationSpec} for each suggestion in the response. If the max suggestion
* count is larger than the number of specs in the list, then the last spec is used for the
* remainder of the suggestions. The list should not be empty.
*/
public Builder(
- @NonNull List<InlinePresentationSpec> presentationSpecs) {
- mPresentationSpecs = presentationSpecs;
+ @NonNull List<InlinePresentationSpec> inlinePresentationSpecs) {
+ mInlinePresentationSpecs = inlinePresentationSpecs;
com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPresentationSpecs);
+ NonNull.class, null, mInlinePresentationSpecs);
}
/**
@@ -447,22 +526,21 @@
* remainder of the suggestions. The list should not be empty.
*/
@DataClass.Generated.Member
- @Override
- @NonNull Builder setPresentationSpecs(@NonNull List<InlinePresentationSpec> value) {
+ public @NonNull Builder setInlinePresentationSpecs(@NonNull List<InlinePresentationSpec> value) {
checkNotUsed();
mBuilderFieldsSet |= 0x2;
- mPresentationSpecs = value;
+ mInlinePresentationSpecs = value;
return this;
}
- /** @see #setPresentationSpecs */
+ /** @see #setInlinePresentationSpecs */
@DataClass.Generated.Member
- public @NonNull Builder addPresentationSpecs(@NonNull InlinePresentationSpec value) {
+ public @NonNull Builder addInlinePresentationSpecs(@NonNull InlinePresentationSpec value) {
// You can refine this method's name by providing item's singular name, e.g.:
// @DataClass.PluralOf("item")) mItems = ...
- if (mPresentationSpecs == null) setPresentationSpecs(new ArrayList<>());
- mPresentationSpecs.add(value);
+ if (mInlinePresentationSpecs == null) setInlinePresentationSpecs(new ArrayList<>());
+ mInlinePresentationSpecs.add(value);
return this;
}
@@ -558,7 +636,7 @@
}
InlineSuggestionsRequest o = new InlineSuggestionsRequest(
mMaxSuggestionCount,
- mPresentationSpecs,
+ mInlinePresentationSpecs,
mHostPackageName,
mSupportedLocales,
mExtras,
@@ -576,10 +654,10 @@
}
@DataClass.Generated(
- time = 1584067152935L,
+ time = 1585528160885L,
codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
- inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> mPresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.Nullable android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\npublic void setHostInputToken(android.os.IBinder)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.Nullable android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.Nullable android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\npublic @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> getPresentationSpecs()\npublic void setHostInputToken(android.os.IBinder)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.Nullable android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\n @android.annotation.NonNull android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\npublic @android.annotation.NonNull android.view.inputmethod.InlineSuggestionsRequest.Builder addPresentationSpecs(android.view.inline.InlinePresentationSpec)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/widget/inline/InlineContentView.java b/core/java/android/widget/inline/InlineContentView.java
new file mode 100644
index 0000000..16a61fb
--- /dev/null
+++ b/core/java/android/widget/inline/InlineContentView.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.inline;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.util.AttributeSet;
+import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+
+/**
+ * This class represents a view that holds opaque content from another app that
+ * you can inline in your UI.
+ *
+ * <p>Since the content presented by this view is from another security domain,it is
+ * shown on a remote surface preventing the host application from accessing that content.
+ * Also the host application cannot interact with the inlined content by injecting touch
+ * events or clicking programmatically.
+ *
+ * <p>This view can be overlaid by other windows, i.e. redressed, but if this is the case
+ * the inined UI would not be interactive. Sometimes this is desirable, e.g. animating
+ * transitions.
+ *
+ * <p>By default the surface backing this view is shown on top of the hosting window such
+ * that the inlined content is interactive. However, you can temporarily move the surface
+ * under the hosting window which could be useful in some cases, e.g. animating transitions.
+ * At this point the inlined content will not be interactive and the touch events would
+ * be delivered to your app.
+ */
+public class InlineContentView extends ViewGroup {
+
+ /**
+ * Callback for observing the lifecycle of the surface control
+ * that manipulates the backing secure embedded UI surface.
+ */
+ public interface SurfaceControlCallback {
+ /**
+ * Called when the backing surface is being created.
+ *
+ * @param surfaceControl The surface control to manipulate the surface.
+ */
+ void onCreated(@NonNull SurfaceControl surfaceControl);
+
+ /**
+ * Called when the backing surface is being destroyed.
+ *
+ * @param surfaceControl The surface control to manipulate the surface.
+ */
+ void onDestroyed(@NonNull SurfaceControl surfaceControl);
+ }
+
+ private final @NonNull SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceCreated(@NonNull SurfaceHolder holder) {
+ mSurfaceControlCallback.onCreated(mSurfaceView.getSurfaceControl());
+ }
+
+ @Override
+ public void surfaceChanged(@NonNull SurfaceHolder holder,
+ int format, int width, int height) {
+ /* do nothing */
+ }
+
+ @Override
+ public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
+ mSurfaceControlCallback.onDestroyed(mSurfaceView.getSurfaceControl());
+ }
+ };
+
+ private final @NonNull SurfaceView mSurfaceView;
+
+ private @Nullable SurfaceControlCallback mSurfaceControlCallback;
+
+ /**
+ * @inheritDoc
+ *
+ * @hide
+ */
+ public InlineContentView(@NonNull Context context) {
+ this(context, null);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @hide
+ */
+ public InlineContentView(@NonNull Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @hide
+ */
+ public InlineContentView(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ /**
+ * Gets the surface control. If the surface is not created this method
+ * returns {@code null}.
+ *
+ * @return The surface control.
+ *
+ * @see #setSurfaceControlCallback(SurfaceControlCallback)
+ */
+ public @Nullable SurfaceControl getSurfaceControl() {
+ return mSurfaceView.getSurfaceControl();
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @hide
+ */
+ public InlineContentView(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mSurfaceView = new SurfaceView(context, attrs, defStyleAttr, defStyleRes);
+ mSurfaceView.setZOrderOnTop(true);
+ mSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);
+ addView(mSurfaceView);
+ }
+
+ /**
+ * Sets the embedded UI.
+ * @param surfacePackage The embedded UI.
+ *
+ * @hide
+ */
+ public void setChildSurfacePackage(
+ @Nullable SurfaceControlViewHost.SurfacePackage surfacePackage) {
+ mSurfaceView.setChildSurfacePackage(surfacePackage);
+ }
+
+ @Override
+ public void onLayout(boolean changed, int l, int t, int r, int b) {
+ mSurfaceView.layout(l, t, r, b);
+ }
+
+ /**
+ * Sets a callback to observe the lifecycle of the surface control for
+ * managing the backing surface.
+ *
+ * @param callback The callback to set or {@code null} to clear.
+ */
+ public void setSurfaceControlCallback(@Nullable SurfaceControlCallback callback) {
+ if (mSurfaceControlCallback != null) {
+ mSurfaceView.getHolder().removeCallback(mSurfaceCallback);
+ }
+ mSurfaceControlCallback = callback;
+ if (mSurfaceControlCallback != null) {
+ mSurfaceView.getHolder().addCallback(mSurfaceCallback);
+ }
+ }
+
+ /**
+ * @return Whether the surface backing this view appears on top of its parent.
+ *
+ * @see #setZOrderedOnTop(boolean)
+ */
+ public boolean isZOrderedOnTop() {
+ return mSurfaceView.isZOrderedOnTop();
+ }
+
+ /**
+ * Controls whether the backing surface is placed on top of this view's window.
+ * Normally, it is placed on top of the window, to allow interaction
+ * with the inlined UI. Via this method, you can place the surface below the
+ * window. This means that all of the contents of the window this view is in
+ * will be visible on top of its surface.
+ *
+ * <p> The Z ordering can be changed dynamically if the backing surface is
+ * created, otherwise the ordering would be applied at surface construction time.
+ *
+ * @param onTop Whether to show the surface on top of this view's window.
+ *
+ * @see #isZOrderedOnTop()
+ */
+ public boolean setZOrderedOnTop(boolean onTop) {
+ return mSurfaceView.setZOrderedOnTop(onTop, /*allowDynamicChange*/ true);
+ }
+}
diff --git a/core/java/android/widget/inline/InlinePresentationSpec.aidl b/core/java/android/widget/inline/InlinePresentationSpec.aidl
new file mode 100644
index 0000000..c76ffe0
--- /dev/null
+++ b/core/java/android/widget/inline/InlinePresentationSpec.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.inline;
+
+parcelable InlinePresentationSpec;
diff --git a/core/java/android/widget/inline/InlinePresentationSpec.java b/core/java/android/widget/inline/InlinePresentationSpec.java
new file mode 100644
index 0000000..8867902
--- /dev/null
+++ b/core/java/android/widget/inline/InlinePresentationSpec.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.inline;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.Size;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * This class represents the presentation specification by which an inline suggestion
+ * should abide when constructing its UI. Since suggestions are inlined in a
+ * host application while provided by another source, they need to be consistent
+ * with the host's look at feel to allow building smooth and integrated UIs.
+ */
+@DataClass(genEqualsHashCode = true, genToString = true, genBuilder = true)
+public final class InlinePresentationSpec implements Parcelable {
+
+ /** The minimal size of the suggestion. */
+ @NonNull
+ private final Size mMinSize;
+ /** The maximal size of the suggestion. */
+ @NonNull
+ private final Size mMaxSize;
+
+ /**
+ * The extras encoding the UI style information. Defaults to {@code null} in which case the
+ * default system UI style will be used.
+ */
+ @Nullable
+ private final Bundle mStyle;
+
+ private static Bundle defaultStyle() {
+ return null;
+ }
+
+ /** @hide */
+ @DataClass.Suppress({"setMaxSize", "setMinSize"})
+ abstract static class BaseBuilder {
+ }
+
+
+
+ // Code below generated by codegen v1.0.15.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/widget/inline/InlinePresentationSpec.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ InlinePresentationSpec(
+ @NonNull Size minSize,
+ @NonNull Size maxSize,
+ @Nullable Bundle style) {
+ this.mMinSize = minSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMinSize);
+ this.mMaxSize = maxSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMaxSize);
+ this.mStyle = style;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The minimal size of the suggestion.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Size getMinSize() {
+ return mMinSize;
+ }
+
+ /**
+ * The maximal size of the suggestion.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Size getMaxSize() {
+ return mMaxSize;
+ }
+
+ /**
+ * The extras encoding the UI style information. Defaults to {@code null} in which case the
+ * default system UI style will be used.
+ */
+ @DataClass.Generated.Member
+ public @Nullable Bundle getStyle() {
+ return mStyle;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "InlinePresentationSpec { " +
+ "minSize = " + mMinSize + ", " +
+ "maxSize = " + mMaxSize + ", " +
+ "style = " + mStyle +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(InlinePresentationSpec other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ InlinePresentationSpec that = (InlinePresentationSpec) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && java.util.Objects.equals(mMinSize, that.mMinSize)
+ && java.util.Objects.equals(mMaxSize, that.mMaxSize)
+ && java.util.Objects.equals(mStyle, that.mStyle);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mMinSize);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mMaxSize);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mStyle);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mStyle != null) flg |= 0x4;
+ dest.writeByte(flg);
+ dest.writeSize(mMinSize);
+ dest.writeSize(mMaxSize);
+ if (mStyle != null) dest.writeBundle(mStyle);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ InlinePresentationSpec(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ Size minSize = (Size) in.readSize();
+ Size maxSize = (Size) in.readSize();
+ Bundle style = (flg & 0x4) == 0 ? null : in.readBundle();
+
+ this.mMinSize = minSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMinSize);
+ this.mMaxSize = maxSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMaxSize);
+ this.mStyle = style;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<InlinePresentationSpec> CREATOR
+ = new Parcelable.Creator<InlinePresentationSpec>() {
+ @Override
+ public InlinePresentationSpec[] newArray(int size) {
+ return new InlinePresentationSpec[size];
+ }
+
+ @Override
+ public InlinePresentationSpec createFromParcel(@NonNull android.os.Parcel in) {
+ return new InlinePresentationSpec(in);
+ }
+ };
+
+ /**
+ * A builder for {@link InlinePresentationSpec}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder extends BaseBuilder {
+
+ private @NonNull Size mMinSize;
+ private @NonNull Size mMaxSize;
+ private @Nullable Bundle mStyle;
+
+ private long mBuilderFieldsSet = 0L;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @param minSize
+ * The minimal size of the suggestion.
+ * @param maxSize
+ * The maximal size of the suggestion.
+ */
+ public Builder(
+ @NonNull Size minSize,
+ @NonNull Size maxSize) {
+ mMinSize = minSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMinSize);
+ mMaxSize = maxSize;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mMaxSize);
+ }
+
+ /**
+ * The extras encoding the UI style information. Defaults to {@code null} in which case the
+ * default system UI style will be used.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setStyle(@NonNull Bundle value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mStyle = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull InlinePresentationSpec build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mStyle = defaultStyle();
+ }
+ InlinePresentationSpec o = new InlinePresentationSpec(
+ mMinSize,
+ mMaxSize,
+ mStyle);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x8) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1585174247896L,
+ codegenVersion = "1.0.15",
+ sourceFile = "frameworks/base/core/java/android/widget/inline/InlinePresentationSpec.java",
+ inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nprivate final @android.annotation.Nullable android.os.Bundle mStyle\nprivate static android.os.Bundle defaultStyle()\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
index c535163..9fc0da8 100644
--- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
@@ -300,21 +300,7 @@
private boolean rebuildTab(ResolverListAdapter activeListAdapter, boolean doPostProcessing) {
UserHandle listUserHandle = activeListAdapter.getUserHandle();
- if (listUserHandle.equals(mWorkProfileUserHandle)
- && mInjector.isQuietModeEnabled(mWorkProfileUserHandle)) {
- DevicePolicyEventLogger
- .createEvent(DevicePolicyEnums.RESOLVER_EMPTY_STATE_WORK_APPS_DISABLED)
- .setStrings(getMetricsCategory())
- .write();
- showWorkProfileOffEmptyState(activeListAdapter,
- v -> {
- ProfileDescriptor descriptor = getItem(
- userHandleToPageIndex(activeListAdapter.getUserHandle()));
- showSpinner(descriptor.getEmptyStateView());
- mInjector.requestQuietModeEnabled(false, mWorkProfileUserHandle);
- });
- return false;
- }
+
if (UserHandle.myUserId() != listUserHandle.getIdentifier()) {
if (!mInjector.hasCrossProfileIntents(activeListAdapter.getIntents(),
UserHandle.myUserId(), listUserHandle.getIdentifier())) {
@@ -352,7 +338,65 @@
protected abstract void showNoWorkToPersonalIntentsEmptyState(
ResolverListAdapter activeListAdapter);
- void showNoAppsAvailableEmptyState(ResolverListAdapter listAdapter) {
+ /**
+ * The empty state screens are shown according to their priority:
+ * <ol>
+ * <li>(highest priority) cross-profile disabled by policy (handled in
+ * {@link #rebuildTab(ResolverListAdapter, boolean)})</li>
+ * <li>no apps available</li>
+ * <li>(least priority) work is off</li>
+ * </ol>
+ *
+ * The intention is to prevent the user from having to turn
+ * the work profile on if there will not be any apps resolved
+ * anyway.
+ */
+ void showEmptyResolverListEmptyState(ResolverListAdapter listAdapter) {
+ if (maybeShowWorkProfileOffEmptyState(listAdapter)) {
+ return;
+ }
+ maybeShowNoAppsAvailableEmptyState(listAdapter);
+ }
+
+ /**
+ * Returns {@code true} if the work profile off empty state screen is shown.
+ */
+ private boolean maybeShowWorkProfileOffEmptyState(ResolverListAdapter listAdapter) {
+ UserHandle listUserHandle = listAdapter.getUserHandle();
+ if (!listUserHandle.equals(mWorkProfileUserHandle)
+ || !mInjector.isQuietModeEnabled(mWorkProfileUserHandle)
+ || !hasResolvedAppsInWorkProfile(listAdapter)) {
+ return false;
+ }
+ DevicePolicyEventLogger
+ .createEvent(DevicePolicyEnums.RESOLVER_EMPTY_STATE_WORK_APPS_DISABLED)
+ .setStrings(getMetricsCategory())
+ .write();
+ showWorkProfileOffEmptyState(listAdapter,
+ v -> {
+ ProfileDescriptor descriptor = getItem(
+ userHandleToPageIndex(listAdapter.getUserHandle()));
+ showSpinner(descriptor.getEmptyStateView());
+ mInjector.requestQuietModeEnabled(false, mWorkProfileUserHandle);
+ });
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if there is at least one app resolved in the work profile,
+ * regardless of whether the work profile is enabled or not.
+ */
+ private boolean hasResolvedAppsInWorkProfile(ResolverListAdapter listAdapter) {
+ List<ResolverActivity.ResolvedComponentInfo> userStateIndependentWorkResolvers =
+ listAdapter.mResolverListController.getUserStateIndependentResolversAsUser(
+ listAdapter.getIntents(), mWorkProfileUserHandle);
+ return userStateIndependentWorkResolvers.stream()
+ .anyMatch(resolvedComponentInfo ->
+ resolvedComponentInfo.getResolveInfoAt(0).targetUserId
+ == UserHandle.USER_CURRENT);
+ }
+
+ private void maybeShowNoAppsAvailableEmptyState(ResolverListAdapter listAdapter) {
UserHandle listUserHandle = listAdapter.getUserHandle();
if (mWorkProfileUserHandle != null
&& (UserHandle.myUserId() == listUserHandle.getIdentifier()
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 2352180..f088ab3 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -994,8 +994,8 @@
if (isAutolaunching() || maybeAutolaunchActivity()) {
return;
}
- if (shouldShowEmptyState(listAdapter)) {
- mMultiProfilePagerAdapter.showNoAppsAvailableEmptyState(listAdapter);
+ if (isResolverListEmpty(listAdapter)) {
+ mMultiProfilePagerAdapter.showEmptyResolverListEmptyState(listAdapter);
} else {
mMultiProfilePagerAdapter.showListView(listAdapter);
}
@@ -1640,12 +1640,12 @@
private void setupViewVisibilities() {
ResolverListAdapter activeListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter();
- if (!shouldShowEmptyState(activeListAdapter)) {
+ if (!isResolverListEmpty(activeListAdapter)) {
addUseDifferentAppLabelIfNecessary(activeListAdapter);
}
}
- private boolean shouldShowEmptyState(ResolverListAdapter listAdapter) {
+ private boolean isResolverListEmpty(ResolverListAdapter listAdapter) {
int count = listAdapter.getUnfilteredCount();
return count == 0 && listAdapter.getPlaceholderCount() == 0;
}
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 51dce55..3f897a5 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -120,12 +120,32 @@
boolean shouldGetActivityMetadata,
List<Intent> intents,
UserHandle userHandle) {
+ int baseFlags = PackageManager.MATCH_DEFAULT_ONLY
+ | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
+ | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0);
+ return getResolversForIntentAsUserInternal(intents, userHandle, baseFlags);
+ }
+
+ /**
+ * Returns a list of resolved intents which is user state-independent. This means it will
+ * return the same results regardless of whether the {@code userHandle} user is disabled or not.
+ */
+ public List<ResolverActivity.ResolvedComponentInfo> getUserStateIndependentResolversAsUser(
+ List<Intent> intents,
+ UserHandle userHandle) {
+ int baseFlags = PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+ return getResolversForIntentAsUserInternal(intents, userHandle, baseFlags);
+ }
+
+ private List<ResolverActivity.ResolvedComponentInfo> getResolversForIntentAsUserInternal(
+ List<Intent> intents,
+ UserHandle userHandle,
+ int baseFlags) {
List<ResolverActivity.ResolvedComponentInfo> resolvedComponents = null;
for (int i = 0, N = intents.size(); i < N; i++) {
final Intent intent = intents.get(i);
- int flags = PackageManager.MATCH_DEFAULT_ONLY
- | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
- | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0);
+ int flags = baseFlags;
if (intent.isWebIntent()
|| (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
flags |= PackageManager.MATCH_INSTANT;
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index c758989..ff03f1a 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -205,15 +205,9 @@
/** List of packages with the same uid, and its app data info: volume uuid and inode. */
public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map";
- /** List of whitelisted packages and its app data info: volume uuid and inode. */
- public static final String WHITELISTED_DATA_INFO_MAP = "--whitelisted-data-info-map";
-
/** Bind mount app storage dirs to lower fs not via fuse */
public static final String BIND_MOUNT_APP_STORAGE_DIRS = "--bind-mount-storage-dirs";
- /** Bind mount app storage dirs to lower fs not via fuse */
- public static final String BIND_MOUNT_APP_DATA_DIRS = "--bind-mount-data-dirs";
-
/**
* An extraArg passed when a zygote process is forking a child-zygote, specifying a name
* in the abstract socket namespace. This socket name is what the new child zygote
@@ -319,8 +313,6 @@
* @param isTopApp true if the process is for top (high priority) application.
* @param pkgDataInfoList A list that stores related packages and its app data
* info: volume uuid and inode.
- * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps.
- * @param bindMountAppDataDirs True if the zygote needs to mount data dirs.
* @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs.
*
* @return 0 if this is the child, pid of the child
@@ -329,15 +321,13 @@
static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
- boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList,
- boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
+ boolean isTopApp, String[] pkgDataInfoList, boolean bindMountAppStorageDirs) {
ZygoteHooks.preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
- pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs,
- bindMountAppStorageDirs);
+ pkgDataInfoList, bindMountAppStorageDirs);
if (pid == 0) {
// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -354,7 +344,6 @@
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
String appDataDir, boolean isTopApp, String[] pkgDataInfoList,
- String[] whitelistedDataInfoList, boolean bindMountAppDataDirs,
boolean bindMountAppStorageDirs);
/**
@@ -382,19 +371,15 @@
* volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name,
* app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid,
* app_b_ce_inode, ...];
- * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps.
- * @param bindMountAppDataDirs True if the zygote needs to mount data dirs.
* @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs.
*/
private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
- String[] pkgDataInfoList, String[] whitelistedDataInfoList,
- boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
+ String[] pkgDataInfoList, boolean bindMountAppStorageDirs) {
nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
niceName, startChildZygote, instructionSet, appDataDir, isTopApp,
- pkgDataInfoList, whitelistedDataInfoList,
- bindMountAppDataDirs, bindMountAppStorageDirs);
+ pkgDataInfoList, bindMountAppStorageDirs);
// Note that this event ends at the end of handleChildProc.
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -414,8 +399,7 @@
private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
- String[] pkgDataInfoList, String[] whitelistedDataInfoList,
- boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs);
+ String[] pkgDataInfoList, boolean bindMountAppStorageDirs);
/**
* Called to do any initialization before starting an application.
@@ -740,8 +724,7 @@
args.mRuntimeFlags, rlimits, args.mMountExternal,
args.mSeInfo, args.mNiceName, args.mStartChildZygote,
args.mInstructionSet, args.mAppDataDir, args.mIsTopApp,
- args.mPkgDataInfoList, args.mWhitelistedDataInfoList,
- args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs);
+ args.mPkgDataInfoList, args.mBindMountAppStorageDirs);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 94c1f71..1a63765 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -227,22 +227,11 @@
String[] mPkgDataInfoList;
/**
- * A list that stores all whitelisted app data info: volume uuid and inode.
- * Null if it does need to do app data isolation.
- */
- String[] mWhitelistedDataInfoList;
-
- /**
* @see Zygote#BIND_MOUNT_APP_STORAGE_DIRS
*/
boolean mBindMountAppStorageDirs;
/**
- * @see Zygote#BIND_MOUNT_APP_DATA_DIRS
- */
- boolean mBindMountAppDataDirs;
-
- /**
* Constructs instance and parses args
*
* @param args zygote command-line args
@@ -463,12 +452,8 @@
}
} else if (arg.startsWith(Zygote.PKG_DATA_INFO_MAP)) {
mPkgDataInfoList = getAssignmentList(arg);
- } else if (arg.startsWith(Zygote.WHITELISTED_DATA_INFO_MAP)) {
- mWhitelistedDataInfoList = getAssignmentList(arg);
} else if (arg.equals(Zygote.BIND_MOUNT_APP_STORAGE_DIRS)) {
mBindMountAppStorageDirs = true;
- } else if (arg.equals(Zygote.BIND_MOUNT_APP_DATA_DIRS)) {
- mBindMountAppDataDirs = true;
} else {
break;
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 6e880d4..bc8dfd4 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -258,8 +258,7 @@
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
- parsedArgs.mPkgDataInfoList,parsedArgs.mWhitelistedDataInfoList,
- parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
+ parsedArgs.mPkgDataInfoList, parsedArgs.mBindMountAppStorageDirs);
try {
if (pid == 0) {
diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java
index 99b4b5f..f007768 100644
--- a/core/java/com/android/internal/policy/DecorContext.java
+++ b/core/java/com/android/internal/policy/DecorContext.java
@@ -41,17 +41,17 @@
public class DecorContext extends ContextThemeWrapper {
private PhoneWindow mPhoneWindow;
private WindowManager mWindowManager;
- private Resources mActivityResources;
+ private Resources mResources;
private ContentCaptureManager mContentCaptureManager;
- private WeakReference<Context> mActivityContext;
+ private WeakReference<Context> mContext;
// TODO(b/149928768): Non-activity context can be passed.
@VisibleForTesting
- public DecorContext(Context context, Context activityContext) {
- super(context.createDisplayContext(activityContext.getDisplayNoVerify()), null);
- mActivityContext = new WeakReference<>(activityContext);
- mActivityResources = activityContext.getResources();
+ public DecorContext(Context baseContext, Context context) {
+ super(baseContext.createDisplayContext(context.getDisplayNoVerify()), null);
+ mContext = new WeakReference<>(context);
+ mResources = context.getResources();
}
void setPhoneWindow(PhoneWindow phoneWindow) {
@@ -61,58 +61,56 @@
@Override
public Object getSystemService(String name) {
+ final Context context = mContext.get();
if (Context.WINDOW_SERVICE.equals(name)) {
- if (mWindowManager == null) {
- WindowManagerImpl wm =
- (WindowManagerImpl) super.getSystemService(Context.WINDOW_SERVICE);
+ if (context != null && mWindowManager == null) {
+ WindowManagerImpl wm = (WindowManagerImpl) context.getSystemService(name);
mWindowManager = wm.createLocalWindowManager(mPhoneWindow);
}
return mWindowManager;
}
if (Context.CONTENT_CAPTURE_MANAGER_SERVICE.equals(name)) {
- if (mContentCaptureManager == null) {
- Context activityContext = mActivityContext.get();
- if (activityContext != null) {
- mContentCaptureManager = (ContentCaptureManager) activityContext
- .getSystemService(name);
- }
+ if (context != null && mContentCaptureManager == null) {
+ mContentCaptureManager = (ContentCaptureManager) context.getSystemService(name);
}
return mContentCaptureManager;
}
- return super.getSystemService(name);
+ // LayoutInflater and WallpaperManagerService should also be obtained from context
+ // instead of application context.
+ return (context != null) ? context.getSystemService(name) : super.getSystemService(name);
}
@Override
public Resources getResources() {
- Context activityContext = mActivityContext.get();
+ Context context = mContext.get();
// Attempt to update the local cached Resources from the activity context. If the activity
// is no longer around, return the old cached values.
- if (activityContext != null) {
- mActivityResources = activityContext.getResources();
+ if (context != null) {
+ mResources = context.getResources();
}
- return mActivityResources;
+ return mResources;
}
@Override
public AssetManager getAssets() {
- return mActivityResources.getAssets();
+ return mResources.getAssets();
}
@Override
public AutofillOptions getAutofillOptions() {
- Context activityContext = mActivityContext.get();
- if (activityContext != null) {
- return activityContext.getAutofillOptions();
+ Context context = mContext.get();
+ if (context != null) {
+ return context.getAutofillOptions();
}
return null;
}
@Override
public ContentCaptureOptions getContentCaptureOptions() {
- Context activityContext = mActivityContext.get();
- if (activityContext != null) {
- return activityContext.getContentCaptureOptions();
+ Context context = mContext.get();
+ if (context != null) {
+ return context.getContentCaptureOptions();
}
return null;
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 51b73fc..71cf5ca 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -78,7 +78,6 @@
import android.view.Gravity;
import android.view.InputQueue;
import android.view.InsetsState;
-import android.view.InsetsController;
import android.view.InsetsState.InternalInsetsType;
import android.view.KeyEvent;
import android.view.KeyboardShortcutGroup;
@@ -121,6 +120,7 @@
import com.android.internal.widget.FloatingToolbar;
import java.util.List;
+import java.util.function.Function;
/** @hide */
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
@@ -1102,7 +1102,6 @@
int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
final WindowInsetsController controller = getWindowInsetsController();
- final InsetsState state = controller != null ? controller.getState() : null;
// IME is an exceptional floating window that requires color view.
final boolean isImeWindow =
@@ -1152,7 +1151,7 @@
calculateNavigationBarColor(), mWindow.mNavigationBarDividerColor, navBarSize,
navBarToRightEdge || navBarToLeftEdge, navBarToLeftEdge,
0 /* sideInset */, animate && !disallowAnimate,
- mForceWindowDrawsBarBackgrounds, state);
+ mForceWindowDrawsBarBackgrounds, controller);
boolean oldDrawLegacy = mDrawLegacyNavigationBarBackground;
mDrawLegacyNavigationBarBackground = mNavigationColorViewState.visible
&& (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0;
@@ -1173,7 +1172,13 @@
calculateStatusBarColor(), 0, mLastTopInset,
false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
animate && !disallowAnimate,
- mForceWindowDrawsBarBackgrounds, state);
+ mForceWindowDrawsBarBackgrounds, controller);
+
+ if (mHasCaption) {
+ final int captionColor = calculateStatusBarColor();
+ mDecorCaptionView.getCaption().setBackgroundColor(captionColor);
+ updateDecorCaptionShade();
+ }
}
// When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or
@@ -1188,7 +1193,7 @@
// SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION to indicate whether the app wants to handle it by
// themselves.
boolean hideNavigation = (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
- || !(state == null || state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
+ || !(controller == null || controller.isRequestedVisible(ITYPE_NAVIGATION_BAR));
boolean forceConsumingNavBar = (mForceWindowDrawsBarBackgrounds
&& (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
&& (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
@@ -1209,7 +1214,7 @@
// fullscreen, as othrewise we can expect the app to handle it.
boolean fullscreen = (sysUiVisibility & SYSTEM_UI_FLAG_FULLSCREEN) != 0
|| (attrs.flags & FLAG_FULLSCREEN) != 0
- || !(state == null || state.getSource(ITYPE_STATUS_BAR).isVisible());
+ || !(controller == null || controller.isRequestedVisible(ITYPE_STATUS_BAR));
boolean consumingStatusBar = (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0
&& (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0
&& (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0
@@ -1349,13 +1354,15 @@
*/
private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
int dividerColor, int size, boolean verticalBar, boolean seascape, int sideMargin,
- boolean animate, boolean force, InsetsState insetsState) {
+ boolean animate, boolean force, WindowInsetsController controller) {
state.present = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
? state.attributes.isPresent(sysUiVis, mWindow.getAttributes().flags, force)
- : state.attributes.isPresent(insetsState, mWindow.getAttributes().flags, force);
+ : state.attributes.isPresent(
+ controller.isRequestedVisible(state.attributes.insetsType),
+ mWindow.getAttributes().flags, force);
boolean show = state.attributes.isVisible(state.present, color,
mWindow.getAttributes().flags, force);
- boolean showView = show && !isResizing() && size > 0;
+ boolean showView = show && !isResizing() && !mHasCaption && size > 0;
boolean visibilityChanged = false;
View view = state.view;
@@ -2021,6 +2028,7 @@
if (getForeground() != null) {
drawableChanged();
}
+ getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight());
}
}
@@ -2094,6 +2102,7 @@
mDecorCaptionView.onConfigurationChanged(displayWindowDecor);
enableCaption(displayWindowDecor);
}
+ getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight());
}
void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
@@ -2182,11 +2191,11 @@
inflater = inflater.from(context);
final DecorCaptionView view = (DecorCaptionView) inflater.inflate(R.layout.decor_caption,
null);
- setDecorCaptionShade(context, view);
+ setDecorCaptionShade(view);
return view;
}
- private void setDecorCaptionShade(Context context, DecorCaptionView view) {
+ private void setDecorCaptionShade(DecorCaptionView view) {
final int shade = mWindow.getDecorCaptionShade();
switch (shade) {
case DECOR_CAPTION_SHADE_LIGHT:
@@ -2196,15 +2205,10 @@
setDarkDecorCaptionShade(view);
break;
default: {
- TypedValue value = new TypedValue();
- context.getTheme().resolveAttribute(R.attr.colorPrimary, value, true);
- // We invert the shade depending on brightness of the theme. Dark shade for light
- // theme and vice versa. Thanks to this the buttons should be visible on the
- // background.
- if (Color.luminance(value.data) < 0.5) {
- setLightDecorCaptionShade(view);
- } else {
+ if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0) {
setDarkDecorCaptionShade(view);
+ } else {
+ setLightDecorCaptionShade(view);
}
break;
}
@@ -2213,7 +2217,7 @@
void updateDecorCaptionShade() {
if (mDecorCaptionView != null) {
- setDecorCaptionShade(getContext(), mDecorCaptionView);
+ setDecorCaptionShade(mDecorCaptionView);
}
}
@@ -2484,6 +2488,15 @@
}
/**
+ * @hide
+ * @return the height of insets covering the top of window content area.
+ */
+ public int getCaptionInsetsHeight() {
+ if (!mWindow.isOverlayWithDecorCaptionEnabled()) return 0;
+ return getCaptionHeight();
+ }
+
+ /**
* Converts a DIP measure into physical pixels.
* @param dip The dip value.
* @return Returns the number of pixels.
@@ -2613,8 +2626,8 @@
|| force);
}
- public boolean isPresent(InsetsState state, int windowFlags, boolean force) {
- return (state == null || state.getSource(insetsType).isVisible())
+ public boolean isPresent(boolean requestedVisible, int windowFlags, boolean force) {
+ return requestedVisible
&& ((windowFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 || force);
}
@@ -2631,7 +2644,8 @@
}
public boolean isVisible(InsetsState state, int color, int windowFlags, boolean force) {
- final boolean present = isPresent(state, windowFlags, force);
+ final boolean present = isPresent(state.getSource(insetsType).isVisible(), windowFlags,
+ force);
return isVisible(present, color, windowFlags, force);
}
}
diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java
index b5d787c2..7a01024 100644
--- a/core/java/com/android/internal/widget/DecorCaptionView.java
+++ b/core/java/com/android/internal/widget/DecorCaptionView.java
@@ -17,7 +17,6 @@
package com.android.internal.widget;
import android.content.Context;
-import android.graphics.Color;
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.AttributeSet;
@@ -53,8 +52,7 @@
* <li>..</li>
* </ul>
*
- * Although this ViewGroup has only two direct sub-Views, its behavior is more complex due to
- * overlaying caption on the content and drawing.
+ * Here describe the behavior of overlaying caption on the content and drawing.
*
* First, no matter where the content View gets added, it will always be the first child and the
* caption will be the second. This way the caption will always be drawn on top of the content when
@@ -66,11 +64,9 @@
* <li>DecorCaptionView.onInterceptTouchEvent() will try intercepting the touch events if the
* down action is performed on top close or maximize buttons; the reason for that is we want these
* buttons to always work.</li>
- * <li>The content View will receive the touch event. Mind that content is actually underneath the
- * caption, so we need to introduce our own dispatch ordering. We achieve this by overriding
- * {@link #buildTouchDispatchChildList()}.</li>
- * <li>If the touch event is not consumed by the content View, it will go to the caption View
- * and the dragging logic will be executed.</li>
+ * <li>The caption view will try to consume the event to apply the dragging logic.</li>
+ * <li>If the touch event is not consumed by the caption, the content View will receive the touch
+ * event</li>
* </ul>
*/
public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
@@ -137,11 +133,6 @@
mOwner = owner;
mShow = show;
mOverlayWithAppContent = owner.isOverlayWithDecorCaptionEnabled();
- if (mOverlayWithAppContent) {
- // The caption is covering the content, so we make its background transparent to make
- // the content visible.
- mCaption.setBackgroundColor(Color.TRANSPARENT);
- }
updateCaptionVisibility();
// By changing the outline provider to BOUNDS, the window can remove its
// background without removing the shadow.
@@ -236,18 +227,6 @@
}
@Override
- public ArrayList<View> buildTouchDispatchChildList() {
- mTouchDispatchList.ensureCapacity(3);
- if (mCaption != null) {
- mTouchDispatchList.add(mCaption);
- }
- if (mContent != null) {
- mTouchDispatchList.add(mContent);
- }
- return mTouchDispatchList;
- }
-
- @Override
public boolean shouldDelayChildPressedState() {
return false;
}
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index cb5a332..bf3fc57 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -214,12 +214,8 @@
// ----------------------------------------------------------------------------
-static std::unique_ptr<DynamicLibManager> sDynamicLibManager =
- std::make_unique<DynamicLibManager>();
-
// Let the opaque type AAssetManager refer to a guarded AssetManager2 instance.
struct GuardedAssetManager : public ::AAssetManager {
- GuardedAssetManager() : guarded_assetmanager(sDynamicLibManager.get()) {}
Guarded<AssetManager2> guarded_assetmanager;
};
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index aa2d1b5..ea3c0fa 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -110,6 +110,7 @@
using android::base::StringPrintf;
using android::base::WriteStringToFile;
using android::base::GetBoolProperty;
+using android::base::GetProperty;
#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
append(StringPrintf(__VA_ARGS__))
@@ -169,6 +170,18 @@
static constexpr int DEFAULT_DATA_DIR_PERMISSION = 0751;
+/**
+ * Property to control if app data isolation is enabled.
+ */
+static const std::string ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
+ "persist.zygote.app_data_isolation";
+
+/**
+ * Property to enable app data isolation for sdcard obb or data in vold.
+ */
+static const std::string ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
+ "persist.sys.vold_app_data_isolation_enabled";
+
static constexpr const uint64_t UPPER_HALF_WORD_MASK = 0xFFFF'FFFF'0000'0000;
static constexpr const uint64_t LOWER_HALF_WORD_MASK = 0x0000'0000'FFFF'FFFF;
@@ -1306,13 +1319,20 @@
* be decrypted after storage is decrypted.
*
*/
-static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_data_info_list,
- uid_t uid, const char* process_name,
- jstring managed_nice_name, fail_fn_t fail_fn) {
+static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
+ uid_t uid, const char* process_name, jstring managed_nice_name,
+ fail_fn_t fail_fn) {
const userid_t userId = multiuser_get_user_id(uid);
- int size = merged_data_info_list.size();
+ auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
+
+ int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
+ // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
+ if ((size % 3) != 0) {
+ fail_fn(CREATE_ERROR("Wrong pkg_inode_list size %d", size));
+ }
+ ensureInAppMountNamespace(fail_fn);
// Mount tmpfs on all possible data directories, so app no longer see the original apps data.
char internalCePath[PATH_MAX];
@@ -1357,10 +1377,14 @@
bool legacySymlinkCreated = false;
for (int i = 0; i < size; i += 3) {
- std::string const & packageName = merged_data_info_list[i];
- std::string const & volUuid = merged_data_info_list[i + 1];
- std::string const & inode = merged_data_info_list[i + 2];
+ jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i));
+ std::string packageName = extract_fn(package_str).value();
+ jstring vol_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 1));
+ std::string volUuid = extract_fn(vol_str).value();
+
+ jstring inode_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 2));
+ std::string inode = extract_fn(inode_str).value();
std::string::size_type sz;
long long ceDataInode = std::stoll(inode, &sz);
@@ -1458,48 +1482,6 @@
freecon(dataDataContext);
}
-static void insertPackagesToMergedList(JNIEnv* env,
- std::vector<std::string>& merged_data_info_list,
- jobjectArray data_info_list, const char* process_name,
- jstring managed_nice_name, fail_fn_t fail_fn) {
-
- auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
-
- int size = (data_info_list != nullptr) ? env->GetArrayLength(data_info_list) : 0;
- // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
- if ((size % 3) != 0) {
- fail_fn(CREATE_ERROR("Wrong data_info_list size %d", size));
- }
-
- for (int i = 0; i < size; i += 3) {
- jstring package_str = (jstring) (env->GetObjectArrayElement(data_info_list, i));
- std::string packageName = extract_fn(package_str).value();
- merged_data_info_list.push_back(packageName);
-
- jstring vol_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 1));
- std::string volUuid = extract_fn(vol_str).value();
- merged_data_info_list.push_back(volUuid);
-
- jstring inode_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 2));
- std::string inode = extract_fn(inode_str).value();
- merged_data_info_list.push_back(inode);
- }
-}
-
-static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
- jobjectArray whitelisted_data_info_list, uid_t uid, const char* process_name,
- jstring managed_nice_name, fail_fn_t fail_fn) {
-
- ensureInAppMountNamespace(fail_fn);
- std::vector<std::string> merged_data_info_list;
- insertPackagesToMergedList(env, merged_data_info_list, pkg_data_info_list,
- process_name, managed_nice_name, fail_fn);
- insertPackagesToMergedList(env, merged_data_info_list, whitelisted_data_info_list,
- process_name, managed_nice_name, fail_fn);
-
- isolateAppData(env, merged_data_info_list, uid, process_name, managed_nice_name, fail_fn);
-}
-
/**
* Like isolateAppData(), isolate jit profile directories, so apps don't see what
* other apps are installed by reading content inside /data/misc/profiles/cur.
@@ -1612,9 +1594,7 @@
jstring managed_nice_name, bool is_system_server,
bool is_child_zygote, jstring managed_instruction_set,
jstring managed_app_data_dir, bool is_top_app,
- jobjectArray pkg_data_info_list,
- jobjectArray whitelisted_data_info_list,
- bool mount_data_dirs, bool mount_storage_dirs) {
+ jobjectArray pkg_data_info_list, bool mount_storage_dirs) {
const char* process_name = is_system_server ? "system_server" : "zygote";
auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
@@ -1648,9 +1628,9 @@
// give a null in same_uid_pkgs and private_volumes so they don't need app data isolation.
// Isolated process / webview / app zygote should be gated by SELinux and file permission
// so they can't even traverse CE / DE directories.
- if (mount_data_dirs) {
- isolateAppData(env, pkg_data_info_list, whitelisted_data_info_list,
- uid, process_name, managed_nice_name, fail_fn);
+ if (pkg_data_info_list != nullptr
+ && GetBoolProperty(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true)) {
+ isolateAppData(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
}
if ((mount_external != MOUNT_EXTERNAL_INSTALLER) && mount_storage_dirs) {
@@ -2023,8 +2003,7 @@
jint mount_external, jstring se_info, jstring nice_name,
jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
- jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
- jboolean mount_data_dirs, jboolean mount_storage_dirs) {
+ jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
if (UNLIKELY(managed_fds_to_close == nullptr)) {
@@ -2062,8 +2041,6 @@
mount_external, se_info, nice_name, false,
is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
is_top_app == JNI_TRUE, pkg_data_info_list,
- whitelisted_data_info_list,
- mount_data_dirs == JNI_TRUE,
mount_storage_dirs == JNI_TRUE);
}
return pid;
@@ -2099,8 +2076,7 @@
permitted_capabilities, effective_capabilities,
MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
false, nullptr, nullptr, /* is_top_app= */ false,
- /* pkg_data_info_list */ nullptr,
- /* whitelisted_data_info_list */ nullptr, false, false);
+ /* pkg_data_info_list */ nullptr, false);
} else if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
@@ -2230,16 +2206,15 @@
jint runtime_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring nice_name,
jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
- jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
- jboolean mount_data_dirs, jboolean mount_storage_dirs) {
+ jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
capabilities, capabilities,
mount_external, se_info, nice_name, false,
is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
- is_top_app == JNI_TRUE, pkg_data_info_list, whitelisted_data_info_list,
- mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE);
+ is_top_app == JNI_TRUE, pkg_data_info_list,
+ mount_storage_dirs == JNI_TRUE);
}
/**
@@ -2433,7 +2408,7 @@
static const JNINativeMethod gMethods[] = {
{"nativeForkAndSpecialize",
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/"
- "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)I",
+ "String;Z[Ljava/lang/String;Z)I",
(void*)com_android_internal_os_Zygote_nativeForkAndSpecialize},
{"nativeForkSystemServer", "(II[II[[IJJ)I",
(void*)com_android_internal_os_Zygote_nativeForkSystemServer},
@@ -2446,7 +2421,7 @@
{"nativeForkUsap", "(II[IZ)I", (void*)com_android_internal_os_Zygote_nativeForkUsap},
{"nativeSpecializeAppProcess",
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/"
- "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)V",
+ "String;Z[Ljava/lang/String;Z)V",
(void*)com_android_internal_os_Zygote_nativeSpecializeAppProcess},
{"nativeInitNativeState", "(Z)V",
(void*)com_android_internal_os_Zygote_nativeInitNativeState},
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index d09273c..075aa97 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -180,6 +180,14 @@
optional SettingProto cmas_additional_broadcast_pkg = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
repeated SettingProto completed_categories = 15;
optional SettingProto connectivity_release_pending_intent_delay_ms = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Controls {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Controls controls = 79;
+
optional SettingProto device_paired = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto dialer_default_application = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto display_density_forced = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
@@ -580,5 +588,5 @@
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 79;
+ // Next tag = 80;
}
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 2a41542..2a2da6a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2116,35 +2116,6 @@
<declare-styleable name="AndroidManifestQueriesProvider" parent="AndroidManifestQueries" >
<attr name="authorities" />
</declare-styleable>
- <!--
- Matches an overlayable, its overlays, its actor, and/or its containing target.
- A target or actor must always be specified, but can be combined for more specificity.
- Valid combinations and what they match are:
-
- targetPackage:
- - All overlays targeting any overlayables inside 'targetPackage'
-
- targetPackage + targetName:
- - All overlays targeting the overlayable 'targetName' inside 'targetPackage'
-
- targetPackage + targetName + actor:
- - All overlays targeting the overlayable 'targetName' inside 'targetPackage' if the
- overlayable specifies 'actor'
-
- targetPackage + actor:
- - All overlays targeting overlayables inside 'targetPackage' that specify `actor`
- - The actor itself if the above matches
-
- actor:
- - All overlays targeting overlayables that specify `actor`
- - All targets that contain an overlayable that specifies `actor`
- - The actor itself
- -->
- <declare-styleable name="AndroidManifestQueriesOverlayable">
- <attr name="targetPackage" />
- <attr name="targetName"/>
- <attr name="actor" format="string" />
- </declare-styleable>
<!-- The <code>static-library</code> tag declares that this apk is providing itself
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 28dcc2f..4c4b7e6 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2406,8 +2406,7 @@
- to henceforth disable feature and try to undo its previous effects: 0
Note: This list must be kept current with PACKAGE_WHITELIST_MODE_PROP in
frameworks/base/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java -->
- <integer name="config_userTypePackageWhitelistMode">29</integer> <!-- 1+4+8+16 -->
- <!-- TODO(b/143200798): Change to value 13, i.e. 1+4+8, when b/143200798 is resolved. -->
+ <integer name="config_userTypePackageWhitelistMode">13</integer> <!-- 1+4+8 -->
<!-- Whether UI for multi user should be shown -->
<bool name="config_enableMultiUserUI">false</bool>
@@ -2779,6 +2778,10 @@
<string name="config_systemUIServiceComponent" translatable="false"
>com.android.systemui/com.android.systemui.SystemUIService</string>
+ <!-- Package handling Quick controls -->
+ <string name="config_controlsPackage" translatable="false"
+ >com.android.systemui</string>
+
<!-- Keyguard component -->
<string name="config_keyguardComponent" translatable="false"
>com.android.systemui/com.android.systemui.keyguard.KeyguardService</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 738688b..67d20da 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3020,7 +3020,6 @@
<public name="preserveLegacyExternalStorage" />
<public name="mimeGroup" />
<public name="gwpAsanMode" />
- <public name="actor" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5b88036..e2e65dd 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1138,17 +1138,17 @@
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessFineLocation">access precise location only in the foreground</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_accessFineLocation">This app can get your exact location only when it is in the foreground. Location services must be turned on and available on your device for the app to be able to use them. This may increase battery consumption.</string>
+ <string name="permdesc_accessFineLocation">This app can get your precise location from location services while the app is in use. Location services for your device must be turned on for the app to get location. This may increase battery usage.</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_accessCoarseLocation">access approximate location only in the foreground</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_accessCoarseLocation">This app can get your approximate location only when it is in the foreground. Location services must be turned on and available on your device for the app to be able to use them.</string>
+ <string name="permdesc_accessCoarseLocation">This app can get your approximate location from location services while the app is in use. Location services for your device must be turned on for the app to get location.</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_accessBackgroundLocation">access location in the background</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_accessBackgroundLocation">This app can access location while running in the background, in addition to foreground location access.</string>
+ <string name="permdesc_accessBackgroundLocation">This app can access location at any time, even while the app is not in use.</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_modifyAudioSettings">change your audio settings</string>
@@ -3597,6 +3597,8 @@
<string name="ext_media_new_notification_title">New <xliff:g id="name" example="SD card">%s</xliff:g></string>
<!-- Notification body when new external media is detected [CHAR LIMIT=NONE] -->
<string name="ext_media_new_notification_message">Tap to set up</string>
+ <!-- Automotive specific notification body when new external media is detected. Empty because there is no fix action (b/151671685) [CHAR LIMIT=NONE] -->
+ <string name="ext_media_new_notification_message" product="automotive"></string>
<!-- Notification body when external media is ready for use [CHAR LIMIT=NONE] -->
<string name="ext_media_ready_notification_message">For transferring photos and media</string>
@@ -3605,8 +3607,10 @@
<string name="ext_media_unmountable_notification_title">Issue with <xliff:g id="name" example="SD card">%s</xliff:g></string>
<!-- Notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
<string name="ext_media_unmountable_notification_message">Tap to fix</string>
- <!-- TV-specifiv notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
+ <!-- TV-specific notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
<string name="ext_media_unmountable_notification_message" product="tv"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Select to fix.</string>
+ <!-- Automotive specific notification body when external media is unmountable (corrupt). Empty because there is no fix action (b/151671685) [CHAR LIMIT=NONE] -->
+ <string name="ext_media_unmountable_notification_message" product="automotive"></string>
<!-- Notification title when external media is unsupported [CHAR LIMIT=30] -->
<string name="ext_media_unsupported_notification_title">Unsupported <xliff:g id="name" example="SD card">%s</xliff:g></string>
@@ -3614,6 +3618,8 @@
<string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Tap to set up in a supported format.</string>
<!-- TV-specific notification body when external media is unsupported [CHAR LIMIT=NONE] -->
<string name="ext_media_unsupported_notification_message" product="tv">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Select to set up in a supported format.</string>
+ <!-- Automotive specific notification body when external media is unsupported. No action is specified to fix (b/151671685) [CHAR LIMIT=NONE] -->
+ <string name="ext_media_unsupported_notification_message" product="automotive">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>.</string>
<!-- Notification title when external media is unsafely removed [CHAR LIMIT=30] -->
<string name="ext_media_badremoval_notification_title"><xliff:g id="name" example="SD card">%s</xliff:g> unexpectedly removed</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 646ffab..04c6a41 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -365,6 +365,7 @@
<java-symbol type="bool" name="config_hasRecents" />
<java-symbol type="string" name="config_recentsComponentName" />
<java-symbol type="string" name="config_systemUIServiceComponent" />
+ <java-symbol type="string" name="config_controlsPackage" />
<java-symbol type="string" name="config_screenRecorderComponent" />
<java-symbol type="string" name="config_somnambulatorComponent" />
<java-symbol type="string" name="config_screenshotServiceComponent" />
diff --git a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
index 13000e9..f4ebe2f 100644
--- a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
+++ b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
@@ -64,8 +64,7 @@
@RunWith(AndroidJUnit4.class)
public class ControlProviderServiceTest {
- private static final ComponentName TEST_SYSUI_COMPONENT =
- ComponentName.unflattenFromString("sysui/.test.cls");
+ private static final String TEST_CONTROLS_PACKAGE = "sysui";
private static final ComponentName TEST_COMPONENT =
ComponentName.unflattenFromString("test.pkg/.test.cls");
@@ -97,8 +96,8 @@
when(mSubscriber.asBinder()).thenCallRealMethod();
when(mSubscriber.queryLocalInterface(any())).thenReturn(mSubscriber);
- when(mResources.getString(com.android.internal.R.string.config_systemUIServiceComponent))
- .thenReturn(TEST_SYSUI_COMPONENT.flattenToString());
+ when(mResources.getString(com.android.internal.R.string.config_controlsPackage))
+ .thenReturn(TEST_CONTROLS_PACKAGE);
when(mContext.getResources()).thenReturn(mResources);
Bundle b = new Bundle();
@@ -252,7 +251,7 @@
eq(Manifest.permission.BIND_CONTROLS));
Intent intent = mIntentArgumentCaptor.getValue();
assertEquals(ControlsProviderService.ACTION_ADD_CONTROL, intent.getAction());
- assertEquals(TEST_SYSUI_COMPONENT.getPackageName(), intent.getPackage());
+ assertEquals(TEST_CONTROLS_PACKAGE, intent.getPackage());
assertEquals(TEST_COMPONENT, intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME));
assertTrue(equals(control,
intent.getParcelableExtra(ControlsProviderService.EXTRA_CONTROL)));
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index efdb51d..cbb379b 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -21,6 +21,7 @@
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
@@ -88,7 +89,6 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class InsetsControllerTest {
-
private InsetsController mController;
private SurfaceSession mSession = new SurfaceSession();
private SurfaceControl mLeash;
@@ -665,6 +665,26 @@
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
+ @Test
+ public void testCaptionInsetsStateAssemble() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ mController.onFrameChanged(new Rect(0, 0, 100, 300));
+ final InsetsState state = new InsetsState(mController.getState(), true);
+ final Rect captionFrame = new Rect(0, 0, 100, 100);
+ mController.setCaptionInsetsHeight(100);
+ mController.onStateChanged(state);
+ final InsetsState currentState = new InsetsState(mController.getState());
+ // The caption bar source should be synced with the info in mAttachInfo.
+ assertEquals(captionFrame, currentState.peekSource(ITYPE_CAPTION_BAR).getFrame());
+ assertTrue(currentState.equals(state, true /* excludingCaptionInsets*/));
+ mController.setCaptionInsetsHeight(0);
+ mController.onStateChanged(state);
+ // The caption bar source should not be there at all, because we don't add empty
+ // caption to the state from the server.
+ assertNull(mController.getState().peekSource(ITYPE_CAPTION_BAR));
+ });
+ }
+
private void waitUntilNextFrame() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 721dc98..2884777 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -153,6 +153,35 @@
}
}
+
+ @Test
+ public void testCalculateInsets_captionStatusBarOverlap() throws Exception {
+ try (InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
+ mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
+
+ Rect visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 100, 400), SOFT_INPUT_ADJUST_NOTHING);
+ assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
+ }
+ }
+
+ @Test
+ public void testCalculateInsets_captionBarOffset() throws Exception {
+ try (InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
+ mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
+
+ Rect visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 150, 400), SOFT_INPUT_ADJUST_NOTHING);
+ assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
+ }
+ }
+
@Test
public void testStripForDispatch() {
mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index e427421..812e2a6 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -1330,8 +1330,15 @@
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(workProfileTargets);
+ when(sOverrides.workResolverListController.getUserStateIndependentResolversAsUser(
+ Mockito.isA(List.class),
+ Mockito.isA(UserHandle.class)))
+ .thenReturn(new ArrayList<>(workResolvedComponentInfos));
sOverrides.isQuietModeEnabled = true;
- setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ // When work profile is disabled, we get 0 results when we query the work profile
+ // intents.
+ setupResolverControllers(personalResolvedComponentInfos,
+ /* workResolvedComponentInfos */ new ArrayList<>());
Intent sendIntent = createSendTextIntent();
sendIntent.setType("TestType");
@@ -1348,7 +1355,7 @@
}
@Test
- public void testWorkTab_noWorkTargets_emptyStateShown() {
+ public void testWorkTab_noWorkAppsAvailable_emptyStateShown() {
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
@@ -1372,6 +1379,57 @@
.check(matches(isDisplayed()));
}
+ @Test
+ public void testWorkTab_xProfileOff_noAppsAvailable_workOff_xProfileOffEmptyStateShown() {
+ // enable the work tab feature flag
+ ResolverActivity.ENABLE_TABBED_VIEW = true;
+ markWorkProfileUserAvailable();
+ List<ResolvedComponentInfo> personalResolvedComponentInfos =
+ createResolvedComponentsForTest(3);
+ List<ResolvedComponentInfo> workResolvedComponentInfos =
+ createResolvedComponentsForTest(0);
+ setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ sOverrides.isQuietModeEnabled = true;
+ sOverrides.hasCrossProfileIntents = false;
+ Intent sendIntent = createSendTextIntent();
+ sendIntent.setType("TestType");
+
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
+ waitForIdle();
+ onView(withId(R.id.contentPanel))
+ .perform(swipeUp());
+ onView(withText(R.string.resolver_work_tab)).perform(click());
+ waitForIdle();
+
+ onView(withText(R.string.resolver_cant_share_with_work_apps))
+ .check(matches(isDisplayed()));
+ }
+
+ @Test
+ public void testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown() {
+ // enable the work tab feature flag
+ ResolverActivity.ENABLE_TABBED_VIEW = true;
+ markWorkProfileUserAvailable();
+ List<ResolvedComponentInfo> personalResolvedComponentInfos =
+ createResolvedComponentsForTest(3);
+ List<ResolvedComponentInfo> workResolvedComponentInfos =
+ createResolvedComponentsForTest(0);
+ setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ sOverrides.isQuietModeEnabled = true;
+ Intent sendIntent = createSendTextIntent();
+ sendIntent.setType("TestType");
+
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
+ waitForIdle();
+ onView(withId(R.id.contentPanel))
+ .perform(swipeUp());
+ onView(withText(R.string.resolver_work_tab)).perform(click());
+ waitForIdle();
+
+ onView(withText(R.string.resolver_no_work_apps_available_share))
+ .check(matches(isDisplayed()));
+ }
+
private Intent createSendTextIntent() {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 4ec89b7..5a3aff9 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -598,7 +598,7 @@
onView(withId(R.id.contentPanel))
.perform(swipeUp());
- onView(withText(R.string.resolver_cant_share_with_work_apps))
+ onView(withText(R.string.resolver_cant_access_work_apps))
.check(matches(isDisplayed()));
}
@@ -612,8 +612,15 @@
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(workProfileTargets);
+ when(sOverrides.workResolverListController.getUserStateIndependentResolversAsUser(
+ Mockito.isA(List.class),
+ Mockito.isA(UserHandle.class)))
+ .thenReturn(new ArrayList<>(workResolvedComponentInfos));
sOverrides.isQuietModeEnabled = true;
- setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ // When work profile is disabled, we get 0 results when we query the work profile
+ // intents.
+ setupResolverControllers(personalResolvedComponentInfos,
+ /* workResolvedComponentInfos */ new ArrayList<>());
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
@@ -629,7 +636,7 @@
}
@Test
- public void testWorkTab_noWorkTargets_emptyStateShown() {
+ public void testWorkTab_noWorkAppsAvailable_emptyStateShown() {
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
@@ -652,6 +659,57 @@
.check(matches(isDisplayed()));
}
+ @Test
+ public void testWorkTab_xProfileOff_noAppsAvailable_workOff_xProfileOffEmptyStateShown() {
+ // enable the work tab feature flag
+ ResolverActivity.ENABLE_TABBED_VIEW = true;
+ markWorkProfileUserAvailable();
+ List<ResolvedComponentInfo> personalResolvedComponentInfos =
+ createResolvedComponentsForTest(3);
+ List<ResolvedComponentInfo> workResolvedComponentInfos =
+ createResolvedComponentsForTest(0);
+ setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ Intent sendIntent = createSendImageIntent();
+ sendIntent.setType("TestType");
+ sOverrides.isQuietModeEnabled = true;
+ sOverrides.hasCrossProfileIntents = false;
+
+ mActivityRule.launchActivity(sendIntent);
+ waitForIdle();
+ onView(withId(R.id.contentPanel))
+ .perform(swipeUp());
+ onView(withText(R.string.resolver_work_tab)).perform(click());
+ waitForIdle();
+
+ onView(withText(R.string.resolver_cant_access_work_apps))
+ .check(matches(isDisplayed()));
+ }
+
+ @Test
+ public void testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown() {
+ // enable the work tab feature flag
+ ResolverActivity.ENABLE_TABBED_VIEW = true;
+ markWorkProfileUserAvailable();
+ List<ResolvedComponentInfo> personalResolvedComponentInfos =
+ createResolvedComponentsForTest(3);
+ List<ResolvedComponentInfo> workResolvedComponentInfos =
+ createResolvedComponentsForTest(0);
+ setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ Intent sendIntent = createSendImageIntent();
+ sendIntent.setType("TestType");
+ sOverrides.isQuietModeEnabled = true;
+
+ mActivityRule.launchActivity(sendIntent);
+ waitForIdle();
+ onView(withId(R.id.contentPanel))
+ .perform(swipeUp());
+ onView(withText(R.string.resolver_work_tab)).perform(click());
+ waitForIdle();
+
+ onView(withText(R.string.resolver_no_work_apps_available_resolve))
+ .check(matches(isDisplayed()));
+ }
+
private Intent createSendImageIntent() {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
index 3e40466..d019704 100644
--- a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
@@ -20,19 +20,24 @@
import static org.junit.Assert.assertEquals;
+import android.app.Activity;
+import android.app.EmptyActivity;
import android.content.Context;
import android.hardware.display.DisplayManagerGlobal;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
import android.view.DisplayAdjustments;
import android.view.DisplayInfo;
+import android.view.WindowManager;
+import android.view.WindowManagerImpl;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
-
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -46,9 +51,13 @@
private Context mContext;
private static final int EXTERNAL_DISPLAY = DEFAULT_DISPLAY + 1;
+ @Rule
+ public ActivityTestRule<EmptyActivity> mActivityRule =
+ new ActivityTestRule<>(EmptyActivity.class);
+
@Before
- public void setUp() throws Exception {
- mContext = InstrumentationRegistry.getContext();
+ public void setUp() {
+ mContext = ApplicationProvider.getApplicationContext();
}
@Test
@@ -76,4 +85,19 @@
Display associatedDisplay = decorContext.getDisplay();
assertEquals(expectedDisplayId, associatedDisplay.getDisplayId());
}
+
+ @Test
+ public void testGetWindowManagerFromVisualDecorContext() throws Throwable {
+ mActivityRule.runOnUiThread(() -> {
+ Activity activity = mActivityRule.getActivity();
+ final DecorContext decorContext = new DecorContext(mContext.getApplicationContext(),
+ activity);
+ WindowManagerImpl actualWm = (WindowManagerImpl)
+ decorContext.getSystemService(WindowManager.class);
+ WindowManagerImpl expectedWm = (WindowManagerImpl)
+ activity.getSystemService(WindowManager.class);
+ // Verify that window manager is from activity not application context.
+ assertEquals(expectedWm.mContext, actualWm.mContext);
+ });
+ }
}
diff --git a/data/etc/preinstalled-packages-platform.xml b/data/etc/preinstalled-packages-platform.xml
index efab27f..17e1f2e 100644
--- a/data/etc/preinstalled-packages-platform.xml
+++ b/data/etc/preinstalled-packages-platform.xml
@@ -97,8 +97,8 @@
is determined by the config resource value config_userTypePackageWhitelistMode.
See frameworks/base/core/res/res/values/config.xml#config_userTypePackageWhitelistMode.
-Changes to the whitelist during system updates can result in installing new system packages
-to pre-existing users, but cannot uninstall system packages from pre-existing users.
+Changes to the whitelist during system updates can result in installing additional system packages
+to pre-existing users, but cannot uninstall pre-existing system packages from pre-existing users.
-->
<config>
<install-in-user-type package="com.android.providers.settings">
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 1efde86..59bdf3d 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -27,6 +27,10 @@
<permission name="android.permission.INTERACT_ACROSS_USERS" />
</privapp-permissions>
+ <privapp-permissions package="com.android.angle">
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ </privapp-permissions>
+
<privapp-permissions package="com.android.apps.tag">
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
</privapp-permissions>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 99605ad..a871047 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -193,12 +193,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/WindowState.java"
},
- "-1741065110": {
- "message": "No app is requesting an orientation, return %d for display id=%d",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ORIENTATION",
- "at": "com\/android\/server\/wm\/DisplayContent.java"
- },
"-1730156332": {
"message": "Display id=%d rotation changed to %d from %d, lastOrientation=%d",
"level": "VERBOSE",
@@ -547,6 +541,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/AppTransitionController.java"
},
+ "-993446393": {
+ "message": "App is requesting an orientation, return %d for display id=%d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/TaskContainers.java"
+ },
"-993378225": {
"message": "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s",
"level": "VERBOSE",
@@ -715,12 +715,6 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
- "-650040763": {
- "message": "rotationForOrientation(orient=%d, last=%d); user=%d %s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ORIENTATION",
- "at": "com\/android\/server\/wm\/DisplayRotation.java"
- },
"-639305784": {
"message": "Could not report config changes to the window token client.",
"level": "WARN",
@@ -1021,12 +1015,6 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "44438983": {
- "message": "performLayout: Activity exiting now removed %s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ADD_REMOVE",
- "at": "com\/android\/server\/wm\/DisplayContent.java"
- },
"45285419": {
"message": "startingWindow was set but startingSurface==null, couldn't remove",
"level": "VERBOSE",
@@ -1087,6 +1075,12 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowSurfaceController.java"
},
+ "137835146": {
+ "message": "No app is requesting an orientation, return %d for display id=%d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/TaskContainers.java"
+ },
"140319294": {
"message": "IME target changed within ActivityRecord",
"level": "DEBUG",
@@ -1531,12 +1525,6 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
- "845234215": {
- "message": "App is requesting an orientation, return %d for display id=%d",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ORIENTATION",
- "at": "com\/android\/server\/wm\/DisplayContent.java"
- },
"853091290": {
"message": "Moved stack=%s behind stack=%s",
"level": "DEBUG",
@@ -1927,6 +1915,12 @@
"group": "WM_DEBUG_STARTING_WINDOW",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "1685441447": {
+ "message": "performLayout: Activity exiting now removed %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ADD_REMOVE",
+ "at": "com\/android\/server\/wm\/TaskContainers.java"
+ },
"1720229827": {
"message": "Creating animation bounds layer",
"level": "INFO",
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index 746378e..31ad81b 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -975,6 +975,7 @@
mChangingConfigurations = orig.mChangingConfigurations;
mChildrenChangingConfigurations = orig.mChildrenChangingConfigurations;
+ mSourceDrawableId = orig.mSourceDrawableId;
for (int i = 0; i < N_CHILDREN; i++) {
final ChildDrawable or = origChildDrawable[i];
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index f87f98a..02c85aa 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -44,7 +44,6 @@
"AttributeResolution.cpp",
"ChunkIterator.cpp",
"ConfigDescription.cpp",
- "DynamicLibManager.cpp",
"Idmap.cpp",
"LoadedArsc.cpp",
"Locale.cpp",
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index f20e184..eaf452b 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -25,7 +25,6 @@
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
-#include "androidfw/DynamicLibManager.h"
#include "androidfw/ResourceUtils.h"
#include "androidfw/Util.h"
#include "utils/ByteOrder.h"
@@ -67,12 +66,7 @@
StringPoolRef entry_string_ref;
};
-AssetManager2::AssetManager2() : dynamic_lib_manager_(std::make_unique<DynamicLibManager>()) {
- memset(&configuration_, 0, sizeof(configuration_));
-}
-
-AssetManager2::AssetManager2(DynamicLibManager* dynamic_lib_manager)
- : dynamic_lib_manager_(dynamic_lib_manager) {
+AssetManager2::AssetManager2() {
memset(&configuration_, 0, sizeof(configuration_));
}
@@ -91,6 +85,9 @@
package_groups_.clear();
package_ids_.fill(0xff);
+ // A mapping from apk assets path to the runtime package id of its first loaded package.
+ std::unordered_map<std::string, uint8_t> apk_assets_package_ids;
+
// Overlay resources are not directly referenced by an application so their resource ids
// can change throughout the application's lifetime. Assign overlay package ids last.
std::vector<const ApkAssets*> sorted_apk_assets(apk_assets_);
@@ -98,37 +95,25 @@
return !a->IsOverlay();
});
- std::unordered_map<std::string, uint8_t> apk_assets_package_ids;
- std::unordered_map<std::string, uint8_t> package_name_package_ids;
-
- // Assign stable package ids to application packages.
- uint8_t next_available_package_id = 0U;
- for (const auto& apk_assets : sorted_apk_assets) {
- for (const auto& package : apk_assets->GetLoadedArsc()->GetPackages()) {
- uint8_t package_id = package->GetPackageId();
- if (package->IsOverlay()) {
- package_id = GetDynamicLibManager()->FindUnassignedId(next_available_package_id);
- next_available_package_id = package_id + 1;
- } else if (package->IsDynamic()) {
- package_id = GetDynamicLibManager()->GetAssignedId(package->GetPackageName());
- }
-
- // Map the path of the apk assets to the package id of its first loaded package.
- apk_assets_package_ids[apk_assets->GetPath()] = package_id;
-
- // Map the package name of the package to the first loaded package with that package id.
- package_name_package_ids[package->GetPackageName()] = package_id;
- }
+ // The assets cookie must map to the position of the apk assets in the unsorted apk assets list.
+ std::unordered_map<const ApkAssets*, ApkAssetsCookie> apk_assets_cookies;
+ apk_assets_cookies.reserve(apk_assets_.size());
+ for (size_t i = 0, n = apk_assets_.size(); i < n; i++) {
+ apk_assets_cookies[apk_assets_[i]] = static_cast<ApkAssetsCookie>(i);
}
- const int apk_assets_count = apk_assets_.size();
- for (int i = 0; i < apk_assets_count; i++) {
- const auto& apk_assets = apk_assets_[i];
- for (const auto& package : apk_assets->GetLoadedArsc()->GetPackages()) {
- const auto package_id_entry = package_name_package_ids.find(package->GetPackageName());
- CHECK(package_id_entry != package_name_package_ids.end())
- << "no package id assgined to package " << package->GetPackageName();
- const uint8_t package_id = package_id_entry->second;
+ // 0x01 is reserved for the android package.
+ int next_package_id = 0x02;
+ for (const ApkAssets* apk_assets : sorted_apk_assets) {
+ const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc();
+ for (const std::unique_ptr<const LoadedPackage>& package : loaded_arsc->GetPackages()) {
+ // Get the package ID or assign one if a shared library.
+ int package_id;
+ if (package->IsDynamic()) {
+ package_id = next_package_id++;
+ } else {
+ package_id = package->GetPackageId();
+ }
// Add the mapping for package ID to index if not present.
uint8_t idx = package_ids_[package_id];
@@ -162,7 +147,7 @@
target_package_group.overlays_.push_back(
ConfiguredOverlay{loaded_idmap->GetTargetResourcesMap(target_package_id,
overlay_table.get()),
- static_cast<ApkAssetsCookie>(i)});
+ apk_assets_cookies[apk_assets]});
}
}
@@ -174,7 +159,7 @@
// Add the package and to the set of packages with the same ID.
package_group->packages_.push_back(ConfiguredPackage{package.get(), {}});
- package_group->cookies_.push_back(static_cast<ApkAssetsCookie>(i));
+ package_group->cookies_.push_back(apk_assets_cookies[apk_assets]);
// Add the package name -> build time ID mappings.
for (const DynamicPackageEntry& entry : package->GetDynamicPackageMap()) {
@@ -182,6 +167,8 @@
package_group->dynamic_ref_table->mEntries.replaceValueFor(
package_name, static_cast<uint8_t>(entry.package_id));
}
+
+ apk_assets_package_ids.insert(std::make_pair(apk_assets->GetPath(), package_id));
}
}
@@ -1329,16 +1316,6 @@
return 0;
}
-DynamicLibManager* AssetManager2::GetDynamicLibManager() const {
- auto dynamic_lib_manager =
- std::get_if<std::unique_ptr<DynamicLibManager>>(&dynamic_lib_manager_);
- if (dynamic_lib_manager) {
- return (*dynamic_lib_manager).get();
- } else {
- return *std::get_if<DynamicLibManager*>(&dynamic_lib_manager_);
- }
-}
-
std::unique_ptr<Theme> AssetManager2::NewTheme() {
return std::unique_ptr<Theme>(new Theme(this));
}
diff --git a/libs/androidfw/DynamicLibManager.cpp b/libs/androidfw/DynamicLibManager.cpp
deleted file mode 100644
index 895b769..0000000
--- a/libs/androidfw/DynamicLibManager.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "androidfw/DynamicLibManager.h"
-
-namespace android {
-
-uint8_t DynamicLibManager::GetAssignedId(const std::string& library_package_name) {
- auto lib_entry = shared_lib_package_ids_.find(library_package_name);
- if (lib_entry != shared_lib_package_ids_.end()) {
- return lib_entry->second;
- }
-
- return shared_lib_package_ids_[library_package_name] = next_package_id_++;
-}
-
-uint8_t DynamicLibManager::FindUnassignedId(uint8_t start_package_id) {
- return (start_package_id < next_package_id_) ? next_package_id_ : start_package_id;
-}
-
-} // namespace android
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index b2cec2a..e21abad 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -27,7 +27,6 @@
#include "androidfw/ApkAssets.h"
#include "androidfw/Asset.h"
#include "androidfw/AssetManager.h"
-#include "androidfw/DynamicLibManager.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
@@ -95,7 +94,6 @@
};
AssetManager2();
- explicit AssetManager2(DynamicLibManager* dynamic_lib_manager);
// Sets/resets the underlying ApkAssets for this AssetManager. The ApkAssets
// are not owned by the AssetManager, and must have a longer lifetime.
@@ -126,6 +124,9 @@
// This may be nullptr if the APK represented by `cookie` has no resource table.
std::shared_ptr<const DynamicRefTable> GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
+ // Retrieve the assigned package id of the package if loaded into this AssetManager
+ uint8_t GetAssignedPackageId(const LoadedPackage* package) const;
+
// Returns a string representation of the overlayable API of a package.
bool GetOverlayablesToString(const android::StringPiece& package_name,
std::string* out) const;
@@ -370,11 +371,6 @@
// been seen while traversing bag parents.
const ResolvedBag* GetBag(uint32_t resid, std::vector<uint32_t>& child_resids);
- // Retrieve the assigned package id of the package if loaded into this AssetManager
- uint8_t GetAssignedPackageId(const LoadedPackage* package) const;
-
- DynamicLibManager* GetDynamicLibManager() const;
-
// 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_;
@@ -393,9 +389,6 @@
// may need to be purged.
ResTable_config configuration_;
- // Component responsible for assigning package ids to shared libraries.
- std::variant<std::unique_ptr<DynamicLibManager>, DynamicLibManager*> dynamic_lib_manager_;
-
// Cached set of bags. These are cached because they can inherit keys from parent bags,
// which involves some calculation.
std::unordered_map<uint32_t, util::unique_cptr<ResolvedBag>> cached_bags_;
diff --git a/libs/androidfw/include/androidfw/DynamicLibManager.h b/libs/androidfw/include/androidfw/DynamicLibManager.h
deleted file mode 100644
index 1ff7079..0000000
--- a/libs/androidfw/include/androidfw/DynamicLibManager.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROIDFW_DYNAMICLIBMANAGER_H
-#define ANDROIDFW_DYNAMICLIBMANAGER_H
-
-#include <string>
-#include <unordered_map>
-
-#include "android-base/macros.h"
-
-namespace android {
-
-// Manages assigning resource ids for dynamic resources.
-class DynamicLibManager {
- public:
- DynamicLibManager() = default;
-
- // Retrieves the assigned package id for the library.
- uint8_t GetAssignedId(const std::string& library_package_name);
-
- // Queries in ascending order for the first available package id that is not currently assigned to
- // a library.
- uint8_t FindUnassignedId(uint8_t start_package_id);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DynamicLibManager);
-
- uint8_t next_package_id_ = 0x02;
- std::unordered_map<std::string, uint8_t> shared_lib_package_ids_;
-};
-
-} // namespace android
-
-#endif //ANDROIDFW_DYNAMICLIBMANAGER_H
diff --git a/libs/androidfw/include/androidfw/MutexGuard.h b/libs/androidfw/include/androidfw/MutexGuard.h
index 8891512..64924f4 100644
--- a/libs/androidfw/include/androidfw/MutexGuard.h
+++ b/libs/androidfw/include/androidfw/MutexGuard.h
@@ -47,8 +47,7 @@
static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer");
public:
- template <typename ...Args>
- explicit Guarded(Args&& ...args) : guarded_(std::forward<Args>(args)...) {
+ explicit Guarded() : guarded_() {
}
template <typename U = T>
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index ac32699..8c255d1 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -17,9 +17,9 @@
#include "androidfw/AssetManager2.h"
#include "androidfw/AssetManager.h"
-#include "android-base/logging.h"
-
#include "TestHelpers.h"
+#include "android-base/file.h"
+#include "android-base/logging.h"
#include "androidfw/ResourceUtils.h"
#include "data/appaslib/R.h"
#include "data/basic/R.h"
@@ -45,37 +45,43 @@
class AssetManager2Test : public ::testing::Test {
public:
void SetUp() override {
- basic_assets_ = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+ // Move to the test data directory so the idmap can locate the overlay APK.
+ std::string original_path = base::GetExecutableDirectory();
+ chdir(GetTestDataPath().c_str());
+
+ basic_assets_ = ApkAssets::Load("basic/basic.apk");
ASSERT_NE(nullptr, basic_assets_);
- basic_de_fr_assets_ = ApkAssets::Load(GetTestDataPath() + "/basic/basic_de_fr.apk");
+ basic_de_fr_assets_ = ApkAssets::Load("basic/basic_de_fr.apk");
ASSERT_NE(nullptr, basic_de_fr_assets_);
- style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
+ style_assets_ = ApkAssets::Load("styles/styles.apk");
ASSERT_NE(nullptr, style_assets_);
- lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk");
+ lib_one_assets_ = ApkAssets::Load("lib_one/lib_one.apk");
ASSERT_NE(nullptr, lib_one_assets_);
- lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk");
+ lib_two_assets_ = ApkAssets::Load("lib_two/lib_two.apk");
ASSERT_NE(nullptr, lib_two_assets_);
- libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
+ libclient_assets_ = ApkAssets::Load("libclient/libclient.apk");
ASSERT_NE(nullptr, libclient_assets_);
- appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk",
- PROPERTY_DYNAMIC);
+ appaslib_assets_ = ApkAssets::Load("appaslib/appaslib.apk", PROPERTY_DYNAMIC);
ASSERT_NE(nullptr, appaslib_assets_);
- system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk",
- PROPERTY_SYSTEM);
+ system_assets_ = ApkAssets::Load("system/system.apk", PROPERTY_SYSTEM);
ASSERT_NE(nullptr, system_assets_);
- app_assets_ = ApkAssets::Load(GetTestDataPath() + "/app/app.apk");
+ app_assets_ = ApkAssets::Load("app/app.apk");
ASSERT_THAT(app_assets_, NotNull());
- overlayable_assets_ = ApkAssets::Load(GetTestDataPath() + "/overlayable/overlayable.apk");
+ overlay_assets_ = ApkAssets::LoadOverlay("overlay/overlay.idmap");
+ ASSERT_NE(nullptr, overlay_assets_);
+
+ overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk");
ASSERT_THAT(overlayable_assets_, NotNull());
+ chdir(original_path.c_str());
}
protected:
@@ -88,6 +94,7 @@
std::unique_ptr<const ApkAssets> appaslib_assets_;
std::unique_ptr<const ApkAssets> system_assets_;
std::unique_ptr<const ApkAssets> app_assets_;
+ std::unique_ptr<const ApkAssets> overlay_assets_;
std::unique_ptr<const ApkAssets> overlayable_assets_;
};
@@ -216,23 +223,24 @@
EXPECT_EQ(fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
}
-TEST_F(AssetManager2Test, AssignsUnchangingPackageIdToSharedLibrary) {
- DynamicLibManager lib_manager;
- AssetManager2 assetmanager(&lib_manager);
+TEST_F(AssetManager2Test, AssignsOverlayPackageIdLast) {
+ AssetManager2 assetmanager;
assetmanager.SetApkAssets(
- {lib_one_assets_.get(), lib_two_assets_.get(), libclient_assets_.get()});
+ {overlayable_assets_.get(), overlay_assets_.get(), lib_one_assets_.get()});
- AssetManager2 assetmanager2(&lib_manager);
- assetmanager2.SetApkAssets(
- {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+ auto apk_assets = assetmanager.GetApkAssets();
+ ASSERT_EQ(3, apk_assets.size());
+ ASSERT_EQ(overlayable_assets_.get(), apk_assets[0]);
+ ASSERT_EQ(overlay_assets_.get(), apk_assets[1]);
+ ASSERT_EQ(lib_one_assets_.get(), apk_assets[2]);
- uint32_t res_id = assetmanager.GetResourceId("com.android.lib_one:string/foo");
- ASSERT_NE(0U, res_id);
+ auto get_first_package_id = [&assetmanager](const ApkAssets* apkAssets) -> uint8_t {
+ return assetmanager.GetAssignedPackageId(apkAssets->GetLoadedArsc()->GetPackages()[0].get());
+ };
- uint32_t res_id_2 = assetmanager2.GetResourceId("com.android.lib_one:string/foo");
- ASSERT_NE(0U, res_id_2);
-
- ASSERT_EQ(res_id, res_id_2);
+ ASSERT_EQ(get_first_package_id(overlayable_assets_.get()), 0x7f);
+ ASSERT_EQ(get_first_package_id(overlay_assets_.get()), 0x03);
+ ASSERT_EQ(get_first_package_id(lib_one_assets_.get()), 0x02);
}
TEST_F(AssetManager2Test, GetSharedLibraryResourceName) {
@@ -770,7 +778,6 @@
ASSERT_EQ(api.find("not_overlayable"), std::string::npos);
ASSERT_NE(api.find("resource='com.android.overlayable:string/overlayable2' overlayable='OverlayableResources1' actor='overlay://theme' policy='0x0000000a'\n"),
std::string::npos);
-
}
} // namespace android
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4299dd3..c19b187 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -555,9 +555,11 @@
FrameInfo* forthBehind = mLast4FrameInfos.front().first;
int64_t composedFrameId = mLast4FrameInfos.front().second;
nsecs_t acquireTime = -1;
- native_window_get_frame_timestamps(mNativeSurface->getNativeWindow(), composedFrameId,
- nullptr, &acquireTime, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr);
+ if (mNativeSurface) {
+ native_window_get_frame_timestamps(mNativeSurface->getNativeWindow(), composedFrameId,
+ nullptr, &acquireTime, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr);
+ }
// Ignore default -1, NATIVE_WINDOW_TIMESTAMP_INVALID and NATIVE_WINDOW_TIMESTAMP_PENDING
forthBehind->set(FrameInfoIndex::GpuCompleted) = acquireTime > 0 ? acquireTime : -1;
mJankTracker.finishGpuDraw(*forthBehind);
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 8600dc4..4150926 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -47,16 +47,14 @@
Location getLastLocation(in LocationRequest request, String packageName, String featureId);
boolean getCurrentLocation(in LocationRequest request,
in ICancellationSignal cancellationSignal, in ILocationListener listener,
- String packageName, String featureId, String listenerIdentifier);
+ String packageName, String featureId);
void requestLocationUpdates(in LocationRequest request, in ILocationListener listener,
- in PendingIntent intent, String packageName, String featureId,
- String listenerIdentifier);
- void removeUpdates(in ILocationListener listener, in PendingIntent intent, String packageName);
+ in PendingIntent intent, String packageName, String featureId);
+ void removeUpdates(in ILocationListener listener, in PendingIntent intent);
void requestGeofence(in LocationRequest request, in Geofence geofence,
- in PendingIntent intent, String packageName, String featureId,
- String listenerIdentifier);
+ in PendingIntent intent, String packageName, String featureId);
void removeGeofence(in Geofence fence, in PendingIntent intent, String packageName);
boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName,
@@ -73,34 +71,31 @@
boolean addGnssMeasurementsListener(in GnssRequest request,
in IGnssMeasurementsListener listener,
- String packageName, String featureId,
- String listenerIdentifier);
+ String packageName, String featureId);
void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections,
in String packageName);
- long getGnssCapabilities(in String packageName);
+ long getGnssCapabilities();
void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);
boolean addGnssAntennaInfoListener(in IGnssAntennaInfoListener listener,
- String packageName, String featureId, String listenerIdentifier);
+ String packageName, String featureId);
void removeGnssAntennaInfoListener(in IGnssAntennaInfoListener listener);
boolean addGnssNavigationMessageListener(in IGnssNavigationMessageListener listener,
- String packageName, String featureId, String listenerIdentifier);
+ String packageName, String featureId);
void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener);
int getGnssYearOfHardware();
String getGnssHardwareModelName();
int getGnssBatchSize(String packageName);
- boolean addGnssBatchingCallback(in IBatchedLocationCallback callback, String packageName,
- String featureId, String listenerIdentifier);
+ boolean addGnssBatchingCallback(in IBatchedLocationCallback callback, String packageName, String featureId);
void removeGnssBatchingCallback();
- boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName);
+ boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName, String featureId);
void flushGnssBatch(String packageName);
boolean stopGnssBatch();
void injectLocation(in Location location);
- @UnsupportedAppUsage
List<String> getAllProviders();
List<String> getProviders(in Criteria criteria, boolean enabledOnly);
String getBestProvider(in Criteria criteria, boolean enabledOnly);
@@ -116,11 +111,11 @@
boolean isProviderEnabledForUser(String provider, int userId);
boolean isLocationEnabledForUser(int userId);
void setLocationEnabledForUser(boolean enabled, int userId);
- void addTestProvider(String name, in ProviderProperties properties, String opPackageName);
- void removeTestProvider(String provider, String opPackageName);
- void setTestProviderLocation(String provider, in Location loc, String opPackageName);
- void setTestProviderEnabled(String provider, boolean enabled, String opPackageName);
- List<LocationRequest> getTestProviderCurrentRequests(String provider, String opPackageName);
+ void addTestProvider(String name, in ProviderProperties properties, String packageName, String featureId);
+ void removeTestProvider(String provider, String packageName, String featureId);
+ void setTestProviderLocation(String provider, in Location location, String packageName, String featureId);
+ void setTestProviderEnabled(String provider, boolean enabled, String packageName, String featureId);
+ List<LocationRequest> getTestProviderCurrentRequests(String provider);
LocationTime getGnssTimeMillis();
boolean sendExtraCommand(String provider, String command, inout Bundle extras);
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 6724324..9aa0c87 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -585,6 +585,16 @@
return mElapsedRealtimeNanos;
}
+ /** @hide */
+ public long getElapsedRealtimeAgeNanos(long referenceRealtimeNs) {
+ return referenceRealtimeNs - mElapsedRealtimeNanos;
+ }
+
+ /** @hide */
+ public long getElapsedRealtimeAgeNanos() {
+ return getElapsedRealtimeAgeNanos(SystemClock.elapsedRealtimeNanos());
+ }
+
/**
* Set the time of this fix, in elapsed real-time since system boot.
*
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index ff7049e..fcbd3e5 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -652,19 +652,6 @@
}
/**
- * Create a string that allows an app to identify a listener
- *
- * @param listener The listener
- *
- * @return A identifying string
- */
- private static String getListenerIdentifier(@NonNull Object listener) {
- return listener.getClass().getName()
- + '@'
- + Integer.toHexString(System.identityHashCode(listener));
- }
-
- /**
* Asynchronously returns a single current location fix. This may activate sensors in order to
* compute a new location, unlike {@link #getLastKnownLocation(String)}, which will only return
* a cached fix if available. The given callback will be invoked once and only once, either with
@@ -742,8 +729,7 @@
try {
if (mService.getCurrentLocation(currentLocationRequest, remoteCancellationSignal,
- listenerTransport, mContext.getPackageName(), mContext.getAttributionTag(),
- getListenerIdentifier(consumer))) {
+ listenerTransport, mContext.getPackageName(), mContext.getAttributionTag())) {
listenerTransport.register(mContext.getSystemService(AlarmManager.class),
remoteCancellationSignal);
if (cancellationSignal != null) {
@@ -1189,8 +1175,7 @@
boolean registered = false;
try {
mService.requestLocationUpdates(locationRequest, transport, null,
- mContext.getPackageName(), mContext.getAttributionTag(),
- getListenerIdentifier(listener));
+ mContext.getPackageName(), mContext.getAttributionTag());
registered = true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1235,8 +1220,7 @@
try {
mService.requestLocationUpdates(locationRequest, null, pendingIntent,
- mContext.getPackageName(), mContext.getAttributionTag(),
- getListenerIdentifier(pendingIntent));
+ mContext.getPackageName(), mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1293,7 +1277,7 @@
transport.unregister();
try {
- mService.removeUpdates(transport, null, mContext.getPackageName());
+ mService.removeUpdates(transport, null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1312,7 +1296,7 @@
Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent");
try {
- mService.removeUpdates(null, pendingIntent, mContext.getPackageName());
+ mService.removeUpdates(null, pendingIntent);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1515,7 +1499,8 @@
requiresSatellite, requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed,
supportsBearing, powerRequirement, accuracy);
try {
- mService.addTestProvider(provider, properties, mContext.getOpPackageName());
+ mService.addTestProvider(provider, properties, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1536,7 +1521,8 @@
Preconditions.checkArgument(provider != null, "invalid null provider");
try {
- mService.removeTestProvider(provider, mContext.getOpPackageName());
+ mService.removeTestProvider(provider, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1570,7 +1556,8 @@
}
try {
- mService.setTestProviderLocation(provider, location, mContext.getOpPackageName());
+ mService.setTestProviderLocation(provider, location, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1599,7 +1586,8 @@
Preconditions.checkArgument(provider != null, "invalid null provider");
try {
- mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName());
+ mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1643,8 +1631,7 @@
public List<LocationRequest> getTestProviderCurrentRequests(String providerName) {
Preconditions.checkArgument(providerName != null, "invalid null provider");
try {
- return mService.getTestProviderCurrentRequests(providerName,
- mContext.getOpPackageName());
+ return mService.getTestProviderCurrentRequests(providerName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1711,7 +1698,7 @@
LocationRequest request = new LocationRequest().setExpireIn(expiration);
try {
mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
- mContext.getAttributionTag(), getListenerIdentifier(intent));
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1798,7 +1785,7 @@
try {
mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
- mContext.getAttributionTag(), getListenerIdentifier(intent));
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1867,7 +1854,7 @@
*/
public @NonNull GnssCapabilities getGnssCapabilities() {
try {
- long gnssCapabilities = mService.getGnssCapabilities(mContext.getPackageName());
+ long gnssCapabilities = mService.getGnssCapabilities();
if (gnssCapabilities == GnssCapabilities.INVALID_CAPABILITIES) {
gnssCapabilities = 0L;
}
@@ -2493,7 +2480,7 @@
try {
if (mBatchedLocationCallbackManager.addListener(callback, handler)) {
return mService.startGnssBatch(periodNanos, wakeOnFifoFull,
- mContext.getPackageName());
+ mContext.getPackageName(), mContext.getAttributionTag());
}
return false;
} catch (RemoteException e) {
@@ -3012,7 +2999,7 @@
GnssMeasurementsListener transport = new GnssMeasurementsListener();
if (mService.addGnssMeasurementsListener(request, transport, mContext.getPackageName(),
- mContext.getAttributionTag(), "gnss measurement callback")) {
+ mContext.getAttributionTag())) {
mListenerTransport = transport;
return true;
} else {
@@ -3065,7 +3052,7 @@
GnssNavigationMessageListener transport = new GnssNavigationMessageListener();
if (mService.addGnssNavigationMessageListener(transport, mContext.getPackageName(),
- mContext.getAttributionTag(), "gnss navigation callback")) {
+ mContext.getAttributionTag())) {
mListenerTransport = transport;
return true;
} else {
@@ -3106,7 +3093,7 @@
GnssAntennaInfoListener transport = new GnssAntennaInfoListener();
if (mService.addGnssAntennaInfoListener(transport, mContext.getPackageName(),
- mContext.getAttributionTag(), "gnss antenna info callback")) {
+ mContext.getAttributionTag())) {
mListenerTransport = transport;
return true;
} else {
@@ -3143,7 +3130,7 @@
BatchedLocationCallback transport = new BatchedLocationCallback();
if (mService.addGnssBatchingCallback(transport, mContext.getPackageName(),
- mContext.getAttributionTag(), "batched location callback")) {
+ mContext.getAttributionTag())) {
mListenerTransport = transport;
return true;
} else {
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 9950f05..db2a1e8 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -432,7 +432,7 @@
* @return An array of supported encapsulation modes for the device. This
* may be an empty array if no encapsulation modes are supported.
*/
- public @NonNull int[] getEncapsulationModes() {
+ public @NonNull @AudioTrack.EncapsulationMode int[] getEncapsulationModes() {
// Implement a getter in r-dev or r-tv-dev as needed.
return new int[0]; // be careful of returning a copy of any internal data.
}
@@ -451,7 +451,7 @@
* @return An array of supported encapsulation metadata types for the device. This
* may be an empty array if no metadata types are supported.
*/
- public @NonNull int[] getEncapsulationMetadataTypes() {
+ public @NonNull @AudioTrack.EncapsulationMetadataType int[] getEncapsulationMetadataTypes() {
// Implement a getter in r-dev or r-tv-dev as needed.
return new int[0]; // be careful of returning a copy of any internal data.
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index fffdd68..7408987e 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4769,7 +4769,7 @@
* opened on that device.
*
* @param device an instance of {@link AudioDeviceInfo} returned from {@link getDevices()}.
- * @param delayMs delay in milliseconds desired. This should be in range of {@code 0}
+ * @param delayMillis delay in milliseconds desired. This should be in range of {@code 0}
* to the value returned by {@link #getMaxAdditionalOutputDeviceDelay()}.
* @return true if successful, false if the device does not support output device delay
* or the delay is not in range of {@link #getMaxAdditionalOutputDeviceDelay()}.
@@ -4777,7 +4777,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public boolean setAdditionalOutputDeviceDelay(
- @NonNull AudioDeviceInfo device, @IntRange(from = 0) int delayMs) {
+ @NonNull AudioDeviceInfo device, @IntRange(from = 0) long delayMillis) {
Objects.requireNonNull(device);
// Implement the setter in r-dev or r-tv-dev as needed.
return false;
@@ -4793,7 +4793,7 @@
*/
@SystemApi
@IntRange(from = 0)
- public int getAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
+ public long getAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
Objects.requireNonNull(device);
// Implement the getter in r-dev or r-tv-dev as needed.
return 0;
@@ -4811,7 +4811,7 @@
*/
@SystemApi
@IntRange(from = 0)
- public int getMaxAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
+ public long getMaxAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
Objects.requireNonNull(device);
// Implement the getter in r-dev or r-tv-dev as needed.
return 0;
@@ -5987,6 +5987,20 @@
}
}
+ /**
+ * Set whether or not there is an active RTT call.
+ * This method should be called by Telecom service.
+ * @hide
+ * TODO: make this a @SystemApi
+ */
+ public static void setRttEnabled(boolean rttEnabled) {
+ try {
+ getService().setRttEnabled(rttEnabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
//---------------------------------------------------------
// Inner classes
//--------------------
diff --git a/media/java/android/media/AudioMetadata.java b/media/java/android/media/AudioMetadata.java
index 1a9517c..c91ff0d 100644
--- a/media/java/android/media/AudioMetadata.java
+++ b/media/java/android/media/AudioMetadata.java
@@ -79,96 +79,11 @@
}
/**
- * A read only {@code Map} interface of {@link Key} value pairs.
- *
- * <p>Using a {@link Key} interface, the map looks up the corresponding value.</p>
- */
- public interface ReadMap {
- /**
- * Returns true if the key exists in the map.
- *
- * @param key interface for requesting the value.
- * @param <T> type of value.
- * @return true if key exists in the Map.
- */
- <T> boolean containsKey(@NonNull Key<T> key);
-
- /**
- * Returns a copy of the map.
- *
- * This is intended for safe conversion between a {@link ReadMap}
- * interface and a {@link Map} interface.
- * Currently only simple objects are used for key values which
- * means a shallow copy is sufficient.
- *
- * @return a Map copied from the existing map.
- */
- @NonNull
- Map dup(); // lint checker doesn't like clone().
-
- /**
- * Returns the value associated with the key.
- *
- * @param key interface for requesting the value.
- * @param <T> type of value.
- * @return returns the value of associated with key or null if it doesn't exist.
- */
- @Nullable
- <T> T get(@NonNull Key<T> key);
-
- /**
- * Returns a {@code Set} of keys associated with the map.
- * @hide
- */
- @NonNull
- Set<Key<?>> keySet();
-
- /**
- * Returns the number of elements in the map.
- */
- int size();
- }
-
- /**
- * A writeable {@link Map} interface of {@link Key} value pairs.
- * This interface is not guaranteed to be thread-safe
- * unless the supplier for the {@code Map} states it as thread safe.
- */
- // TODO: Create a wrapper like java.util.Collections.synchronizedMap?
- public interface Map extends ReadMap {
- /**
- * Removes the value associated with the key.
- * @param key interface for storing the value.
- * @param <T> type of value.
- * @return the value of the key, null if it doesn't exist.
- */
- @Nullable
- <T> T remove(@NonNull Key<T> key);
-
- /**
- * Sets a value for the key.
- *
- * @param key interface for storing the value.
- * @param <T> type of value.
- * @param value a non-null value of type T.
- * @return the previous value associated with key or null if it doesn't exist.
- */
- // See automatic Kotlin overloading for Java interoperability.
- // https://kotlinlang.org/docs/reference/java-interop.html#operators
- // See also Kotlin set for overloaded operator indexing.
- // https://kotlinlang.org/docs/reference/operator-overloading.html#indexed
- // Also the Kotlin mutable-list set.
- // https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/set.html
- @Nullable
- <T> T set(@NonNull Key<T> key, @NonNull T value);
- }
-
- /**
- * Creates a {@link Map} suitable for adding keys.
- * @return an empty {@link Map} instance.
+ * Creates a {@link AudioMetadataMap} suitable for adding keys.
+ * @return an empty {@link AudioMetadataMap} instance.
*/
@NonNull
- public static Map createMap() {
+ public static AudioMetadataMap createMap() {
return new BaseMap();
}
@@ -339,7 +254,7 @@
* It is possible to require the keys to be of a certain class
* before allowing a set or get operation.
*/
- public static class BaseMap implements Map {
+ public static class BaseMap implements AudioMetadataMap {
@Override
public <T> boolean containsKey(@NonNull Key<T> key) {
Pair<Key<?>, Object> valuePair = mHashMap.get(pairFromKey(key));
@@ -348,7 +263,7 @@
@Override
@NonNull
- public Map dup() {
+ public AudioMetadataMap dup() {
BaseMap map = new BaseMap();
map.mHashMap.putAll(this.mHashMap);
return map;
diff --git a/media/java/android/media/AudioMetadataMap.java b/media/java/android/media/AudioMetadataMap.java
new file mode 100644
index 0000000..1961931
--- /dev/null
+++ b/media/java/android/media/AudioMetadataMap.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * AudioMetadataMap is a writeable {@code Map}-style
+ * interface of {@link AudioMetadata.Key} value pairs.
+ * This interface is not guaranteed to be thread-safe
+ * unless the underlying implementation for the {@code AudioMetadataMap}
+ * states it as thread safe.
+ *
+ * {@see AudioMetadataReadMap}
+ */
+// TODO: Create a wrapper like java.util.Collections.synchronizedMap?
+
+public interface AudioMetadataMap extends AudioMetadataReadMap {
+ /**
+ * Removes the value associated with the key.
+ * @param key interface for storing the value.
+ * @param <T> type of value.
+ * @return the value of the key, null if it doesn't exist.
+ */
+ @Nullable
+ <T> T remove(@NonNull AudioMetadata.Key<T> key);
+
+ /**
+ * Sets a value for the key.
+ *
+ * @param key interface for storing the value.
+ * @param <T> type of value.
+ * @param value a non-null value of type T.
+ * @return the previous value associated with key or null if it doesn't exist.
+ */
+ // See automatic Kotlin overloading for Java interoperability.
+ // https://kotlinlang.org/docs/reference/java-interop.html#operators
+ // See also Kotlin set for overloaded operator indexing.
+ // https://kotlinlang.org/docs/reference/operator-overloading.html#indexed
+ // Also the Kotlin mutable-list set.
+ // https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/set.html
+ @Nullable
+ <T> T set(@NonNull AudioMetadata.Key<T> key, @NonNull T value);
+}
diff --git a/media/java/android/media/AudioMetadataReadMap.java b/media/java/android/media/AudioMetadataReadMap.java
new file mode 100644
index 0000000..e74242a
--- /dev/null
+++ b/media/java/android/media/AudioMetadataReadMap.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.Set;
+
+/**
+ * A read only {@code Map}-style interface of {@link AudioMetadata.Key} value pairs used
+ * for {@link AudioMetadata}.
+ *
+ * <p>Using a {@link AudioMetadata.Key} interface,
+ * this map looks up the corresponding value.
+ * Read-only maps are thread-safe for lookup, but the underlying object
+ * values may need their own thread protection if mutable.</p>
+ *
+ * {@see AudioMetadataMap}
+ */
+public interface AudioMetadataReadMap {
+ /**
+ * Returns true if the key exists in the map.
+ *
+ * @param key interface for requesting the value.
+ * @param <T> type of value.
+ * @return true if key exists in the Map.
+ */
+ <T> boolean containsKey(@NonNull AudioMetadata.Key<T> key);
+
+ /**
+ * Returns a copy of the map.
+ *
+ * This is intended for safe conversion between a {@link AudioMetadataReadMap}
+ * interface and a {@link AudioMetadataMap} interface.
+ * Currently only simple objects are used for key values which
+ * means a shallow copy is sufficient.
+ *
+ * @return a Map copied from the existing map.
+ */
+ @NonNull
+ AudioMetadataMap dup(); // lint checker doesn't like clone().
+
+ /**
+ * Returns the value associated with the key.
+ *
+ * @param key interface for requesting the value.
+ * @param <T> type of value.
+ * @return returns the value of associated with key or null if it doesn't exist.
+ */
+ @Nullable
+ <T> T get(@NonNull AudioMetadata.Key<T> key);
+
+ /**
+ * Returns a {@code Set} of keys associated with the map.
+ * @hide
+ */
+ @NonNull
+ Set<AudioMetadata.Key<?>> keySet();
+
+ /**
+ * Returns the number of elements in the map.
+ */
+ @IntRange(from = 0)
+ int size();
+}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index d17e429..1d229b80 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -918,7 +918,29 @@
private final int mContentId;
private final int mSyncId;
- private TunerConfiguration(int contentId, int syncId) {
+ /**
+ * Constructs a TunerConfiguration instance for use in {@link AudioTrack.Builder}
+ *
+ * @param contentId selects the audio stream to use.
+ * The contentId may be obtained from
+ * {@link android.media.tv.tuner.filter.Filter#getId()}.
+ * This is always a positive number.
+ * @param syncId selects the clock to use for synchronization
+ * of audio with other streams such as video.
+ * The syncId may be obtained from
+ * {@link android.media.tv.tuner.Tuner#getAvSyncHwId()}.
+ * This is always a positive number.
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public TunerConfiguration(
+ @IntRange(from = 1) int contentId, @IntRange(from = 1)int syncId) {
+ if (contentId < 1) {
+ throw new IllegalArgumentException(
+ "contentId " + contentId + " must be positive");
+ }
+ if (syncId < 1) {
+ throw new IllegalArgumentException("syncId " + syncId + " must be positive");
+ }
mContentId = contentId;
mSyncId = syncId;
}
@@ -938,73 +960,6 @@
public @IntRange(from = 1) int getSyncId() {
return mSyncId; // The Builder ensures this is > 0.
}
-
- /**
- * Builder class for {@link AudioTrack.TunerConfiguration} objects.
- */
- public static class Builder {
- private int mContentId;
- private int mSyncId;
-
- /**
- * Sets the contentId from the Tuner filter.
- *
- * @param contentId selects the audio stream to use.
- * The contentId may be obtained from
- * {@link android.media.tv.tuner.filter.Filter#getId()}.
- * This is always a positive number.
- *
- * @return the same Builder instance.
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
- public @NonNull Builder setContentId(@IntRange(from = 1) int contentId) {
- if (contentId < 1) {
- throw new IllegalArgumentException(
- "contentId " + contentId + " must be positive");
- }
- mContentId = contentId;
- return this;
- }
-
- /**
- * Sets the syncId from the Tuner filter.
- *
- * @param syncId selects the clock to use for synchronization
- * of audio with other streams such as video.
- * The syncId may be obtained from
- * {@link android.media.tv.tuner.Tuner#getAvSyncHwId()}.
- * This is always a positive number.
- *
- * @return the same Builder instance.
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
- public @NonNull Builder setSyncId(@IntRange(from = 1) int syncId) {
- if (syncId < 1) {
- throw new IllegalArgumentException("syncId " + syncId + " must be positive");
- }
- mSyncId = syncId;
- return this;
- }
-
- /**
- * Builds a {@link AudioTrack.TunerConfiguration} instance initialized with
- * the parameters set on this {@code Builder}.
- *
- * @return a new successfully initialized {@link AudioTrack.TunerConfiguration}.
- * @throws UnsupportedOperationException if the parameters set on the
- * {@code Builder} are incompatible.
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
- public @NonNull TunerConfiguration build() {
- if (mContentId < 1 || mSyncId < 1) {
- throw new UnsupportedOperationException(
- "mContentId " + mContentId
- + " mSyncId " + mSyncId
- + " must be set");
- }
- return new TunerConfiguration(mContentId, mSyncId);
- }
- }
}
/**
@@ -3673,7 +3628,7 @@
// OnCodecFormatChangedListener notifications uses an instance
// of ListenerList to manage its listeners.
- private final Utils.ListenerList<AudioMetadata.ReadMap> mCodecFormatChangedListeners =
+ private final Utils.ListenerList<AudioMetadataReadMap> mCodecFormatChangedListeners =
new Utils.ListenerList();
/**
@@ -3684,13 +3639,13 @@
* Called when the compressed codec format changes.
*
* @param audioTrack is the {@code AudioTrack} instance associated with the codec.
- * @param info is a {@link AudioMetadata.ReadMap} of values which contains decoded format
+ * @param info is a {@link AudioMetadataReadMap} of values which contains decoded format
* changes reported by the codec. Not all hardware
* codecs indicate codec format changes. Acceptable keys are taken from
* {@code AudioMetadata.Format.KEY_*} range, with the associated value type.
*/
void onCodecFormatChanged(
- @NonNull AudioTrack audioTrack, @Nullable AudioMetadata.ReadMap info);
+ @NonNull AudioTrack audioTrack, @Nullable AudioMetadataReadMap info);
}
/**
@@ -3708,7 +3663,7 @@
mCodecFormatChangedListeners.add(
listener, /* key for removal */
executor,
- (int eventCode, AudioMetadata.ReadMap readMap) -> {
+ (int eventCode, AudioMetadataReadMap readMap) -> {
// eventCode is unused by this implementation.
listener.onCodecFormatChanged(this, readMap);
}
@@ -4067,7 +4022,7 @@
ByteBuffer buffer = (ByteBuffer) obj;
buffer.order(ByteOrder.nativeOrder());
buffer.rewind();
- AudioMetadata.ReadMap audioMetaData = AudioMetadata.fromByteBuffer(buffer);
+ AudioMetadataReadMap audioMetaData = AudioMetadata.fromByteBuffer(buffer);
if (audioMetaData == null) {
Log.e(TAG, "Unable to get audio metadata from byte buffer");
return;
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5f320cd..453a5d8 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -292,6 +292,8 @@
oneway void unregisterStrategyPreferredDeviceDispatcher(
IStrategyPreferredDeviceDispatcher dispatcher);
+ oneway void setRttEnabled(in boolean rttEnabled);
+
// WARNING: read warning at top of file, new methods that need to be used by native
// code via IAudioManager.h need to be added to the top section.
}
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 9985613..e5ad569 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -663,8 +663,8 @@
}
/**
- * Constructor for builder to create {@link MediaRoute2Info} with
- * existing {@link MediaRoute2Info} instance.
+ * Constructor for builder to create {@link MediaRoute2Info} with existing
+ * {@link MediaRoute2Info} instance.
*
* @param routeInfo the existing instance to copy data from.
*/
@@ -690,6 +690,38 @@
}
/**
+ * Constructor for builder to create {@link MediaRoute2Info} with existing
+ * {@link MediaRoute2Info} instance and replace ID with the given {@code id}.
+ *
+ * @param id The ID of the new route. Must not be empty.
+ * @param routeInfo the existing instance to copy data from.
+ * @hide
+ */
+ public Builder(@NonNull String id, @NonNull MediaRoute2Info routeInfo) {
+ if (TextUtils.isEmpty(id)) {
+ throw new IllegalArgumentException("id must not be empty");
+ }
+ Objects.requireNonNull(routeInfo, "routeInfo must not be null");
+
+ mId = id;
+ mName = routeInfo.mName;
+ mFeatures = new ArrayList<>(routeInfo.mFeatures);
+ mType = routeInfo.mType;
+ mIsSystem = routeInfo.mIsSystem;
+ mIconUri = routeInfo.mIconUri;
+ mDescription = routeInfo.mDescription;
+ mConnectionState = routeInfo.mConnectionState;
+ mClientPackageName = routeInfo.mClientPackageName;
+ mVolumeHandling = routeInfo.mVolumeHandling;
+ mVolumeMax = routeInfo.mVolumeMax;
+ mVolume = routeInfo.mVolume;
+ if (routeInfo.mExtras != null) {
+ mExtras = new Bundle(routeInfo.mExtras);
+ }
+ mProviderId = routeInfo.mProviderId;
+ }
+
+ /**
* Adds a feature for the route.
* @param feature a feature that the route has. May be one of predefined features
* such as {@link #FEATURE_LIVE_AUDIO}, {@link #FEATURE_LIVE_VIDEO} or
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index 6a8483c..7d51b10 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -211,7 +211,7 @@
*/
@NonNull
public UUID getModelUuid() {
- return mGenericSoundModel.uuid;
+ return mGenericSoundModel.getUuid();
}
/**
@@ -221,7 +221,7 @@
*/
@NonNull
public UUID getVendorUuid() {
- return mGenericSoundModel.vendorUuid;
+ return mGenericSoundModel.getVendorUuid();
}
/**
@@ -230,7 +230,7 @@
* @return Version associated with the model
*/
public int getVersion() {
- return mGenericSoundModel.version;
+ return mGenericSoundModel.getVersion();
}
/**
@@ -240,7 +240,7 @@
*/
@Nullable
public byte[] getModelData() {
- return mGenericSoundModel.data;
+ return mGenericSoundModel.getData();
}
/**
@@ -307,7 +307,7 @@
}
try {
- switch (soundModel.type) {
+ switch (soundModel.getType()) {
case SoundModel.TYPE_GENERIC_SOUND:
return mSoundTriggerService.loadGenericSoundModel(
(GenericSoundModel) soundModel);
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java
index ea95a01..c51c8fa 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java
@@ -22,24 +22,41 @@
import java.io.IOException;
/**
- * This is an abstract base class that decodes a packet buffer and passes it to a
- * {@link android.media.midi.MidiReceiver}
+ * This is an abstract base class that decodes a BLE-MIDI packet
+ * buffer and passes it to a {@link android.media.midi.MidiReceiver}
*/
public class BluetoothPacketDecoder extends PacketDecoder {
private static final String TAG = "BluetoothPacketDecoder";
private final byte[] mBuffer;
+ private int mBytesInBuffer;
private MidiBtleTimeTracker mTimeTracker;
- private final int TIMESTAMP_MASK_HIGH = 0x1F80;
- private final int TIMESTAMP_MASK_LOW = 0x7F;
- private final int HEADER_TIMESTAMP_MASK = 0x3F;
+ private int mLowTimestamp;
+ private long mNanoTimestamp;
+
+ private static final int TIMESTAMP_MASK_HIGH = 0x1F80; // top 7 bits
+ private static final int TIMESTAMP_MASK_LOW = 0x7F; // bottom 7 bits
+ private static final int HEADER_TIMESTAMP_MASK = 0x3F; // bottom 6 bits
public BluetoothPacketDecoder(int maxPacketSize) {
mBuffer = new byte[maxPacketSize];
}
+ private void flushOutput(MidiReceiver receiver) {
+ if (mBytesInBuffer > 0) {
+ try {
+ receiver.send(mBuffer, 0, mBytesInBuffer, mNanoTimestamp);
+ } catch (IOException e) {
+ // ???
+ }
+ mBytesInBuffer = 0;
+ }
+ }
+
+ // NOTE: this code allows running status across packets,
+ // although the specification does not allow that.
@Override
public void decodePacket(byte[] buffer, MidiReceiver receiver) {
if (mTimeTracker == null) {
@@ -47,14 +64,11 @@
}
int length = buffer.length;
-
- // NOTE his code allows running status across packets,
- // although the specification does not allow that.
-
if (length < 1) {
Log.e(TAG, "empty packet");
return;
}
+
byte header = buffer[0];
if ((header & 0xC0) != 0x80) {
Log.e(TAG, "packet does not start with header");
@@ -64,52 +78,46 @@
// shift bits 0 - 5 to bits 7 - 12
int highTimestamp = (header & HEADER_TIMESTAMP_MASK) << 7;
boolean lastWasTimestamp = false;
- int dataCount = 0;
int previousLowTimestamp = 0;
- long nanoTimestamp = 0;
- int currentTimestamp = 0;
+ int currentTimestamp = highTimestamp | mLowTimestamp;
- // iterate through the rest of the packet, separating MIDI data from timestamps
+ // Iterate through the rest of the packet, separating MIDI data from timestamps.
for (int i = 1; i < buffer.length; i++) {
byte b = buffer[i];
+ // Is this a timestamp byte?
if ((b & 0x80) != 0 && !lastWasTimestamp) {
lastWasTimestamp = true;
- int lowTimestamp = b & TIMESTAMP_MASK_LOW;
- if (lowTimestamp < previousLowTimestamp) {
+ mLowTimestamp = b & TIMESTAMP_MASK_LOW;
+
+ // If the low timestamp byte wraps within the packet then
+ // increment the high timestamp byte.
+ if (mLowTimestamp < previousLowTimestamp) {
highTimestamp = (highTimestamp + 0x0080) & TIMESTAMP_MASK_HIGH;
}
- previousLowTimestamp = lowTimestamp;
+ previousLowTimestamp = mLowTimestamp;
- int newTimestamp = highTimestamp | lowTimestamp;
+ // If the timestamp advances then send any pending data.
+ int newTimestamp = highTimestamp | mLowTimestamp;
if (newTimestamp != currentTimestamp) {
- if (dataCount > 0) {
- // send previous message separately since it has a different timestamp
- try {
- receiver.send(mBuffer, 0, dataCount, nanoTimestamp);
- } catch (IOException e) {
- // ???
- }
- dataCount = 0;
- }
+ // Send previous message separately since it has a different timestamp.
+ flushOutput(receiver);
currentTimestamp = newTimestamp;
}
- // calculate nanoTimestamp
+ // Calculate MIDI nanosecond timestamp from BLE timestamp.
long now = System.nanoTime();
- nanoTimestamp = mTimeTracker.convertTimestampToNanotime(currentTimestamp, now);
+ mNanoTimestamp = mTimeTracker.convertTimestampToNanotime(currentTimestamp, now);
} else {
lastWasTimestamp = false;
- mBuffer[dataCount++] = b;
+ // Flush if full before adding more data.
+ if (mBytesInBuffer == mBuffer.length) {
+ flushOutput(receiver);
+ }
+ mBuffer[mBytesInBuffer++] = b;
}
}
- if (dataCount > 0) {
- try {
- receiver.send(mBuffer, 0, dataCount, nanoTimestamp);
- } catch (IOException e) {
- // ???
- }
- }
+ flushOutput(receiver);
}
}
diff --git a/packages/CtsShim/build/Android.bp b/packages/CtsShim/build/Android.bp
index ede1fab..587109d 100644
--- a/packages/CtsShim/build/Android.bp
+++ b/packages/CtsShim/build/Android.bp
@@ -100,6 +100,20 @@
}
//##########################################################
+// Variant: Non Privileged app upgrade which is malformed
+android_app {
+ name: "CtsShimTargetPSdk",
+ sdk_version: "current",
+ optimize: {
+ enabled: false,
+ },
+ dex_preopt: {
+ enabled: false,
+ },
+ manifest: "shim/AndroidManifestTargetPSdk.xml"
+}
+
+//##########################################################
// Variant: System app
android_app {
diff --git a/packages/CtsShim/build/shim/AndroidManifestTargetPSdk.xml b/packages/CtsShim/build/shim/AndroidManifestTargetPSdk.xml
new file mode 100644
index 0000000..2e9381a
--- /dev/null
+++ b/packages/CtsShim/build/shim/AndroidManifestTargetPSdk.xml
@@ -0,0 +1,22 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.apk.cts.shim"
+ android:versionCode="2"
+ android:versionName="2.0" >
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="P" />
+</manifest>
\ No newline at end of file
diff --git a/packages/OsuLogin/Android.bp b/packages/OsuLogin/Android.bp
index cd9cd1e..d7e36b1 100644
--- a/packages/OsuLogin/Android.bp
+++ b/packages/OsuLogin/Android.bp
@@ -4,9 +4,14 @@
resource_dirs: ["res"],
srcs: ["src/**/*.java"],
sdk_version: "system_current",
-
+ certificate: ":com.android.hotspot2.osulogin.certificate",
apex_available: [
"com.android.wifi",
"test_com.android.wifi",
],
}
+
+android_app_certificate {
+ name: "com.android.hotspot2.osulogin.certificate",
+ certificate: "certs/com.android.hotspot2.osulogin"
+}
diff --git a/packages/OsuLogin/certs/com.android.hotspot2.osulogin.pk8 b/packages/OsuLogin/certs/com.android.hotspot2.osulogin.pk8
new file mode 100644
index 0000000..87fd622
--- /dev/null
+++ b/packages/OsuLogin/certs/com.android.hotspot2.osulogin.pk8
Binary files differ
diff --git a/packages/OsuLogin/certs/com.android.hotspot2.osulogin.x509.pem b/packages/OsuLogin/certs/com.android.hotspot2.osulogin.x509.pem
new file mode 100644
index 0000000..1dfe701
--- /dev/null
+++ b/packages/OsuLogin/certs/com.android.hotspot2.osulogin.x509.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGDzCCA/egAwIBAgIUHzkh0UCF/H+1mZZp0ROX4nXKOUowDQYJKoZIhvcNAQEL
+BQAwgZUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
+b2lkMREwDwYDVQQDDAhPc3VMb2dpbjEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBh
+bmRyb2lkLmNvbTAgFw0yMDAzMjUwMjQ5MTNaGA80NzU4MDIxOTAyNDkxM1owgZUx
+CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3Vu
+dGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRyb2lkMREw
+DwYDVQQDDAhPc3VMb2dpbjEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lk
+LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMJDnjAeIZ2KUvKc
+ONwxuzIhLvXr6LRm+Uz0ebjz++5IzQJLwr/COPBG9zbIm8izj2acp+l4WVEYT6I4
+Es5LEp556ySCuZx8IjOd0Zd6NCdaKmYouDTjYTrELWUlZjfA7Km2L5x2M6ArnDO5
+zJ1BIsQ06S3C7iR3ktAQ1cFdidg6Ha2gainS0A1JKN3kL9BL1pvHRLzWZX4gsNhB
+C/6Ue3W3Sx2JRQkaaLksDdoKq0QswEk5tGfKbVr9+hHv/pztaaqEXSeV6f305cAx
+Hzd6+QJ8f8AJz2Rhnv43y72UO8b02CSP3laUj8geidR8XXw+R7Kzu8NfFDL7uVIh
+ktPaBxfWPNYtedp3JrGeZhkzljsushY+bVHECEzROhY2CiUZBEn+wwZLWe2W7oee
+VCL1EZBYctK5CfrrV6x0wvbBUF/ViwV+2LQXQNp08xB8bJBqoBn4KZjK0tTN86Dq
+qRALyoVIVh5VDU9Wbi3vrJb0/9TEQtMjuo0DS3hdtnowdRyAyhwbQHO26dqnnzBI
+XtTAve4RkOwnb8QzZde56qvRgweDE9Im1jpx4E+MMGqVYs8Txurmd/t6bCjTvp1P
+4i88crk/zqCoHEQEbiaNdfkULJAWg9wqxPjqPCTVNtOXoJwuHsNymQVSztIUSySz
+ZQ8Trk0ApqQf8yH2mjM6HJJZoNpBAgMBAAGjUzBRMB0GA1UdDgQWBBRdpduh1P+I
+BMbg5S4n1kbj5hQsOzAfBgNVHSMEGDAWgBRdpduh1P+IBMbg5S4n1kbj5hQsOzAP
+BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQB+FzSuoA7LCvn8l86V
+sSI4lH1KLLH+wrXp20w/wYcBY+s4hYPpAJ8YbEMOT9uibK/HpEWYFqiVCqk4gKXr
+Qraxvmtqq0WNSwkjeopTYlZeBzTC/If3UoOCp7KCfMdydIcxvk6LNokMWWqSCNP8
+QiD872XuBvj/uQeBsbHZTqruqPnu+LZwpuHFVRp/Pyj9rT61PsvGitb7q/chW0G7
+7csHOc5q2223LKlNknPsfbcR6nVEg4KfN7kPKny8iJtl2pdbfBjFDp+73nzW8qZU
+5JWO5nWL7cJh4mt5sPGrzpt/Hf8/Dngg69sImRqjv/6/wCV0pEmmNjKJkXcMaZ0T
+2TSs+A7K6l15NYk8exkMymTU7jk+iDud3tnQ68YHf/A9pDu15OCw6U/pTgOgu9co
+rBLLhGV0Tb6XAnsWKe9tsLcumQXU5ZUn9m5VJl58wQHNhUqpT7L0fWtpiTMTStVA
+/yZbndPO4SbjR5rjcAk1xge8lyIIp0WBWmwoQ/1y4DXF/yPaX733wO7uWUljgKuy
+MM/zM4zklB8nFjXfPNf3j24Bzqmy7rqy4XB64enVmYQ2mVNqfwXvINoo2XOrAmj/
+bhSWXiCFltJFM7fmJGOMEEHBt9QfbmCgmM4aoWMgH7P+HxGW+Vc3tGixBbsxNRC+
+/VrPAINQV4x5q8zGYNQBqNFn/A==
+-----END CERTIFICATE-----
diff --git a/packages/OsuLogin/certs/key.pem b/packages/OsuLogin/certs/key.pem
new file mode 100644
index 0000000..f560a8d
--- /dev/null
+++ b/packages/OsuLogin/certs/key.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDCQ54wHiGdilLy
+nDjcMbsyIS716+i0ZvlM9Hm48/vuSM0CS8K/wjjwRvc2yJvIs49mnKfpeFlRGE+i
+OBLOSxKeeeskgrmcfCIzndGXejQnWipmKLg042E6xC1lJWY3wOypti+cdjOgK5wz
+ucydQSLENOktwu4kd5LQENXBXYnYOh2toGop0tANSSjd5C/QS9abx0S81mV+ILDY
+QQv+lHt1t0sdiUUJGmi5LA3aCqtELMBJObRnym1a/foR7/6c7WmqhF0nlen99OXA
+MR83evkCfH/ACc9kYZ7+N8u9lDvG9Ngkj95WlI/IHonUfF18Pkeys7vDXxQy+7lS
+IZLT2gcX1jzWLXnadyaxnmYZM5Y7LrIWPm1RxAhM0ToWNgolGQRJ/sMGS1ntlu6H
+nlQi9RGQWHLSuQn661esdML2wVBf1YsFfti0F0DadPMQfGyQaqAZ+CmYytLUzfOg
+6qkQC8qFSFYeVQ1PVm4t76yW9P/UxELTI7qNA0t4XbZ6MHUcgMocG0Bztunap58w
+SF7UwL3uEZDsJ2/EM2XXueqr0YMHgxPSJtY6ceBPjDBqlWLPE8bq5nf7emwo076d
+T+IvPHK5P86gqBxEBG4mjXX5FCyQFoPcKsT46jwk1TbTl6CcLh7DcpkFUs7SFEsk
+s2UPE65NAKakH/Mh9pozOhySWaDaQQIDAQABAoICAGgX7XKhIqgVD59aoIk0yLby
+2wQBdf780ocu1O6LJiqnrdqWF/PCsdnmXN9pHTitJqD4Pm03BL0Uhs9ItqL9zStH
+7vzwY177kSQRY9aEL+AKS3/UP+hvEpF3v09ce+pSIT5LFjYDjGQ+GgQJgh+dYHC8
+XVodAphdzjhZXQCxC4TmlzKLK3ffs4X69r/3XruBd6yfWTDKvTWZdMlcCX5Pt9v6
+7HAWNvzKvuTCO2Xjo6PzStGx7v5SlMhWISJtdARInv80z+m/RdPD3zxd1flXloiD
+h7yyRQPn31cfNLgP7vwMBKmKwbuo/WZhHr/SKBHEGY0jC/CDSQKMqd/dh5ynTnbC
+vi/qjKFIHofmhzgQ+fiHMeMsAO1c9eYs8a6bDeJjhA5qJP1HjSie9Ss9z94mp6Ww
+TRkU93yVX04DU4TCCf0IcFpKdbtKp84i6iLV9lKGh9juM42hSOFUV6bhxmlJ9zvM
+yl7vfhhuFHy1SypmaK/oJ+nwac4vIMaHCX9ifl6hm/z4PrGFSYJGQoJtVOz0vT15
+lSwCJVdHkGAe0LI+3iFn5jJlluD7TqsLmZLxqTTmzDZ3U9WhAslmn5TcZd92mL0i
+ZVTfCkjyl1wUHeif2992oTUH6CFZ1jKd8xwdWvyKkvQcjhiS9GUsm7j6jolR/QI7
+VPQlocM/vCCusrMWnR7xAoIBAQDv9O8kboz6WzN6Xw5UC7MWpi2jZg1bTs/uKcfz
+biAEC96iJQ33YSkYi6QzV4jSaackU99vGkHbQIdaBTkudz+FK5XqH0auImB2xxcR
+Xu9G2j2fhzESchVTtOnotVgjiuv18SLZ/GQoSIccs0QxcisPiTa5Ij9pl8xVoS6J
+sxfqAe15hASqLh+9Ula3+Orb1kCkqK0UwU0nM9nfUH88BKvUwQIMA7kipTA8jJog
+MJOlYPQUGxkltlim8Vip//P336E7CWT6fWbfo62US6IEu6HcC6T8u8jcLjIKsmjJ
+YJyqrepZqAVMPlv2Z+mNhxRR0ct6blfjJSrEZEtxBRn98kZ1AoIBAQDPQJ1z7Mfy
+AOfjSO6Dlfr7V9SWmGvexosH0gu6H8KO+n1/ZPH5fHGt7ORubUDhkNI/fqZK0Hls
+Q9Jwgq1QI9UwMTogF8DgmZ6L6jiXhUScIk0BFhUxOBoplugaI0jdTW350D2quFUJ
+LjYo+VcRapTfXXVehHSjbUh3nmTWj0WboA+//7xq8q9KHPb1Sbiwjf7N1iYD5R8p
+PaaG0DMET+l90bxI+QVX1enwjZGcFjo8VI+qXGGkpB/1zK5yWm29ZWypLw8TZreM
+7rLUdBY1/m7MB54zOaJ2jSsxLQSXIVSGPI1ugkmFr6OxeuLdcCLN4yca3+HYHewa
+w3GCBP3kfYMdAoIBAAxG0slhYpMYgWy8WkZQhuwcum8GtJ48TQUZXCKHOtoaJVzU
+Wn+SmACqfE8oJlblkuiX5fGQPVhTV9lyNPe8oCJXFYdx7DLSjW7mRrbbzZApcEeu
+KgOQlKjAs8r1JDpFTEc7/BV9BT7OXyNHxLBm7+8OjR8xsl7bplenNHNVF18glB7I
+c1ilnXgZM1icQp/WuV3zR0+tiB3+WCJFwwy2DHiJG2qz8g/ktbATXXtSIOuwJyy0
+Kjg0uRppdKjV8Ix5A426sFDkg5PjkujoabSmSOSyL9HCZcdmEadcc2ICMGHHHhtS
+Lls1QY08ycU06QQ6oJd198cmSqbbnsR8h1TnxVUCggEBAI2zF/QSiAImLGVxj+HX
+wWnneyobvGTsSlJmgi4XWOZ4zSU011xEgVTxCp2VhS6z3YwcA4ZTUzF6jX7vWZ/Z
+YAE7JwqaMv1dCtGOqnKuY2J88Tk05/hm6zxUOQzl4wOr1O1gO0lmDn3gYpdRIv59
+aJvvQjgFR9oU9d8TJM6t1mG45gvXxfM5Si/Z7d93MBdGflgteoBfPxbrV9gEsVzZ
+ZkLoC1u5JrYPQ4t8v3mAmQB2sGNCFmCC9ncQIpV8zlsX5VsnGZ+iMwzghtRLKoRw
+GUDWVIuhdDqp+kX9CY5q82d0Lx7HZY1JsRm/cy0DZkhubmYpfDhO/QavagQDdbOr
+POECggEAXOliqX4yFvy6USXihHVM44s63gK+yH0+0iRppqoB3+E5tDyhvvvBMPLZ
+7EBkhd7ILTDXbc0c8nSl8I/556YSlIaOB4Xbf4UQbsmD4fNGEnNWFbCzcEWYOjpQ
+5QyXjIzK/k8eg22OZlC3XNjGHgb/mA5f+v2enGQNuy7WRTl1mKYZB2h/2p6xy+jV
+CGhd4btB2bOu+1XR/B2KFvI5NdtPPti05LmsYgsU00yYJfQkpc7VvOSH5Jyy3eZL
+L9xTAy7NWBQ3LGdIpX+V1jcn3SzVits0m6hOUCtJLT1snMXAKFweTvWAQynuGomc
+VPf88ITMTOBjOH6YC8jKd/n2lVWLjw==
+-----END PRIVATE KEY-----
diff --git a/packages/SettingsLib/SearchWidget/res/values-es-rUS/strings.xml b/packages/SettingsLib/SearchWidget/res/values-es-rUS/strings.xml
index ed549db..9b735fe 100644
--- a/packages/SettingsLib/SearchWidget/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-es-rUS/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="search_menu" msgid="1914043873178389845">"Buscar en la configuración"</string>
+ <string name="search_menu" msgid="1914043873178389845">"Buscar configuraciones"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 88f996a..944294b 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-adres en -poort"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skandeer QR-kode"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Bind toestel oor Wi-Fi saam deur \'n QR-kode te skandeer"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Koppel asseblief aan \'n Wi-Fi-netwerk"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Kortpad na foutverslag"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Wys \'n knoppie in die kragkieslys om \'n foutverslag te doen"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rooi-groen)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blou-geel)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurregstelling"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Kleurregstelling stel jou in staat om te verstel hoe kleure op jou toestel vertoon word"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Sal waarskynlik hou tot omtrent <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Sal waarskynlik hou tot omtrent <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Tot <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Battery kan teen <xliff:g id="TIME">%1$s</xliff:g> afloop"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Minder as <xliff:g id="THRESHOLD">%1$s</xliff:g> oor"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Minder as <xliff:g id="THRESHOLD">%1$s</xliff:g> oor (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Meer as <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Foonluidspreker"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kan nie koppel nie. Skakel toestel af en weer aan"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedrade oudiotoestel"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Hulp en terugvoer"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Berging"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Gedeelde data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Bekyk en wysig gedeelde data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Gedeelde data-ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Verval op <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Programme wat data deel"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Geen beskrywing is deur die program voorsien nie."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Huurkontrak verval op <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Vee gedeelde data uit?"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Is jy seker jy wil hierdie gedeelde data uitvee?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Gebruikers het hul eie programme en inhoud"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Jy kan toegang tot programme en inhoud op jou rekening beperk"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Gebruiker"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Beperkte profiel"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Voeg nuwe gebruiker by?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Jy kan hierdie toestel met ander mense deel deur bykomende gebruikers te skep. Elke gebruiker het sy eie spasie wat hulle kan pasmaak met programme, muurpapier en so meer. Gebruikers kan ook toestelinstellings wat almal raak, soos Wi-Fi, aanpas.\n\nWanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul eie spasie opstel.\n\nEnige gebruiker kan programme vir alle ander gebruikers opdateer. Toeganklikheidinstellings en -dienste sal dalk nie na die nuwe gebruiker oorgedra word nie."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Wanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul spasie opstel.\n\nEnige gebruiker kan programme vir al die ander gebruikers opdateer."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Moet die gebruiker nou opgestel word?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Maak seker die persoon is beskikbaar om die toestel te vat en hul spasie op te stel"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Stel profiel nou op?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Stel nou op"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Nie nou nie"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Voeg by"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nuwe gebruiker"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Nuwe profiel"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Gebruikerinligting"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profiel-inligting"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Voordat jy \'n beperkte profiel kan skep, moet jy \'n skermslot opstel om jou programme en persoonlike data te beskerm."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Stel slot op"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index a402901..0a7b045 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"የአይፒ አድራሻ እና ወደብ"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR ኮድን ይቃኙ"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"የQR ኮድ በመጠቀም መሣሪያን በመቃኘት በWi-Fi ላይ ያጣምሩ"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"እባክዎ ከWi-Fi አውታረ መረብ ጋር ያገናኙ"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb፣ ማረም፣ ግንባታ"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"የሳንካ ሪፖርት አቋራጭ"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"የሳንካ ሪፖርት ለመውሰድ በሃይል ምናሌ ውስጥ አዝራር አሳይ"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ፕሮታኖማሊ (ቀይ-አረንጓዴ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ትራይታኖማሊ (ሰማያዊ-ቢጫ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"የቀለም ማስተካከያ"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ቀለም ማስተካከያ ቀለሞች በመሣሪያዎ ላይ እንዴት እንደሚታዩ እንዲያስተካክሉ ያስችሉዎታል"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ገደማ ቀርቷል"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"እስከ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ገደማ ድረስ መቆየት አለበት"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"እስከ <xliff:g id="TIME">%1$s</xliff:g> ገደማ መቆየት አለበት"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"እስከ <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"ባትሪ እስከ <xliff:g id="TIME">%1$s</xliff:g> ድረስ ሊያልቅ ይችላል"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"ከ<xliff:g id="THRESHOLD">%1$s</xliff:g> ያነሰ ይቀራል"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"ከ<xliff:g id="THRESHOLD">%1$s</xliff:g> ያነሰ ይቀራል (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"ከ<xliff:g id="TIME_REMAINING">%1$s</xliff:g> በላይ ይቀራል (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"የስልክ ድምጽ ማጉያ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"መገናኘት ላይ ችግር። መሳሪያውን ያጥፉት እና እንደገና ያብሩት"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ባለገመድ የኦዲዮ መሣሪያ"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"እገዛ እና ግብረመልስ"</string>
+ <string name="storage_category" msgid="2287342585424631813">"ማከማቻ"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"የተጋራ ውሂብ"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"የተጋራ ውሂብን ይመልከቱ እና ያሻሽሉ"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"የተጋራ ውሂብ መታወቂያ፦ <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"በ<xliff:g id="DATE">%s</xliff:g> ላይ የአገልግሎት ጊዜው ያበቃል"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"ውሂብ የሚጋሩ መተግበሪያዎች"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"በመተግበሪያው ምንም ዝርዝር መረጃ አልተሰጠም።"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"ኪራይ በ<xliff:g id="DATE">%s</xliff:g> ላይ አገልግሎት ጊዜው ያበቃል"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"የተጋራ ውሂብን ሰርዝ"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"ይህን የተጋራ ውሂብ ለመሰረዝ እንደሚፈልጉ እርግጠኛ ነዎት?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"ተጠቃሚዎች የራሳቸው መተግበሪያዎች እና ይዘት አሏቸው"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ከመለያዎ ላይ የመተግበሪያዎች መዳረሻን እና ይዘትን መገደብ ይችላሉ"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"ተጠቃሚ"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"የተገደበ መገለጫ"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"አዲስ ተጠቃሚ ይታከል?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"ተጨማሪ ተጠቃሚዎችን በመፍጠር ይህን መሣሪያ ለሌሎች ሰዎች ማጋራት ይችላሉ። እያንዳንዱ ተጠቃሚ በራሱ መተግበሪያዎች፣ ልጣፍ እና በመሳሰሉ ነገሮች ሊያበጀው የሚችል የራሱ ቦታ አለው። ተጠቃሚዎችም እንዲሁ እንደ Wi‑Fi ያሉ በሁሉም ሰው ላይ ተጽዕኖ ሊኖራቸው የሚችሉ የመሣሪያ ቅንብሮችን ማስተካከል ይችላሉ። \n\nእርስዎ አንድ አዲስ ተጠቃሚ ሲያክሉ ያ ሰው የራሱ ቦታ ማዘጋጀት አለበት።\n\nማንኛውም ተጠቃሚ መተግበሪያዎችን ለሌሎች ተጠቃሚዎች ሁሉ ሊያዘምኑ ይችላሉ።"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"እርስዎ አንድ አዲስ ተጠቃሚ ሲያክሉ ያ ሰው የራሱ ቦታ ማዘጋጀት አለበት።\n\nማንኛውም ተጠቃሚ መተግበሪያዎችን ለሌሎች ተጠቃሚዎች ሁሉ ሊያዘምን ይችላል።"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ተጠቃሚ አሁን ይዋቀር?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ግለሰቡ መሣሪያውን ወስደው ቦታቸውን ለማዋቀር እንደሚገኙ ያረጋግጡ"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"መገለጫ አሁን ይዋቀር?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"አሁን ያዋቅሩ"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"አሁን አይደለም"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"አክል"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"አዲስ ተጠቃሚ"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"አዲስ መገለጫ"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"የተጠቃሚ መረጃ"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"የመገለጫ መረጃ"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"የተገደበ መገለጫ መፍጠር ከመቻልዎ በፊት መተግበሪያዎችዎን እና የግል ውሂብዎን ለመጠበቅ ቁልፍ ማያ ገጽ ማዋቀር አለብዎት።"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"ቁልፍ አዘጋጅ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 7241c30..03dbfb0 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -418,8 +418,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"غطش الأحمر (الأحمر والأخضر)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"غمش الأزرق (الأزرق والأصفر)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"تصحيح الألوان"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"تسمح لك ميزة تصحيح الألوان بتعديل كيفية عرض الألوان على جهازك."</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"تم الاستبدال بـ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا"</string>
@@ -524,10 +523,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -538,4 +545,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"المستخدمون لديهم تطبيقات ومحتوى خاص بهم"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"يمكنك تقييد الدخول إلى التطبيقات والمحتوى من حسابك"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"المستخدم"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"ملف شخصي محظور"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"هل تريد إضافة مستخدم جديد؟"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"يمكنك مشاركة هذا الجهاز مع أشخاص آخرين من خلال إنشاء حسابات لمستخدمين إضافيين. وسيحصل كل مستخدم على مساحته الخاصة التي يمكنه تخصيصها بتطبيقاته وخلفياته التي يريدها وغيرها. كما يمكن للمستخدمين أيضًا ضبط إعدادات الجهاز مثل Wi-Fi والتي تؤثر في جميع المستخدمين.\n\nعند إضافة مستخدم جديد، عليه إعداد مساحته.\n\nيمكن لأي مستخدم تحديث التطبيقات لجميع المستخدمين الآخرين. وقد لا يتم نقل إعدادات وخدمات \"سهولة الاستخدام\" إلى المستخدم الجديد."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"عند إضافة مستخدم جديد، عليه إعداد مساحته.\n\nويمكن لأي مستخدم تحديث التطبيقات لجميع المستخدمين الآخرين."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"هل تريد إعداد المستخدم الآن؟"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"يُرجى التأكّد من أن الشخص يمكنه استخدام الجهاز الآن وإعداد مساحته."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"هل ترغب في إعداد ملف شخصي الآن؟"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"الإعداد الآن"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ليس الآن"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"إضافة"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"مستخدم جديد"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"ملف شخصي جديد"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"معلومات المستخدم"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"معلومات الملف الشخصي"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"قبل أن تتمكن من إنشاء ملف شخصي مقيد، يلزمك إعداد تأمين للشاشة لحماية تطبيقاتك وبياناتك الشخصية."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"تعيين التأمين"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index a2123d3..06df8f7 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"আইপি ঠিকনা & প’ৰ্ট"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"কিউআৰ ক’ড স্কেন কৰক"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"এটা কিউআৰ ক’ড স্কেন কৰি ৱাই-ফাইৰে ডিভাইচ পেয়াৰ কৰক"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"অনুগ্ৰহ কৰি এটা ৱাই-ফাই নেটৱর্কলৈ সংযোগ কৰক"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ডিবাগ, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"বাগ ৰিপৰ্টৰ শ্ৱৰ্টকাট"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"পাৱাৰ মেনুত বাগ প্ৰতিবেদন গ্ৰহণ কৰিবলৈ এটা বুটাম দেখুৱাওক"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"প্ৰ’টানোমালি (ৰঙা-সেউজীয়া)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ট্ৰাইটান\'মেলী (নীলা-হালধীয়া)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ৰং শুধৰণী"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ৰং শুধৰণি সুবিধাটোৰে আপোনাক আপোনাৰ ডিভাইচত ৰংবোৰ কেনেকৈ প্ৰদর্শন কৰা হয় সেয়া মিলাবলৈ দিয়ে"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g>ৰ দ্বাৰা অগ্ৰাহ্য কৰা হৈছে"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"প্রায় <xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"বেটাৰি আনুমানিকভাৱে <xliff:g id="TIME">%1$s</xliff:g> লৈকে চলিব (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"বেটাৰি আনুমানিকভাৱে <xliff:g id="TIME">%1$s</xliff:g> লৈকে চলিব"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> পৰ্যন্ত"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g>ৰ ভিতৰত বেটাৰী শেষ হ\'ব পাৰে"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g>তকৈও কম সময় বাকী আছে"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>তকৈও কম সময় বাকী আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>তকৈও বেছি সময় বাকী আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"ফ’নৰ স্পীকাৰ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"সংযোগ হোৱাত সমস্যা হৈছে। ডিভাইচটো অফ কৰি পুনৰ অন কৰক"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"তাঁৰযুক্ত অডিঅ’ ডিভাইচ"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"সহায় আৰু মতামত"</string>
+ <string name="storage_category" msgid="2287342585424631813">"ষ্ট’ৰেজ"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"শ্বেয়াৰ কৰা ডেটা"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"শ্বেয়াৰ কৰা ডেটা চাওক আৰু সংশোধন কৰক"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"শ্বেয়াৰ কৰা ডেটাৰ আইডি: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"<xliff:g id="DATE">%s</xliff:g>ত ম্যাদ উকলিব"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"ডেটা শ্বেয়াৰ কৰা এপ্সমূহ"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"এপ্টোৱে কোনো বিৱৰণ দিয়া নাই।"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"<xliff:g id="DATE">%s</xliff:g>ত লীজৰ ম্যাদ উকলিব"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"শ্বেয়াৰ কৰা ডেটা মচক"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"আপুনি এই শ্বেয়াৰ কৰা ডেটাখিনি মচিব বিচৰাটো নিশ্চিতনে?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"ব্যৱহাৰকাৰীসকলৰ নিজৰ এপ্ আৰু সমল থাকে"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"আপুনি নিজৰ একাউণ্টৰ পৰা এপ্ আৰু সমল চোৱা সুবিধাটো সীমাবদ্ধ কৰিব পাৰে"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"ব্যৱহাৰকাৰী"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"সীমিত প্ৰ\'ফাইল"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"নতুন ব্যৱহাৰকাৰী যোগ কৰিবনে?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"আপুনি অতিৰিক্ত ব্য়ৱহাৰকাৰীক যোগ কৰি এই ডিভাইচটো অন্য় ব্য়ক্তিৰ সৈতে শ্বেয়াৰ কৰিব পাৰে। প্ৰতিজন ব্য়ৱহাৰকাৰীৰ বাবে নিজাকৈ ঠাই আছে যাক তেওঁলোকে এপ্, ৱালপেপাৰ আৰু অন্য়ান্য় বস্তুৰ বাবে নিজৰ উপযোগিতা অনুযায়ী ব্য়ৱহাৰ কৰিব পাৰে। ব্য়ৱহাৰকাৰীসকলে সকলোকে প্ৰভাৱান্বিত কৰা ৱাই-ফাইৰ নিচিনা ডিভাইচৰ ছেটিংসমূহ সাল-সলনি কৰিবও পাৰে।\n\nআপুনি যেতিয়া কোনো নতুন ব্য়ৱহাৰকাৰীক যোগ কৰে সেই ব্য়ক্তিজনে নিজেই নিজৰ বাবে ঠাই ছেট আপ কৰিব লাগিব।\n\nসকলো ব্য়ৱহাৰকাৰীএ অন্য় ব্য়ৱহাৰকাৰীৰ বাবে এপসমূহ আপডে’ট কৰিব পাৰে। সাধ্য় সুবিধাসমূহৰ ছেটিং আৰু সেৱাসমূহ নতুন ব্য়ৱহাৰকাৰীলৈ স্থানান্তৰ নহ\'বও পাৰে।"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"আপুনি যেতিয়া এজন নতুন ব্যৱহাৰকাৰী যোগ কৰে, তেওঁ নিজৰ ঠাই ছেট আপ কৰা প্ৰয়োজন।\n\nযিকোনো ব্যৱহাৰকাৰীয়ে সকলো ব্যৱহাৰকাৰীৰ বাবে এপ্ আপডেইট কৰিব পাৰে।"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ব্যৱহাৰকাৰী এতিয়া ছেট আপ কৰিবনে?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ডিভাইচটো লৈ নিজৰ ঠাই ছেটআপ কৰিবলৈ নতুন ব্যৱহাৰকাৰী উপলব্ধ থকাটো নিশ্চিত কৰক"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"এতিয়া প্ৰ\'ফাইল ছেট আপ কৰিবনে?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"এতিয়াই ছেট আপ কৰক"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"এতিয়া নহয়"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"যোগ কৰক"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"নতুন ব্যৱহাৰকাৰী"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"নতুন প্ৰ\'ফাইল"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"ব্যৱহাৰকাৰীৰ তথ্য"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"প্ৰ\'ফাইলৰ তথ্য"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"আপুনি সীমিত প্ৰ\'ফাইল এটা সৃষ্টি কৰাৰ আগেয়ে, আপোনাৰ ব্যক্তিগত ডেটা আৰু এপবিলাকক সুৰক্ষিত কৰিবলৈ স্ক্ৰীণ লক এটা নিৰ্ধাৰণ কৰিব লাগিব।"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"লক ছেট কৰক"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 53fe7a8..56f3640 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ünvanı və Port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR kodu skanlayın"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR Kodu skanlamaqla cihazı Wi‑Fi vasitəsilə cütləşdirin"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi şəbəkəsinə qoşulun"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Baq raportu qısa yolu"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Baq raportunu götürmək üçün qidalanma menyusunda düyməni göstərin"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qırmızı-yaşıl)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (göy-sarı)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rəng düzəlişi"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Rəng korreksiyası sizə rənglərin cihazınızda necə göstərilməsini tənzimləmək imkanı verir"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> olana qədər"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batareya <xliff:g id="TIME">%1$s</xliff:g> radələrinə qədər boşala bilər"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Qalan vaxt <xliff:g id="THRESHOLD">%1$s</xliff:g> və daha azdır"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Qalan vaxt <xliff:g id="THRESHOLD">%1$s</xliff:g> və daha azdır (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Qalan vaxt <xliff:g id="TIME_REMAINING">%1$s</xliff:g> və daha çoxdur (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon dinamiki"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Qoşulmaqla bağlı problem. Cihazı deaktiv edin, sonra yenidən aktiv edin"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio cihaz"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Yardım və rəy"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Yaddaş"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Paylaşılan data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Paylaşılan dataya baxın və ona dəyişiklik edin"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Paylaşılan data ID\'si: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"<xliff:g id="DATE">%s</xliff:g> tarixində müddəti bitir"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Data paylaşan tətbiqlər"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Tətbiq tərəfindən heç bir təsvir təmin edilməyib."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"İcarə müddəti <xliff:g id="DATE">%s</xliff:g> tarixində bitir"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Paylaşılan datanı silin"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Bu paylaşılan datanı silmək istədiyinizə əminsiniz?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"İstifadəçilərin öz tətbiqləri və məzmunları var"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Siz hesabınızdan tətbiq və kontentə girişi məhdudlaşdıra bilərsiniz."</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"İstifadəçi"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Məhdudlaşdırılmış profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Yeni istifadəçi əlavə edilsin?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Əlavə istifadəçilər yaratmaqla bu cihazı digərləri ilə paylaşa bilərsiniz. Hər bir istifadəçinin tətbiq, divar kağızı və daha çoxu ilə fərdiləşdirə biləcəyi fərdi məkanları olacaq. İstifadəçilər hər kəsə təsir edən Wi‑Fi kimi cihaz ayarlarını da tənzimləyə biləcək.\n\nYeni istifadəçi əlavə etdiyiniz zaman həmin istifadəçi öz məkanını ayarlamalıdır.\n\nİstənilən istifadəçi tətbiqləri digər bütün istifadəçilər üçün güncəlləyə bilər. Əlçatımlılıq ayarları və xidmətlər yeni istifadəçiyə transfer edilməyə bilər."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Yeni istifadəçi əlavə etdiyiniz zaman həmin şəxs öz yerini quraşdırmalıdır.\n\nİstənilən istifadəçi bütün digər istifadəçilərdən olan tətbiqləri güncəlləşdirə bilər."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"İstifadəçi indi ayarlansın?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Şəxsin cihazı götürə bilməsinə və yerini quraşdıra bilməsinə əmin olun"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Profil indi quraşdırılsın?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"İndi ayarla"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"İndi yox"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Əlavə edin"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Yeni istifadəçi"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Yeni profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"İstifadəçi infosu"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profil info"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Məhdudlaşdırılmış profil yaratmadan öncə, Siz tətbiqlərinizi və şəxsi datanızı qorumaq üçün ekran kilidi quraşdırmalısınız."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Kilid ayarlayın"</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 ac0c254..e81dbc3 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresa i port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skeniraj QR kôd"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Uparite uređaj pomoću Wi‑Fi mreže ili tako što ćete skenirati QR kôd"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Povežite se na Wi-Fi mrežu"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, otklanjanje grešaka, programer"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Prečica za izveštaj o greškama"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikaži dugme u meniju napajanja za pravljenje izveštaja o greškama"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno-zeleno)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo-žuto)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcija boja"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korekcija boja vam omogućava da prilagodite način na koji se boje prikazuju na uređaju"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Trajaće približno do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Trajaće približno do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Baterija će se možda isprazniti do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -513,26 +510,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvučnik telefona"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem pri povezivanju. Isključite uređaj, pa ga ponovo uključite"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Memorijski prostor"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Deljeni podaci"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Pregledajte i izmenite deljene podatke"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID deljenih podataka: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Ističe: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplikacije koje dele podatke"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"U aplikaciji nije naveden nijedan opis."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Iznajmljivanje ističe: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Izbriši deljene podatke"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Želite li stvarno da izbrišete ove deljene podatke?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Korisnici imaju sopstvene aplikacije i sadržaj"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Možete da ograničite pristup na aplikacije i sadržaj sa naloga"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Korisnik"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Ograničeni profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Dodajete novog korisnika?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Ovaj uređaj možete da delite sa drugim ljudima ako napravite još korisnika. Svaki korisnik ima sopstveni prostor, koji može da prilagođava pomoću aplikacija, pozadine i slično. Korisnici mogu da prilagođavaju i podešavanja uređaja koja utiču na svakoga, poput Wi‑Fi-ja.\n\nKada dodate novog korisnika, ta osoba treba da podesi sopstveni prostor.\n\nSvaki korisnik može da ažurira aplikacije za sve ostale korisnike. Podešavanja i usluge pristupačnosti ne mogu da se prenose na novog korisnika."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Kada dodate novog korisnika, ta osoba treba da podesi sopstveni prostor.\n\nSvaki korisnik može da ažurira aplikacije za sve ostale korisnike."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Podešavate korisnika?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Ta osoba treba da uzme uređaj i podesi svoj prostor"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Želite li da odmah podesite profil?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Podesi"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ne sada"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Dodavanje"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Novi korisnik"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Novi profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Podaci o korisniku"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Podaci o profilu"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Da biste mogli da napravite ograničeni profil, treba da podesite zaključavanje ekrana da biste zaštitili aplikacije i lične podatke."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Podesi zaključavanje"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 49584eb..01f3eed 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-адрас і порт"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Сканіраваць QR-код"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Спалучыць прыладу праз Wi‑Fi шляхам сканіравання QR-кода"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Падключыцеся да сеткі Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, адладка, распрацоўшчык"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Ярлык для справаздачы пра памылкі"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Паказаць кнопку для прыняцця справаздачы пра памылку ў меню сілкавання"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Пратанамалія (чырвоны-зялёны)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Трытанамалія (сіні-жоўты)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Карэкцыя колеру"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Карэкцыя колеру дазволіць вам наладзіць адлюстраванне колераў на экране прылады"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Зараду хопіць прыблізна на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Зараду (<xliff:g id="LEVEL">%2$s</xliff:g>) хопіць прыблізна да <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Зараду хопіць прыблізна да <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Да <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Акумулятар разрадзіцца ў <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Засталося менш за <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Узровень зараду батарэі: <xliff:g id="LEVEL">%2$s</xliff:g> (хопіць менш чым на <xliff:g id="THRESHOLD">%1$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Узровень зараду батарэі: <xliff:g id="LEVEL">%2$s</xliff:g> (хопіць больш чым на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>)"</string>
@@ -514,26 +511,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Дынамік тэлефона"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Праблема з падключэннем. Выключыце і зноў уключыце прыладу"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Правадная аўдыяпрылада"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Даведка і водгукі"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Сховішча"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Абагуленыя даныя"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Прагляд і змяненне абагуленых даных"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Ідэнтыфікатар абагуленых даных: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Тэрмін дзеяння заканчваецца <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Праграмы, якія абагульваюць даныя"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"У праграмы адсутнічае апісанне."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Тэрмін дзеяння арэнды завяршаецца <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Выдаліць абагуленыя даныя"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Сапраўды выдаліць гэтыя абагуленыя даныя?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Карыстальнікі маюць свае ўласныя прыкладанні і змесцiва"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Вы можаце абмяжоўваць доступ да прыкладанняў і змесціва са свайго ўліковага запісу"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Карыстальнік"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Абмежаваны профiль"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Дадаць новага карыстальніка?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Вы можаце адкрыць доступ да гэтай прылады іншым людзям шляхам стварэння дадатковых карыстальнікаў. Кожны карыстальнік мае свой уласны раздзел, на якім ён можа наладзіць свае праграмы, шпалеры і іншае. Карыстальнікі таксама могуць наладжваць параметры прылады, напрыклад Wi-Fi, якія ўплываюць на ўсіх.\n\nКалі вы дадаяце новага карыстальніка, ён павінен наладзіць свой раздзел.\n\nЛюбы карыстальнік можа абнаўляць праграмы для ўсіх астатніх карыстальнікаў. Спецыяльныя магчымасці наладжваюцца асабіста кожным карыстальнікам."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Пасля стварэння профіля яго трэба наладзіць.\n\nЛюбы карыстальнік прылады можа абнаўляць праграмы ўсіх іншых карыстальнікаў."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Наладзіць профіль?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Пераканайцеся, што чалавек мае магчымасць узяць прыладу і наладзіць свой раздзел"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Наладзiць профiль?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Наладзіць"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Не зараз"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Дадаць"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Новы карыстальнік"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Новы профiль"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Інфармацыя карыстальніка"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Звесткi профiлю"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Перш чым вы зможаце стварыць профіль з абмежаваннямi, вам трэба наладзіць блакiроўку экрана для абароны сваiх дадаткаў і асабістай інфармацыі."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Усталёўка блакiроўкi"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 20145b0..6e15f30 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP адрес и порт"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Сканиране на QR код"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Сдвояване на устройството през Wi‑Fi чрез сканиране на QR код"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Моля, свържете се с Wi-Fi мрежа"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, отстраняване на грешки, програмиране"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Пряк път за сигнал за програмна грешка"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"В менюто за захранване да се показва бутон за подаване на сигнал за програмна грешка"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (червено – зелено)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (синьо – жълто)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекция на цветове"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Корекцията на цветове ви позволява да коригирате това, как цветовете се показват на устройството ви"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Следва да издържи до около <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"До <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Батерията може да се изтощи до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Остава/т повече от <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Високоговорител на телефона"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"При свързването възникна проблем. Изключете устройството и го включете отново"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Аудиоустройство с кабел"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Помощ и отзиви"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Хранилище"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Споделени данни"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Преглед и промяна на споделените данни"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Идентификатор на споделените данни: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Изтича на <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Приложения, споделящи данни"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Няма описание, предоставено от приложението."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Споделянето приключва на <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Изтриване на споделените данни"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Наистина ли искате да изтриете тези споделени данни?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Потребителите имат свои собствени приложения и съдържание"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Можете да ограничите достъпа до приложенията и съдържанието от профила си"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Потребител"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Ограничен потр. профил"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Да се добави ли нов потреб.?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Можете да споделите това устройство с други хора, като създадете допълнителни потребители. Всеки от тях има собствено работно пространство, което може да персонализира с приложения, тапет и др. Потребителите могат също да коригират настройки на устройството, които засягат всички – например за Wi‑Fi.\n\nКогато добавите нов потребител, той трябва да настрои работното си пространство.\n\nВсеки потребител може да актуализира приложенията за всички останали потребители. Настройките и услугите за достъпност може да не се прехвърлят за новия потребител."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Когато добавите нов потребител, той трябва да настрои работното си пространство.\n\nВсеки потребител може да актуализира приложенията за всички останали потребители."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Настройване на потребителя?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Уверете се, че човекът има възможност да вземе устройството и да настрои работното си пространство."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Ще настроите ли потребителския профил сега?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Настройване сега"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Не сега"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Добавяне"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Нов потребител"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Нов потребителски профил"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Данни за потребителя"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Инф. за потр. профил"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Преди да можете да създадете потребителски профил с ограничена функционалност, трябва да настроите заключения екран, за да защитите приложенията и личните си данни."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Задаване на заключване"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index a6f1177..8805c21 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -418,8 +418,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"প্রোটানোম্যালি (লাল-সবুজ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ট্রিট্যানোম্যালি (নীল-হলুদ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"রঙ সংশোধন"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ডিভাইসে রঙগুলি কেমনভাবে দেখানো হবে তা অ্যাডজাস্ট করতে \'রঙ সংশোধন করুন\' বিকল্প ব্যবহার করা যেতে পারে"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"আর আনুমানিক <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে"</string>
@@ -520,10 +519,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -534,4 +541,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"ব্যবহারকারীদের তাঁদের নিজস্ব অ্যাপ্লিকেশন এবং কন্টেন্ট আছে"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"আপনি আপনার অ্যাকাউন্ট থেকে অ্যাপ্লিকেশন এবং কন্টেন্ট অ্যাক্সেস সীমাবদ্ধ করতে পারেন"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"ব্যবহারকারী"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"সীমাবদ্ধ প্রোফাইল"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"নতুন ব্যবহারকারী জুড়বেন?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"আপনি একাধিক ব্যবহারকারীর আইডি তৈরি করে অন্যদের সাথে এই ডিভাইসটি শেয়ার করতে পারেন। ডিভাইসের স্টোরেজে প্রত্যেক ব্যবহারকারী তার নিজস্ব জায়গা পাবেন যা তিনি অ্যাপ, ওয়ালপেপার এবং আরও অনেক কিছু দিয়ে কাস্টমাইজ করতে পারেন। ওয়াই-ফাই এর মতো ডিভাইস সেটিংস, যেগুলি সকলের ক্ষেত্রে প্রযোজ্য হয়, সেগুলি ব্যবহারকারীরা পরিবর্তন করতে পারবেন।\n\nনতুন ব্যবহারকারীর আইডি যোগ করলে সেই ব্যক্তিকে স্টোরেজে তার নিজের জায়গা সেট-আপ করতে হবে।\n\nঅন্যান্য ব্যবহারকারীদের হয়ে যে কোনও ব্যবহারকারী অ্যাপ আপডেট করতে পারবেন। তবে ব্যবহারযোগ্যতার সেটিংস এবং পরিষেবা নতুন ব্যবহারকারীর ক্ষেত্রে প্রযোজ্য নাও হতে পারে।"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"আপনি একজন নতুন ব্যবহারকারী জুড়লে তাকে তার জায়গা সেট-আপ করে নিতে হবে।\n\nযেকোনো ব্যবহারকারী অন্য সব ব্যবহারকারীর জন্য অ্যাপ্লিকেশান আপডেট করতে পারবেন।"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"এখন ব্যবহারকারী সেট-আপ করবেন?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"নিশ্চিত করুন, যে ব্যক্তিটি ডিভাইসটি নেওয়ার জন্য এবং তার জায়গা সেট-আপ করার জন্য উপলব্ধ আছেন"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"এখনই প্রোফাইল সেট-আপ করবেন?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"এখনই সেট-আপ করুন"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"এখনই নয়"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"যোগ করুন"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"নতুন ব্যবহারকারী"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"নতুন প্রোফাইল"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"ব্যবহারকারী তথ্য"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"প্রোফাইল তথ্য"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"আপনি একটি সীমাবদ্ধযুক্ত প্রোফাইল তৈরি করার আগে, আপনাকে আপনার অ্যাপ্লিকেশন এবং ব্যক্তিগত ডেটা সুরক্ষিত করার জন্য একটি স্ক্রিন লক সেট-আপ করতে হবে।"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"লক সেট করুন"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 5a317ee..188c2f5 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresa i priključak"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skenirajte QR kôd"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Uparite uređaj putem WiFi-ja skeniranjem QR koda"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Povežite se na WiFi mrežu"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, otklanjanje grešaka, programer"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Prečica za izvještaj o greškama"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikaz dugmeta za prijavu grešaka u meniju napajanja"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno-zeleno)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo-žuto)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Ispravka boje"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korekcija boje vam dozvoljava da prilagodite način prikazivanja boja na uređaju"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Trebala bi trajati do otprilike <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Trebala bi trajati otprilike do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Baterija bi se mogla isprazniti do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -513,26 +510,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvučnik telefona"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Došlo je do problema prilikom povezivanja. Isključite, pa ponovo uključite uređaj"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Pohrana"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Dijeljeni podaci"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Prikaz i izmjena dijeljenih podataka"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID dijeljenih podataka: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Ističe dana <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplikacije koje dijele podatke"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"U aplikaciji nije naveden opis."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Najam ističe dana <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Izbriši dijeljene podatke"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Jeste li sigurni da želite izbrisati ove dijeljene podatke?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Korisnici imaju sopstvene aplikacije i sadržaj"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Možete ograničiti pristup aplikacijama i sadržaju sa svog računa"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Korisnik"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Ograničeni profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Dodati novog korisnika?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Za dijeljenje ovog uređaja s drugima možete napraviti dodatne korisnike. Svaki korisnik ima svoj prostor koji može prilagoditi pomoću aplikacija, pozadinske slike i slično. Korisnici također mogu prilagoditi postavke uređaja koje utiču na sve ostale korisnike, kao što je WiFi.\n\nKada dodate novog korisnika, ta osoba treba postaviti svoj prostor.\n\nSvaki korisnik može ažurirati aplikacije za sve ostale korisnike. Postavke i usluge pristupačnosti možda se neće prenijeti na novog korisnika."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Kada dodate novog korisnika, ta osoba treba postaviti svoj prostor. \n\n Svaki korisnik može ažurirati aplikacije za sve ostale korisnike."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Postaviti korisnika sada?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Provjerite može li osoba uzeti uređaj i postaviti svoj prostor"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Postaviti profil sada?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Postavi"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ne sada"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Dodaj"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Novi korisnik"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Novi profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Podaci o korisniku"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Podaci o profilu"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Prije nego vam se omogući kreiranje ograničenog profila, morate postaviti zaključavanje ekrana da biste zaštitili svoje aplikacije i lične podatke."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Postaviti zaključavanje"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 333f8e9..7fadf93 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -169,11 +169,11 @@
<string name="tts_install_data_title" msgid="1829942496472751703">"Instal·la dades de veu"</string>
<string name="tts_install_data_summary" msgid="3608874324992243851">"Instal·la les dades de veu necessàries per a la síntesi de veu"</string>
<string name="tts_engine_security_warning" msgid="3372432853837988146">"Pot ser que aquest motor de síntesi de parla pugui recopilar tot el text que s\'enunciarà, incloses les dades personals, com ara les contrasenyes i els números de les targetes de crèdit. Ve del motor <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Vols activar l\'ús d\'aquest motor de síntesi de parla?"</string>
- <string name="tts_engine_network_required" msgid="8722087649733906851">"Aquest idioma requereix una connexió de xarxa activa per a la sortida de text a parla."</string>
+ <string name="tts_engine_network_required" msgid="8722087649733906851">"Aquest idioma requereix una connexió a la xarxa activa per a la sortida de text a parla."</string>
<string name="tts_default_sample_string" msgid="6388016028292967973">"Això és un exemple de síntesi de veu"</string>
<string name="tts_status_title" msgid="8190784181389278640">"Estat de l\'idioma predeterminat"</string>
<string name="tts_status_ok" msgid="8583076006537547379">"<xliff:g id="LOCALE">%1$s</xliff:g> és totalment compatible"</string>
- <string name="tts_status_requires_network" msgid="8327617638884678896">"Es necessita una connexió de xarxa per a <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_requires_network" msgid="8327617638884678896">"Es necessita una connexió a la xarxa per a <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
<string name="tts_status_not_supported" msgid="2702997696245523743">"<xliff:g id="LOCALE">%1$s</xliff:g> no és compatible"</string>
<string name="tts_status_checking" msgid="8026559918948285013">"S\'està comprovant…"</string>
<string name="tts_engine_settings_title" msgid="7849477533103566291">"Configuració de: <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adreça IP i port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Escaneja un codi QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Vincula el dispositiu per Wi‑Fi escanejant un codi QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Connecta\'t a una xarxa Wi‑Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, depurar, desenvolupador"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Drecera per a informe d\'errors"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostra un botó al menú d\'engegada per crear un informe d\'errors"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermell-verd)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (blau-groc)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correcció del color"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La correcció del color permet ajustar com es mostren els colors al teu dispositiu"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant aproximat: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Fins a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"És possible que la bateria s\'esgoti a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Temps restant inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Temps restant inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Temps restant superior a <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altaveu del telèfon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Hi ha hagut un problema amb la connexió. Desactiva el dispositiu i torna\'l a activar."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositiu d\'àudio amb cable"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Ajuda i suggeriments"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Emmagatzematge"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Dades compartides"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Mostra i modifica les dades compartides"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Identificador de dades compartides: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Caduca el dia <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplicacions que comparteixen dades"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"L\'aplicació no ha proporcionat cap descripció."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"La concessió caduca el dia <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Suprimeix dades compartides"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Confirmes que vols suprimir aquestes dades compartides?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Els usuaris tenen les seves aplicacions i el seu contingut"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Pots restringir l\'accés a les aplicacions i al contingut del teu compte."</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Usuari"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restringit"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Vols afegir un usuari nou?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Pots compartir aquest dispositiu amb altres usuaris creant usuaris addicionals. Cada usuari té el seu propi espai, que pot personalitzar amb aplicacions i fons de pantalla, entre d\'altres. Els usuaris també poden ajustar opcions de configuració del dispositiu, com ara la Wi-Fi, que afecten els altres usuaris.\n\nQuan afegeixis un usuari nou, haurà de configurar el seu espai.\n\nTots els usuaris poden actualitzar les aplicacions de la resta. És possible que la configuració i els serveis d\'accessibilitat no es transfereixin a l\'usuari nou."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Quan s\'afegeix un usuari nou, aquest usuari ha de configurar el seu espai.\n\nQualsevol usuari pot actualitzar les aplicacions dels altres usuaris."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Vols configurar l\'usuari ara?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Comprova que l\'usuari pugui accedir al dispositiu i configurar el seu espai."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Vols configurar el perfil ara?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configura ara"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ara no"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Afegeix"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Usuari nou"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Perfil nou"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Info. de l\'usuari"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informació de perfil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Per crear un perfil restringit, has de configurar una pantalla de bloqueig per protegir les aplicacions i les dades personals."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Defineix un bloqueig"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 453bb87..f5d8465 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresa a port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Naskenování QR kódu"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Párovat zařízení přes Wi-Fi naskenováním QR kódu"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Připojte se k síti Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ladění, vývoj"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Zástupce hlášení chyb"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Zobrazit v hlavní nabídce tlačítko k vygenerování chybového hlášení"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomálie (červená a zelená)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomálie (modrá a žlutá)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekce barev"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korekce barev umožňuje upravit zobrazování barev na zařízení"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Vydrží asi do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Vydrží asi do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Baterie se může vybít do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Zbývá méně než <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Zbývá méně než <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Zbývá více než <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -514,26 +511,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Reproduktor telefonu"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problém s připojením. Vypněte zařízení a znovu jej zapněte"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kabelové audiozařízení"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Nápověda a zpětná vazba"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Úložiště"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Sdílená data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Zobrazit a upravit sdílená data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID sdílených dat: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Platnost vyprší <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplikace, které sdílejí data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Aplikace neposkytuje žádný popis."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Pronájem vyprší <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Vymazat sdílená data"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Opravdu tato sdílená data chcete vymazat?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Uživatelé mají své vlastní aplikace a obsah."</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Můžete omezit přístup k aplikacím a obsahu ze svého účtu"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Uživatel"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Omezený profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Přidat nového uživatele?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Vytvořením dalších uživatelů můžete toto zařízení sdílet s jinými lidmi. Každý uživatel má svůj prostor, který si může přizpůsobit instalací aplikací, přidáním tapety apod. Uživatelé také mohou upravit nastavení zařízení (např. Wi-Fi), která ovlivní všechny uživatele.\n\nKaždý nově přidaný uživatel si musí nastavit vlastní prostor.\n\nKaždý uživatel může aktualizovat aplikace všech ostatních uživatelů."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Když přidáte nového uživatele, musí si nastavit vlastní prostor.\n\nJakýkoli uživatel může aktualizovat aplikace všech ostatních uživatelů."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Nastavit uživatele?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Ujistěte se, že je uživatel k dispozici a může si v zařízení nastavit svůj prostor"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Nastavit profil?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Nastavit"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Teď ne"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Přidat"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nový uživatel"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Nový profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Info o uživateli"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informace o profilu"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Před vytvořením omezeného profilu je nutné nejprve nastavit zámek obrazovky k ochraně aplikací a dat."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Nastavit zámek"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 7206e38..07a90d6 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-adresse og port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR-kode"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Dan par med en enhed via Wi-Fi ved at scanne en QR-kode"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Opret forbindelse til et Wi-Fi-netværk"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, fejlfinding, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Genvej til fejlrapportering"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Vis en knap til oprettelse af fejlrapporter i afbrydermenuen"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanopi (rød-grøn)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanopi (blå-gul)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korriger farver"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Ved hjælp af farvekorrigering kan du justere, hvordan farver ser ud på din enhed"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Bør holde indtil ca. <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Bør holde indtil ca. <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Indtil <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Enheden løber muligvis tør for batteri inden <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Der er mindre end <xliff:g id="THRESHOLD">%1$s</xliff:g> tilbage"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Der er mindre end <xliff:g id="THRESHOLD">%1$s</xliff:g> tilbage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Der er mere end <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonens højttaler"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Der kunne ikke oprettes forbindelse. Sluk og tænd enheden"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhed med ledning"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Hjælp og feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Lager"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Delte data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Se og rediger delte data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Id for delte data: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Udløber <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps, der deler data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Der er ikke angivet nogen beskrivelse af appen."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Leasingen udløber <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Slet delte data"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Er du sikker på, at du vil slette disse delte data?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Brugere har egne apps og eget indhold"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Du kan begrænse adgangen til apps og indhold fra din konto"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Bruger"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Begrænset profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Vil du tilføje en ny bruger?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Du kan dele denne enhed med andre ved at oprette ekstra brugere. Hver bruger har sit eget rum, som kan tilpasses med apps, baggrund osv. Brugerne kan også justere enhedsindstillinger, som for eksempel Wi-Fi, som påvirker alle.\n\nNår du tilføjer en ny bruger, skal vedkommende konfigurere sit rum.\n\nAlle brugere kan opdatere apps for alle andre brugere. Indstillinger og tjenester for hjælpefunktioner overføres muligvis ikke til den nye bruger."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Når du tilføjer en ny bruger, skal personen konfigurere sit rum.\n\nEnhver bruger kan opdatere apps for alle andre brugere."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Vil du konfigurere brugeren nu?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Sørg for, at brugeren har mulighed for at tage enheden og konfigurere sit eget rum"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Vil du oprette en profil nu?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Konfigurer nu"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ikke nu"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Tilføj"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Ny bruger"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Ny profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Brugeroplysninger"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profiloplysninger"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Før du kan oprette en begrænset profil, skal du oprette en skærmlås for at beskytte dine apps og personlige data."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Konfigurer låseskærmen"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index f9cf552..f151bc3 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-Adresse & Port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR-Code scannen"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Scanne einen QR-Code, um ein Gerät über WLAN zu koppeln"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Bitte stell eine WLAN-Verbindung her"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, Debug, Dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Verknüpfung zu Fehlerbericht"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Im Menü \"Ein/Aus\" wird eine Option zum Erstellen eines Fehlerberichts angezeigt"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (Rot-Grün-Sehschwäche)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (Blau-Gelb-Sehschwäche)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Farbkorrektur"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Mit der Farbkorrektur kannst du anpassen, wie Farben auf deinem Display angezeigt werden"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Noch etwa <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Sollte etwa bis <xliff:g id="TIME">%1$s</xliff:g> reichen (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Sollte etwa bis <xliff:g id="TIME">%1$s</xliff:g> reichen"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Bis <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Der Akku ist voraussichtlich um <xliff:g id="TIME">%1$s</xliff:g> leer"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Weniger als <xliff:g id="THRESHOLD">%1$s</xliff:g> verbleibend"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Weniger als <xliff:g id="THRESHOLD">%1$s</xliff:g> verbleibend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mehr als <xliff:g id="TIME_REMAINING">%1$s</xliff:g> verbleibend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Smartphone-Lautsprecher"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Verbindung kann nicht hergestellt werden. Schalte das Gerät aus & und wieder ein."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Netzbetriebenes Audiogerät"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Hilfe und Feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Speicher"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Geteilte Daten"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Geteilte Daten anzeigen und ändern"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID für geteilte Daten: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Läuft am <xliff:g id="DATE">%s</xliff:g> ab"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps, die Daten teilen"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Keine Beschreibung der App verfügbar."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Freigabe läuft am <xliff:g id="DATE">%s</xliff:g> ab"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Geteilte Daten löschen"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Bist du sicher, dass du diese geteilten Daten löschen möchtest?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Die Nutzer haben eigene Apps und Inhalte."</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Du kannst den Zugriff auf Apps und Inhalte aus deinem Konto beschränken."</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Nutzer"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Eingeschränkte Profile"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Neuen Nutzer hinzufügen?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Du kannst dieses Gerät zusammen mit anderen nutzen, indem du weitere Nutzer erstellst. Jeder erhält einen eigenen Bereich, in dem er Apps, den Hintergrund usw. personalisieren kann. Außerdem lassen sich Geräteeinstellungen wie WLAN ändern, die sich auf alle Nutzer auswirken.\n\nWenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten.\n\nJeder Nutzer kann Apps für alle anderen Nutzer aktualisieren. Bedienungshilfen-Einstellungen und -Dienste werden möglicherweise nicht auf den neuen Nutzer übertragen."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Wenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten.\n\nJeder Nutzer kann Apps für alle anderen Nutzer aktualisieren."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Nutzer jetzt einrichten?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Die Person muss Zugang zum Gerät haben und bereit sein, ihren Bereich einzurichten."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Profil jetzt einrichten?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Jetzt einrichten"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Nicht jetzt"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Hinzufügen"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Neuer Nutzer"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Neues Profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Nutzerinformationen"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profilinformationen"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Vor dem Erstellen eines eingeschränkten Profils musst du eine Displaysperre einrichten, um deine Apps und personenbezogenen Daten zu schützen."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Sperre einrichten"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 07d161d..094e1d7 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Διεύθυνση IP και θύρα"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Σάρωση κωδικού QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Σύζευξη συσκευής μέσω Wi‑Fi με τη σάρωση ενός κωδικού QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Συνδεθείτε σε ένα δίκτυο Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, εντοπισμός σφαλμάτων, προγραμματιστής"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Συντόμευση αναφοράς σφαλμάτων"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Εμφάνιση κουμπιού στο μενού ενεργοποίησης για τη λήψη αναφοράς σφαλμάτων"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Πρωτανοπία (κόκκινο-πράσινο)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Τριτανοπία (μπλε-κίτρινο)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Διόρθωση χρωμάτων"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Η διόρθωση χρωμάτων σάς επιτρέπει να ρυθμίσετε τον τρόπο εμφάνισης των χρωμάτων στη συσκευή σας"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Απομένει/ουν περίπου <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Θα διαρκέσει μέχρι τις <xliff:g id="TIME">%1$s</xliff:g> περίπου (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Θα διαρκέσει μέχρι τις <xliff:g id="TIME">%1$s</xliff:g> περίπου"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Έως τις <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Η μπαταρία μπορεί να εξαντληθεί έως τις <xliff:g id="TIME">%1$s</xliff:g>."</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Απομένει/ουν λιγότερo/α από <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Απομένει/ουν λιγότερo/α από <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Απομένουν περισσότερα/ες από <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Ηχείο τηλεφώνου"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Πρόβλημα κατά τη σύνδεση. Απενεργοποιήστε τη συσκευή και ενεργοποιήστε την ξανά"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ενσύρματη συσκευή ήχου"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Βοήθεια και σχόλια"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Αποθηκευτικός χώρος"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Κοινόχρηστα δεδομένα"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Προβολή και τροποποίηση κοινόχρηστων δεδομένων"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Αναγνωριστικό κοινόχρηστων δεδομένων: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Λήγει στις <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Εφαρμογές που κάνουν κοινή χρήση δεδομένων"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Δεν παρέχεται περιγραφή από την εφαρμογή."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Λήξη άδειας στις <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Διαγραφή κοινόχρηστων δεδομένων"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Είστε σίγουροι ότι θέλετε να διαγράψετε αυτά τα κοινόχρηστα δεδομένα;"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Οι χρήστες διαθέτουν τις δικές τους εφαρμογές και περιεχόμενο"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Μπορείτε να περιορίσετε την πρόσβαση σε εφαρμογές και περιεχόμενο από το λογαριασμό σας"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Χρήστης"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Προφίλ περιορ. πρόσβασης"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Προσθήκη νέου χρήστη;"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Μπορείτε να μοιραστείτε αυτήν τη συσκευή με άλλα άτομα, δημιουργώντας επιπλέον χρήστες. Κάθε χρήστης θα έχει το δικό του χώρο, τον οποίο μπορεί να προσαρμόσει με τις δικές του εφαρμογές, ταπετσαρία κ.λπ. Οι χρήστες μπορούν επίσης να προσαρμόσουν ρυθμίσεις της συσκευής, όπως το Wi‑Fi, που επηρεάζουν τους πάντες.\n\nΚατά την προσθήκη ενός νέου χρήστη, αυτός θα πρέπει να ρυθμίσει τον χώρο του.\n\nΟποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες. Οι ρυθμίσεις και οι υπηρεσίες προσβασιμότητας ενδέχεται να μην μεταφερθούν στον νέο χρήστη"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Κατά την προσθήκη ενός νέου χρήστη, αυτός θα πρέπει να ρυθμίσει το χώρο του.\n\nΟποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Να γίνει ρύθμιση χρήστη τώρα;"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Βεβαιωθείτε ότι ο χρήστης μπορεί να πάρει τη συσκευή και ρυθμίστε το χώρο του"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Να γίνει ρύθμιση προφίλ τώρα;"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Ρύθμιση τώρα"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Όχι τώρα"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Προσθήκη"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Νέος χρήστης"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Νέο προφίλ"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Πληροφορίες χρήστη"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Πληροφορίες προφίλ"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Προκειμένου να μπορέσετε να δημιουργήσετε ένα περιορισμένο προφίλ, θα πρέπει να δημιουργήσετε ένα κλείδωμα οθόνης για την προστασία των εφαρμογών και των προσωπικών δεδομένων σας."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Ορισμός κλειδώματος"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index dae998f..fc1adbb 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address & port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Pair device over Wi‑Fi by scanning a QR code"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Please connect to a Wi‑Fi network"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Bug report shortcut"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Show a button in the power menu for taking a bug report"</string>
@@ -432,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Should last until about <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Until <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Battery may run out by <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -511,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Storage"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Shared data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"View and modify shared data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Shared data ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Expires on <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps sharing data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"No description provided by the app."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Lease expires on <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Delete shared data"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Are you sure that you want to delete this shared data?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Users have their own apps and content"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"You can restrict access to apps and content from your account"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"User"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Restricted profile"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Add new user?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"You can share this device with other people by creating additional users. Each user has their own space, which they can customise with apps, wallpaper and so on. Users can also adjust device settings such as Wi‑Fi that affect everyone.\n\nWhen you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. Accessibility settings and services may not transfer to the new user."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Set up user now?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Make sure that the person is available to take the device and set up their space."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Set up profile now?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Set up now"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Not now"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Add"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"New user"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"New profile"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"User info"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profile info"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index dae998f..fc1adbb 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address & port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Pair device over Wi‑Fi by scanning a QR code"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Please connect to a Wi‑Fi network"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Bug report shortcut"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Show a button in the power menu for taking a bug report"</string>
@@ -432,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Should last until about <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Until <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Battery may run out by <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -511,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Storage"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Shared data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"View and modify shared data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Shared data ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Expires on <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps sharing data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"No description provided by the app."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Lease expires on <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Delete shared data"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Are you sure that you want to delete this shared data?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Users have their own apps and content"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"You can restrict access to apps and content from your account"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"User"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Restricted profile"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Add new user?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"You can share this device with other people by creating additional users. Each user has their own space, which they can customise with apps, wallpaper and so on. Users can also adjust device settings such as Wi‑Fi that affect everyone.\n\nWhen you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. Accessibility settings and services may not transfer to the new user."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Set up user now?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Make sure that the person is available to take the device and set up their space."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Set up profile now?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Set up now"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Not now"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Add"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"New user"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"New profile"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"User info"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profile info"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index dae998f..fc1adbb 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address & port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Pair device over Wi‑Fi by scanning a QR code"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Please connect to a Wi‑Fi network"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Bug report shortcut"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Show a button in the power menu for taking a bug report"</string>
@@ -432,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Should last until about <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Until <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Battery may run out by <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -511,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Storage"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Shared data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"View and modify shared data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Shared data ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Expires on <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps sharing data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"No description provided by the app."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Lease expires on <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Delete shared data"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Are you sure that you want to delete this shared data?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Users have their own apps and content"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"You can restrict access to apps and content from your account"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"User"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Restricted profile"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Add new user?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"You can share this device with other people by creating additional users. Each user has their own space, which they can customise with apps, wallpaper and so on. Users can also adjust device settings such as Wi‑Fi that affect everyone.\n\nWhen you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. Accessibility settings and services may not transfer to the new user."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Set up user now?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Make sure that the person is available to take the device and set up their space."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Set up profile now?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Set up now"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Not now"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Add"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"New user"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"New profile"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"User info"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profile info"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index dae998f..fc1adbb 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address & port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Pair device over Wi‑Fi by scanning a QR code"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Please connect to a Wi‑Fi network"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Bug report shortcut"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Show a button in the power menu for taking a bug report"</string>
@@ -432,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Should last until about <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Until <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Battery may run out by <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -511,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Storage"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Shared data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"View and modify shared data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Shared data ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Expires on <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps sharing data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"No description provided by the app."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Lease expires on <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Delete shared data"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Are you sure that you want to delete this shared data?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Users have their own apps and content"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"You can restrict access to apps and content from your account"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"User"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Restricted profile"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Add new user?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"You can share this device with other people by creating additional users. Each user has their own space, which they can customise with apps, wallpaper and so on. Users can also adjust device settings such as Wi‑Fi that affect everyone.\n\nWhen you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. Accessibility settings and services may not transfer to the new user."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Set up user now?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Make sure that the person is available to take the device and set up their space."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Set up profile now?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Set up now"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Not now"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Add"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"New user"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"New profile"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"User info"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profile info"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index a3822251..1736429 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -513,11 +513,38 @@
<string name="storage_category" msgid="2287342585424631813">"Storage"</string>
<string name="shared_data_title" msgid="1017034836800864953">"Shared data"</string>
<string name="shared_data_summary" msgid="5516326713822885652">"View and modify shared data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<string name="blob_id_text" msgid="8680078988996308061">"Shared data ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
<string name="blob_expires_text" msgid="7882727111491739331">"Expires at <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<string name="accessor_info_title" msgid="8289823651512477787">"Apps sharing data"</string>
<string name="accessor_no_description_text" msgid="7510967452505591456">"No description provided by the app."</string>
<string name="accessor_expires_text" msgid="4625619273236786252">"Lease expires at <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="delete_blob_text" msgid="2819192607255625697">"Delete shared data"</string>
<string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Are you sure you want to delete this shared data?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Users have their own apps and content"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"You can restrict access to apps and content from your account"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"User"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Restricted profile"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Add new user?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"You can share this device with other people by creating additional users. Each user has their own space, which they can customize with apps, wallpaper, and so on. Users can also adjust device settings like Wi‑Fi that affect everyone.\n\nWhen you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. Accessibility settings and services may not transfer to the new user."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Set up user now?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Make sure the person is available to take the device and set up their space"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Set up profile now?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Set up now"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Not now"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Add"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"New user"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"New profile"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"User info"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profile info"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you’ll need to set up a screen lock to protect your apps and personal data."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 62082a4..a881b3c 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Dirección IP y puerto"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Escanear código QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Escanea un código QR para vincular el dispositivo mediante Wi‑Fi"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conéctate a una red Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Acceso directo para informes de errores"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar un botón en el menú de encendido para realizar un informe de errores"</string>
@@ -432,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Duración aproximada hasta: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Hasta <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Es posible que la batería se agote para las <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Tiempo restante: más de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -511,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altavoz del teléfono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Error al establecer la conexión. Apaga el dispositivo y vuelve a encenderlo."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Ayuda y comentarios"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Storage"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Datos compartidos"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Ver y modificar los datos compartidos"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID de datos compartidos: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Vence el <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps que comparten datos"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"La app no proporcionó una descripción."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"La asignación de tiempo vence el <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Borrar datos compartidos"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"¿Seguro que quieres borrar estos datos compartidos?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Los usuarios tienen sus propias aplicaciones y contenidos."</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Desde tu cuenta, puedes restringir el acceso a las aplicaciones y al contenido."</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Usuario"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restringido"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"¿Agregar usuario nuevo?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Para compartir este dispositivo, crea más usuarios. Cada uno tendrá su propio espacio y podrá personalizarlo con apps, un fondo de pantalla y mucho más. Los usuarios también podrán ajustar algunas opciones del dispositivo, como la conexión Wi‑Fi, que afectan a todos los usuarios.\n\nCuando agregues un nuevo usuario, esa persona deberá configurar su espacio.\n\nCualquier usuario podrá actualizar las apps de otras personas. Es posible que no se transfieran los servicios ni las opciones de accesibilidad al nuevo usuario."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Cuando agregas un nuevo usuario, esa persona debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de los usuarios."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"¿Configurar el usuario ahora?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Asegúrate de que la persona pueda acceder al dispositivo y configurar su espacio."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"¿Quieres configurar tu perfil ahora?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configurar ahora"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ahora no"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Agregar"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Usuario nuevo"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Perfil nuevo"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Datos de usuario"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Datos del perfil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restringido, debes configurar un bloqueo de pantalla que proteja tus aplicaciones y datos personales."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Configurar bloqueo"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 62c8bb7..8d80527 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Dirección IP y puerto"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Escanear código QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Vincula un dispositivo a través de Wi‑Fi con un código QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conéctate a una red Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, depuración, desarrollo"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Atajo a informe de errores"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar un botón en el menú de encendido para crear un informe de errores"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La corrección de color te permite ajustar cómo se muestran los colores en tu dispositivo"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Duración aproximada hasta: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Hasta: <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Es probable que te quedes sin batería sobre las <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Queda menos del <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Queda más del <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altavoz del teléfono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"No se ha podido conectar; reinicia el dispositivo"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Ayuda y sugerencias"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Memoria"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Datos compartidos"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Ver y modificar los datos compartidos"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID de datos compartidos: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Caduca el <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplicaciones que comparten datos"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"La aplicación no ofrece ninguna descripción."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"La concesión caduca el <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Eliminar datos compartidos"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"¿Seguro que quieres eliminar estos datos compartidos?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Los usuarios tienen contenido y aplicaciones propios"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Desde tu cuenta, puedes restringir el acceso a las aplicaciones y al contenido"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Usuario"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restringido"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"¿Añadir nuevo usuario?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Puedes compartir este dispositivo si creas más usuarios. Cada uno tendrá su propio espacio y podrá personalizarlo con aplicaciones, un fondo de pantalla y mucho más. Los usuarios también pueden ajustar opciones del dispositivo, como la conexión Wi‑Fi, que afectan a todos los usuarios.\n\nCuando añadas un usuario, tendrá que configurar su espacio.\n\nCualquier usuario puede actualizar aplicaciones de todos los usuarios. Es posible que no se transfieran los servicios y opciones de accesibilidad al nuevo usuario."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Al añadir un usuario nuevo, este debe configurar su espacio.\n\nCualquier usuario puede actualizar las aplicaciones del resto de usuarios."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"¿Configurar usuario ahora?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Asegúrate de que la persona pueda acceder al dispositivo y configurar su espacio."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"¿Quieres configurar un perfil ahora?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configurar ahora"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ahora no"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Añadir"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nuevo usuario"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Perfil nuevo"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Información del usuario"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Información del perfil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restringido, debes configurar una pantalla de bloqueo que proteja tus aplicaciones y datos personales."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index fefa3a7..f4e0e73 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-aadress ja port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR-koodi skannimine"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Siduge seade WiFi kaudu, skannides QR-koodi"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Looge ühendus WiFi-võrguga"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, silumine, arendus"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Veaaruande otsetee"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Kuva toitemenüüs veaaruande jäädvustamise nupp"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaalia (punane-roheline)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaalia (sinine-kollane)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värvide korrigeerimine"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Värviparandus võimaldab kohandada seadmes kuvatavaid värve"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäänud"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Peaks kestma kuni <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Peaks kestma kuni <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Kuni <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Aku võib tühjaks saada kell <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Jäänud on alla <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Jäänud on alla <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Jäänud on üle <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefoni kõlar"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem ühendamisel. Lülitage seade välja ja uuesti sisse"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Juhtmega heliseade"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Abi ja tagasiside"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Salvestusruum"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Jagatud andmed"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Vaadake ja muutke jagatud andmeid"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Jagatud andmete ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Aegub <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Andmeid jagavad rakendused"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Rakendus ei esita kirjeldust."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Rendiperiood lõpeb <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Kustuta jagatud andmed"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Kas soovite kindlasti need jagatud andmed kustutada?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Kasutajatel on oma rakendused ja sisu"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Oma kontol saate piirata juurdepääsu rakendustele ja sisule"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Kasutaja"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Piiratud profiil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Kas lisada uus kasutaja?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Võite jagada seda seadet teiste inimestega, luues uusi kasutajaid. Igal kasutajal on oma ruum, mida saab kohandada rakenduste, taustapildi ja muuga. Kasutajad saavad kohandada ka seadme seadeid, näiteks WiFi-valikuid, mis mõjutavad kõiki kasutajaid.\n\nKui lisate uue kasutaja, siis peab ta seadistama oma ruumi.\n\nIga kasutaja saab rakendusi kõigi kasutajate jaoks värskendada. Juurdepääsetavuse seadeid ja teenuseid ei pruugita uuele kasutajale üle kanda."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Kui lisate uue kasutaja, siis peab ta seadistama oma ruumi.\n\nIga kasutaja saab värskendada rakendusi kõigi kasutajate jaoks."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Kas seadistada kasutaja kohe?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Veenduge, et isik saaks seadet kasutada ja oma ruumi seadistada"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Kas soovite kohe profiili seadistada?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Seadista kohe"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Mitte praegu"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Lisamine"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Uus kasutaja"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Uus profiil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Kasutajateave"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profiili teave"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Enne piiratud profiili loomist peate seadistama lukustusekraani, et oma rakendusi ja isiklikke andmeid kaitsta."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Määra lukk"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index f29b6e4..e516222 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP helbidea eta ataka"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Eskaneatu QR kodea"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Parekatu gailua wifi-sare baten bidez QR kode bat eskaneatuta"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Konektatu wifi-sare batera"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, araztu, gailua"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Akatsen txostenerako lasterbidea"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Bateriaren menuan, erakutsi akatsen txostena sortzeko botoia"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanopia (gorri-berdeak)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanopia (urdin-horia)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Koloreen zuzenketa"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Koloreen zuzenketaren bidez, gailuan koloreak bistaratzen diren modua doi dezakezu"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Ordu honetara arte iraungo du, gutxi gorabehera: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Ordu honetara arte iraungo du, gutxi gorabehera: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> arte"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Baliteke bateria ordu honetan agortzea: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> baino gutxiago gelditzen dira"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> baino gutxiago gelditzen da (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> baino gehiago gelditzen da (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonoaren bozgorailua"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Arazoren bat izan da konektatzean. Itzali gailua eta pitz ezazu berriro."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio-gailu kableduna"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Laguntza eta iritzia"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Memoria"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Partekatutako datuak"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Ikusi eta aldatu partekatutako datuak"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Partekatutako datuen IDa: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Iraungitze-data: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Datuak partekatzen dituzten aplikazioak"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Aplikazioak ez du azalpenik eman."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Alokatzearen iraungitze-data: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Ezabatu partekatutako datuak"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Ziur partekatutako datuak ezabatu nahi dituzula?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Erabiltzaileek euren aplikazioak eta edukia dituzte."</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Aplikazioetarako eta edukirako sarbidea muga dezakezu zure kontutik."</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Erabiltzailea"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil murriztua"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Beste erabiltzaile bat gehitu nahi duzu?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Gailu hau beste pertsona batzuekin partekatzeko, sortu erabiltzaile gehiago. Erabiltzaile bakoitzak bere eremua izango du eta, bertan, aplikazioak, horma-papera eta antzekoak pertsonalizatu ahal izango ditu. Horrez gain, erabiltzaile guztiei eragin diezaieketen ezarpen batzuk ere doi daitezke; adibidez, wifi-konexioarena.\n\nErabiltzaile bat gehitzen duzunean, pertsona horrek berak konfiguratu beharko du bere eremua.\n\nEdozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak. Baliteke erabilerraztasun-ezarpenak eta -zerbitzuak ez transferitzea erabiltzaile berriei."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Erabiltzaile bat gehitzen duzunean, erabiltzaile horrek bere eremua konfiguratu beharko du.\n\nEdozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Erabiltzailea konfiguratu?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Ziurtatu pertsona horrek gailua hartu eta bere eremua konfigura dezakeela"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Profila konfiguratu?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Konfiguratu"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Orain ez"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Gehitu"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Erabiltzaile berria"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Profil berria"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Erabiltzaile-info."</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profileko informazioa"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Profil murriztua sortu aurretik, aplikazioak eta datu pertsonalak babesteko, pantaila blokeatzeko metodo bat konfiguratu beharko duzu."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Ezarri blokeoa"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index cdd416d..cfdab50 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"نشانی IP و درگاه"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"اسکن کد QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"دستگاه را ازطریق Wi‑Fi و با اسکن کردن کد QR مرتبط کنید"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"لطفاً به شبکه Wi-Fi متصل شوید"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB (پل اشکالزدایی Android)، اشکالزدایی کردن، برنامهنویس"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"میانبر گزارش مشکل"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"نمایش دکمهای در منوی روشن/خاموش برای گرفتن گزارش اشکال"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"قرمزدشواربینی (قرمز-سبز)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"آبیدشواربینی (آبی-زرد)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"تصحیح رنگ"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"تصحیح رنگ به شما امکان میدهد نحوه نمایش رنگها را در دستگاهتان تنظیم کنید"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"باید حدوداً تا <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) شارژ داشته باشید"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"باید حدوداً تا <xliff:g id="TIME">%1$s</xliff:g> شارژ داشته باشید"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"تا <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"ممکن است باتری در <xliff:g id="TIME">%1$s</xliff:g> تمام شود"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"کمتر از <xliff:g id="THRESHOLD">%1$s</xliff:g> باقی مانده"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"کمتر از <xliff:g id="THRESHOLD">%1$s</xliff:g> شارژ باقی مانده است (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"بیش از <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"بلندگوی تلفن"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"مشکل در اتصال. دستگاه را خاموش و دوباره روشن کنید"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"دستگاه صوتی سیمی"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"راهنما و بازخورد"</string>
+ <string name="storage_category" msgid="2287342585424631813">"فضای ذخیرهسازی"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"دادههای همرسانیشده"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"مشاهده و تغییر دادههای همرسانیشده"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"شناسه دادههای همرسانیشده: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"تاریخ انقضا <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"دادههای همرسانی برنامهها"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"برنامه هیچ توضیحی ارائه نکرده است."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"تاریخ انقضای کرایه <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"حذف دادههای همرسانیشده"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"مطمئن هستید میخواهید این دادههای همرسانیشده را حذف کنید؟"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"کاربران دارای برنامهها و محتوای متعلق به خود هستند"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"میتوانید از حساب خود دسترسی به برنامهها و محتوا را محدود کنید"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"کاربر"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"نمایه محدود شده"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"کاربر جدیدی اضافه میکنید؟"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"با ایجاد کاربران بیشتر، میتوانید این دستگاه را با دیگران بهاشتراک بگذارید. هر کاربر فضای مخصوص به خودش را دارد که میتواند آن را با برنامهها، کاغذدیواری و موارد دیگر سفارشی کند. همچنین کاربران میتوانند تنظیماتی در دستگاه ایجاد کنند، مانند تنظیمات Wi-Fi، که بر تنظیمات بقیه اثر دارد.\n\nوقتی کاربر جدیدی اضافه میکنید، آن شخص باید فضای خودش را تنظیم کند.\n\nهر کاربر میتواند برنامهها را برای سایر کاربران بهروزرسانی کند. دسترسپذیری، تنظیمات، و سرویسها قابلانتقال به کاربر جدید نیستند."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"وقتی کاربر جدیدی اضافه میکنید آن فرد باید فضای خودش را تنظیم کند.\n\nهر کاربری میتواند برنامهها را برای همه کاربران دیگر بهروزرسانی کند."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"هم اکنون کاربر تنظیم شود؟"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"مطمئن شوید شخص در دسترس است تا دستگاه را بگیرد و فضایش را تنظیم کند"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"اکنون نمایه را تنظیم میکنید؟"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"اکنون تنظیم شود"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"اکنون نه"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"افزودن"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"کاربر جدید"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"نمایه جدید"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"اطلاعات کاربر"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"اطلاعات نمایه"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"قبل از ایجاد یک نمایه محدود، باید یک قفل صفحه را برای محافظت از برنامهها و دادههای شخصی خود تنظیم کنید."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"تنظیم قفل"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 2bc53af..57ab974 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-osoite & portti"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skannaa QR-koodi"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Muodosta laitepari Wi-Fi-yhteyden kautta skannaamalla QR-koodi"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Yhdistä langattomaan verkkoon"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, virheenkorjaus, kehittäminen"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Virheraportin pikakuvake"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Näytä virheraporttipainike virtavalikossa."</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (puna-vihersokeus)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (sini-keltasokeus)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värikorjaus"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Värinkorjauksella voit muuttaa värien näkymistä laitteellasi"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Varaus loppuu noin <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Varaus loppuu noin <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> saakka"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Akku voi loppua <xliff:g id="TIME">%1$s</xliff:g> mennessä"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Alle <xliff:g id="THRESHOLD">%1$s</xliff:g> jäljellä"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Alle <xliff:g id="THRESHOLD">%1$s</xliff:g> jäljellä (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Yli <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Puhelimen kaiutin"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Yhteysvirhe. Sammuta laite ja käynnistä se uudelleen."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Langallinen äänilaite"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Ohje ja palaute"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Tallennustila"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Jaettu data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Katso ja muokkaa jaettua dataa"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Jaetun datan tunnus: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Vanhenee <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Dataa jakavat sovellukset"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Sovelluksella ei ole kuvausta."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Vuokra-aika päättyy <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Poista jaettu data"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Haluatko varmasti poistaa tämän jaetun datan?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Tavallisilla käyttäjillä on omia sovelluksia ja sisältöä."</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Voit rajoittaa tilisi sovelluksien ja sisällön käyttöä"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Käyttäjä"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Rajoitettu profiili"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Lisätäänkö uusi käyttäjä?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Voit jakaa tämän laitteen muiden kanssa luomalla lisää käyttäjiä. Kullakin käyttäjällä on oma tilansa, jota he voivat muokata esimerkiksi omilla sovelluksilla ja taustakuvilla. Käyttäjät voivat myös muokata laiteasetuksia, kuten Wi‑Fi-asetuksia, jotka vaikuttavat laitteen kaikkiin käyttäjiin.\n\nKun lisäät uuden käyttäjän, hänen tulee määrittää oman tilansa asetukset.\n\nKaikki käyttäjät voivat päivittää muiden käyttäjien sovelluksia. Esteettömyysominaisuuksia tai ‑palveluita ei välttämättä siirretä uudelle käyttäjälle."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Kun lisäät uuden käyttäjän, hänen tulee määrittää oman tilansa asetukset.\n\nKaikki käyttäjät voivat päivittää sovelluksia muille käyttäjille."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Määritetäänkö käyttäjän asetukset nyt?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Varmista, että käyttäjä voi vastaanottaa laitteen ja määrittää oman tilansa."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Määritetäänkö profiilin asetukset nyt?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Määritä nyt"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ei nyt"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Lisää"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Uusi käyttäjä"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Uusi profiili"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Käyttäjätiedot"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profiilin tiedot"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Ennen kuin voit luoda rajoitetun profiilin, määritä näytön lukitus, joka suojelee sovelluksiasi ja henkilökohtaisia tietojasi."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Aseta lukitus"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 330c180..10ed6c1 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresse IP et port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Numériser le code QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Associer un appareil par Wi-Fi en numérisant un code QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Veuillez vous connecter à un réseau Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, concepteur"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Raccourci de rapport de bogue"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afficher un bouton permettant d\'établir un rapport de bogue dans le menu de démarrage"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rouge/vert)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (bleu/jaune)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correction des couleurs"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La correction des couleurs vous permet d\'ajuster la manière dont les couleurs s\'affichent sur votre appareil"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> : <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Jusqu\'à <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"La pile risque d\'être épuisée à <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Haut-parleur du téléphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteingez et rallumez l\'appareil"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio à câble"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Aide et commentaires"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Stockage"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Données partagées"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Afficher et modifier les données partagées"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Identifiant de données partagées : <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Expirent le <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Applications qui partagent des données"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Aucune description fournie par l\'application."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Le bail expire le <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Supprimer les données partagées"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Voulez-vous vraiment supprimer ces données partagées?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Les utilisateurs disposent de leurs propres applications et de leur propre contenu."</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Vous pouvez limiter l\'accès aux applications et au contenu depuis votre compte."</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Utilisateur"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil limité"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Ajouter un utilisateur?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Vous pouvez partager cet appareil avec d\'autres personnes en ajoutant des utilisateurs. Chaque utilisateur dispose de son propre espace, où il peut personnaliser, entre autres, ses applications et son fond d\'écran. Chacun peut également modifier les paramètres de l\'appareil, comme les réseaux Wi-Fi, qui touchent tous les utilisateurs.\n\nLorsque vous ajoutez un utilisateur, celui-ci doit configurer son propre espace.\n\nTout utilisateur peut mettre à jour les applications pour les autres utilisateurs. Il se peut que les paramètres et les services d\'accessibilité ne soient pas transférés aux nouveaux utilisateurs."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.\n\nTout utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurer l\'utilisateur?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Assurez-vous que la personne est disponible et qu\'elle peut utiliser l\'appareil pour configurer son espace."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Configurer le profil maintenant?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configurer maintenant"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Pas maintenant"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Ajouter"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nouvel utilisateur"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Nouveau profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Informations sur l\'utilisateur"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informations de profil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Avant de créer un profil limité, vous devez définir un écran de verrouillage pour protéger vos applications et vos données personnelles."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 2a28037..014a175 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresse IP et port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scanner un code QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Associer l\'appareil via le Wi‑Fi à l\'aide d\'un code QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Connectez-vous à un réseau Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Raccourci vers rapport de bug"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afficher un bouton dans le menu de démarrage permettant de créer un rapport de bug"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rouge/vert)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (bleu-jaune)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correction couleur"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La correction des couleurs vous permet d\'ajuster l\'affichage des couleurs sur votre appareil"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Jusqu\'à <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"La batterie risque d\'être épuisée à <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Haut-parleur du téléphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteignez l\'appareil, puis rallumez-le"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio filaire"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Aide et commentaires"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Stockage"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Données partagées"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Afficher et modifier les données partagées"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID de données partagées : <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Date d\'expiration : <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Applications qui partagent des données"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Aucune description fournie par l\'application."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Date d\'expiration des données partagées : <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Supprimer les données partagées"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Voulez-vous vraiment supprimer ces données partagées ?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Les utilisateurs disposent de leurs propres applications et de leur propre contenu."</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Vous pouvez limiter l\'accès aux applications et au contenu depuis votre compte."</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Utilisateur"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil limité"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Ajouter un utilisateur ?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Vous pouvez partager cet appareil avec d\'autres personnes en ajoutant des utilisateurs. Chaque utilisateur dispose de son propre espace où il peut personnaliser ses applications et son fond d\'écran, entre autres. Chaque utilisateur peut également modifier les paramètres de l\'appareil qui s\'appliquent à tous, tels que le Wi-Fi.\n\nLorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.\n\nN\'importe quel utilisateur peut mettre à jour les applications pour tous les autres. Toutefois, il est possible que les services et les paramètres d\'accessibilité ne soient pas transférés vers le nouvel utilisateur."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace.\n\nN\'importe quel utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurer l\'utilisateur ?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Assurez-vous que la personne est prête à utiliser l\'appareil et à configurer son espace."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Configurer le profil maintenant ?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configurer"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Pas maintenant"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Ajouter"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nouvel utilisateur"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Nouveau profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Infos utilisateur"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informations de profil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Avant de créer un profil limité, vous devez définir un écran de verrouillage pour protéger vos applications et vos données personnelles."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index e33d951..46c5128 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Enderezo IP e porto"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Escanear o código QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Vincula o dispositivo a través da wifi escaneando un código QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conéctate a unha rede wifi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, depuración, programador"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Atallo do informe de erros"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostra un botón no menú de acendido para crear un informe de erros"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (vermello-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección da cor"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"A corrección da cor permíteche axustar como se mostran as cores no dispositivo"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Debería durar aproximadamente ata a seguinte hora: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Debería durar aproximadamente ata a seguinte hora: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Ata: <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"A batería pode esgotarse á seguinte hora: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Tempo restante inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Tempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Tempo restante: máis de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altofalante do teléfono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Produciuse un problema coa conexión. Apaga e acende o dispositivo."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Axuda e comentarios"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Almacenamento"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Datos compartidos"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Consulta e modifica os datos compartidos"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Código de identificación dos datos compartidos: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Caduca o <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplicacións que comparten datos"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"A aplicación non forneceu ningunha descrición."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"O alugueiro caduca o <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Eliminar datos compartidos"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Seguro que queres eliminar estes datos compartidos?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Os usuarios teñen as súas propias aplicacións e contidos"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Podes restrinxir o acceso a aplicacións e contido da túa conta"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Usuario"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restrinxido"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Engadir un usuario novo?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Podes compartir este dispositivo con outras persoas a través da creación de usuarios adicionais. Cada usuario ten o seu propio espazo que pode personalizar coas súas propias aplicacións, fondos de pantalla etc. Os usuarios tamén poden modificar as opcións de configuración do dispositivo, como a rede wifi, que afectan a todo o mundo.\n\nCando engadas un usuario novo, este deberá configurar o seu espazo.\n\nCalquera usuario pode actualizar as aplicacións para todos os demais usuarios. Non se poden transferir ao novo usuario os servizos nin a configuración de accesibilidade."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Cando engadas un usuario novo, este deberá configurar o seu espazo.\n\nCalquera usuario pode actualizar as aplicacións para todos os demais usuarios."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurar o usuario agora?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Asegúrate de que a persoa está dispoñible para acceder ao dispositivo e configurar o seu espazo"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Configurar o perfil agora?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configurar agora"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Agora non"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Engadir"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Novo usuario"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Novo perfil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Información usuario"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Información do perfil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restrinxido, precisarás configurar un bloqueo da pantalla para protexer as túas aplicacións e datos persoais."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 156c0fc..564b703 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -519,10 +519,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -533,4 +541,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"વપરાશકર્તાઓ પાસે તેઓની પોતાની ઍપ્લિકેશનો અને કન્ટેન્ટ છે"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"તમે તમારા એકાઉન્ટથી ઍપ્લિકેશનો અને સામગ્રીની અૅક્સેસને નિયંત્રિત કરી શકો છો"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"વપરાશકર્તા"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"પ્રતિબંધિત પ્રોફાઇલ"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"નવા વપરાશકર્તાને ઉમેરીએ?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"તમે વધારાના વપરાશકર્તાઓ બનાવીને અન્ય લોકો સાથે આ ઉપકરણને શેર કરી શકો છો. દરેક વપરાશકર્તા પાસે તેમની પોતાની સ્પેસ છે, જેને તેઓ ઍપ, વૉલપેપર, વગેરે સાથે કસ્ટમાઇઝ કરી શકે છે. વપરાશકર્તાઓ પ્રત્યેક વ્યક્તિને અસર કરતી હોય તેવી ઉપકરણ સેટિંગ જેમ કે વાઇ-ફાઇને પણ સમાયોજિત કરી શકે છે.\n\nજ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિને તેમની સ્પેસ સેટ કરવાની જરૂર પડે છે.\n\nકોઈપણ વપરાશકર્તા અન્ય બધા વપરાશકર્તાઓ માટે ઍપને અપડેટ કરી શકે છે. નવા વપરાશકર્તાને ઍક્સેસિબિલિટી સેટિંગ અને સેવાઓ ટ્રાન્સફર ન પણ થાય."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"જ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિને તેમનું સ્થાન સેટ અપ કરવાની જરૂર પડે છે.\n\nકોઈપણ વપરાશકર્તા બધા અન્ય વપરાશકર્તાઓ માટે એપ્લિકેશન્સને અપડેટ કરી શકે છે."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"અત્યારે જ વપરાશકર્તાને સેટ અપ કરીએ?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ખાતરી કરો કે વ્યક્તિ ઉપકરણ લેવા અને તેમના સ્થાનનું સેટ અપ કરવા માટે ઉપલબ્ધ છે"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"હવે પ્રોફાઇલ સેટ કરીએ?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"હવે સેટ કરો"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"હમણાં નહીં"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"ઉમેરો"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"નવો વપરાશકર્તા"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"નવી પ્રોફાઇલ"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"વપરાશકર્તા માહિતી"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"પ્રોફાઇલ માહિતી"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"તમે પ્રતિબંધિત પ્રોફાઇલ બનાવી શકો તે પહેલાં, તમારે તમારી ઍપ્લિકેશનો અને વ્યક્તિગત ડેટાની સુરક્ષા માટે એક લૉક સ્ક્રીન સેટ કરવાની જરૂર પડશે."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"લૉક સેટ કરો"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index fb2ed03..556600f 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"आईपी पता और पोर्ट"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"क्यूआर कोड स्कैन करें"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"क्यूआर कोड स्कैन करके, वाई-फ़ाई से डिवाइस को जोड़ें"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"कृपया किसी वाई-फ़ाई नेटवर्क से कनेक्ट करें"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"गड़बड़ी की रिपोर्ट का शॉर्टकट"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"गड़बड़ी की रिपोर्ट लेने के लिए पावर मेन्यू में कोई बटन दिखाएं"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"लाल रंग पहचान न पाना (लाल-हरा)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"नीला रंग पहचान न पाना (नीला-पीला)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रंग सुधार"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"रंग में सुधार करने की सुविधा, आपके डिवाइस पर दिखने वाले रंगों में बदलाव करने में मदद करती है"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"बैटरी करीब <xliff:g id="TIME_REMAINING">%1$s</xliff:g> में खत्म हो जाएगी"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"बैटरी करीब <xliff:g id="TIME">%1$s</xliff:g> चलेगी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"बैटरी करीब <xliff:g id="TIME">%1$s</xliff:g> चलेगी"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> तक"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"बैटरी <xliff:g id="TIME">%1$s</xliff:g> तक खत्म हो जाएगी"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> से कम समय बचा है"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> से कम बैटरी बची है (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> से ज़्यादा चलने लायक बैटरी बची है (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"फ़ोन का स्पीकर"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करने में समस्या हो रही है. डिवाइस को बंद करके चालू करें"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर वाला ऑडियो डिवाइस"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"सहायता और सुझाव"</string>
+ <string name="storage_category" msgid="2287342585424631813">"डिवाइस की मेमोरी"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"शेयर किया गया डेटा"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"शेयर किए गए डेटा को देखे और उसमें बदलाव करें"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"शेयर किए गए डेटा का आईडी: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"डेटा का ऐक्सेस <xliff:g id="DATE">%s</xliff:g> को खत्म हो जाएगा"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"ऐप्लिकेशन का शेयर किया गया डेटा"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"ऐप्लिकेशन से कोई जानकारी नहीं मिली."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"लीज़ <xliff:g id="DATE">%s</xliff:g> को खत्म होगी"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"शेयर किया गया डेटा मिटाएं"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"क्या आप वाकई शेयर किया गया यह डेटा मिटाना चाहते हैं?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"उपयोगकर्ताओं के उनके स्वयं के ऐप्लिकेशन और सामग्री होती है"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"आप अपने खाते से ऐप और सामग्री की पहुंच को रोक सकते हैं"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"उपयोगकर्ता"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"प्रतिबंधित प्रोफ़ाइल"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"नया उपयोगकर्ता जोड़ें?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"आप और ज़्यादा उपयोगकर्ता बनाकर इस डिवाइस को दूसरे लोगों के साथ शेयर कर सकते हैं. हर उपयोगकर्ता के पास अपनी जगह होती है, जिसमें वह मनपसंद तरीके से ऐप्लिकेशन, वॉलपेपर और दूसरी चीज़ों में बदलाव कर सकते हैं. उपयोगकर्ता वाई-फ़ाई जैसी डिवाइस सेटिंग में भी बदलाव कर सकते हैं, जिसका असर हर किसी पर पड़ेगा.\n\nजब आप कोई नया उपयोगकर्ता जोड़ते हैं तो उन्हें अपनी जगह सेट करनी होगी.\n\nकोई भी उपयोगकर्ता दूसरे सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकते हैं. हो सकता है कि सुलभता सेटिंग और सेवाएं नए उपयोगकर्ता को ट्रांसफ़र न हो पाएं."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं तो उसे अपनी जगह सेट करनी होती है.\n\nकोई भी उपयोगकर्ता बाकी सभी उपयोगकर्ताओं के लिए ऐप अपडेट कर सकता है."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"उपयोगकर्ता को अभी सेट करें?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"पक्का करें कि व्यक्ति डिवाइस का इस्तेमाल करने और अपनी जगह सेट करने के लिए मौजूद है"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"प्रोफ़ाइल अभी सेट करें?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"अभी सेट करें"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"रद्द करें"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"जोड़ें"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"नया उपयोगकर्ता"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"नई प्रोफ़ाइल"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"उपयोगकर्ता की जानकारी"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"प्रोफ़ाइल की जानकारी"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"इससे पहले कि आप कोई प्रतिबंधित प्रोफ़ाइल बनाएं, आपको अपने ऐप्लिकेशन और व्यक्तिगत डेटा की सुरक्षा करने के लिए एक स्क्रीन लॉक सेट करना होगा."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"लॉक सेट करें"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 4960735..35f3d38 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresa i priključak"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skeniraj QR kôd"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Uparivanje uređaja putem Wi-Fija skeniranjem QR koda"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Povežite se s Wifi mrežom"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, otklanjanje pogrešaka, razvoj"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Prečac izvješća o pogreškama"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikaži gumb u izborniku napajanja za izradu izvješća o programskim pogreškama"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno – zeleno)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo – žuto)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcija boje"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korekcija boje omogućuje vam prilagodbu načina prikazivanja boja na vašem uređaju"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Još otprilike <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Otprilike bi trebalo trajati do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Otprilike bi trebalo trajati do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Baterija bi se mogla isprazniti do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -513,26 +510,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvučnik telefona"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem s povezivanjem. Isključite i ponovo uključite uređaj"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audiouređaj"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Pohrana"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Dijeljeni podaci"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Prikaz i izmjena dijeljenih podataka"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID dijeljenih podataka: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Istječe <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplikacije koje dijele podatke"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"U aplikaciji nije naveden opis."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Najam istječe <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Izbriši dijeljene podatke"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Jeste li sigurni da želite izbrisati te dijeljene podatke?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Korisnici imaju vlastite aplikacije i sadržaj"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Možete ograničiti pristup aplikacijama i sadržaju sa svojeg računa"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Korisnik"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Ograničeni profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Dodati novog korisnika?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Da biste ovaj uređaj dijelili s drugima, možete napraviti dodatne korisnike. Svaki korisnik ima svoj prostor koji može prilagoditi pomoću vlastitih aplikacija, pozadine i tako dalje. Korisnici mogu prilagoditi i postavke uređaja koje utječu na sve ostale korisnike, na primjer Wi‑Fi.\n\nKada dodate novog korisnika, ta osoba mora postaviti svoj prostor.\n\nBilo koji korisnik može ažurirati aplikacije za sve ostale korisnike. Postavke i usluge pristupačnosti možda se neće prenijeti na novog korisnika."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Kada dodate novog korisnika, ta osoba mora postaviti vlastiti prostor.\n\nBilo koji korisnik može ažurirati aplikacije za sve ostale korisnike."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Postaviti korisnika sada?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Provjerite može li osoba uzeti uređaj i postaviti svoj prostor"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Želite li sada postaviti profil?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Postavi sada"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ne sad"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Dodavanje"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Novi korisnik"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Novi profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Podaci o korisniku"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profilni podaci"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Prije izrade ograničenog profila trebate postaviti zaključavanje zaslona radi zaštite svojih aplikacija i osobnih podataka."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Postavi zaključavanje"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 570b075..71fd2e6 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-cím és port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR-kód beolvasása"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Párosítsa az eszközt Wi-Fi-n keresztül QR-kód beolvasásával"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Csatlakozzon Wi-Fi-hálózathoz"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Hibabejelentési gomb"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Gomb megjelenítése a bekapcsolási menüben hibajelentés készítéséhez"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomália (piros– zöld)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomália (kék–sárga)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Színkorrekció"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"A színkorrekcióval módosíthatja a színek megjelenítésének módját az eszközön"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Nagyjából még ennyit bír: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Nagyjából még ennyit bír: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Eddig: <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Az akkumulátor lemerülhet a következő időpontig: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Kevesebb mint <xliff:g id="THRESHOLD">%1$s</xliff:g> van hátra"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Kevesebb mint <xliff:g id="THRESHOLD">%1$s</xliff:g> van hátra (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Kevesebb mint <xliff:g id="TIME_REMAINING">%1$s</xliff:g> van hátra (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon hangszórója"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sikertelen csatlakozás. Kapcsolja ki az eszközt, majd kapcsolja be újra."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vezetékes audioeszköz"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Súgó és visszajelzés"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Tárhely"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Megosztott adatok"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Megosztott adatok megtekintése és módosítása"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Megosztott adat azonosítója: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Lejárat időpontja: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Adatokat megosztó alkalmazások"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Nincs megadva leírás az alkalmazásnál."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"A bérlet a következő időpontban jár le: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Megosztott adat törlése"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Biztosan törli ezt a megosztott adatot?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"A felhasználóknak saját alkalmazásaik és tartalmaik vannak"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Korlátozhatja az alkalmazásokhoz és tartalmakhoz való hozzáférést a fiókjából"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Felhasználó"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Korlátozott profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Hozzáad új felhasználót?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"További felhasználók létrehozásával megoszthatja ezt az eszközt másokkal. Minden felhasználó saját felülettel rendelkezik, amelyet személyre szabhat saját alkalmazásaival, háttérképével stb. A felhasználók módosíthatják az eszköz beállításait is, például a Wi‑Fi használatát, amely mindenkit érint.\n\nHa új felhasználót ad hozzá, az illetőnek be kell állítania saját felületét.\n\nBármely felhasználó frissítheti az alkalmazásokat valamennyi felhasználó számára. Előfordulhat, hogy a kisegítő lehetőségekkel kapcsolatos beállításokat és szolgáltatásokat nem viszi át a rendszer az új felhasználóhoz."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Ha új felhasználót ad hozzá, az illetőnek be kell állítania saját tárterületét.\n\nBármely felhasználó frissítheti az alkalmazásokat valamennyi felhasználó számára."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Beállít most egy felhasználót?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Győződjön meg arról, hogy a személy hozzá tud férni az eszközhöz, hogy beállíthassa a területét"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Létrehoz most egy profilt?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Beállítás most"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Most nem"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Hozzáadás"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Új felhasználó"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Új profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Felhasználói adatok"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profiladatok"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Mielőtt létrehozhatna egy korlátozott profilt, be kell állítania egy képernyőzárat, hogy megvédje alkalmazásait és személyes adatait."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Képernyőzár beállítása"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 755a75f..abc03a7 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP հասցե և միացք"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR կոդի սկանավորում"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Զուգակցեք սարքը՝ Wi‑Fi-ի օգնությամբ սկանավորելով QR կոդը"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Միացեք Wi-Fi ցանցի"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, վրիպազերծում, ծրագրավորող"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Սխալի հաղորդման դյուրանցում"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Գործարկման ցանկում ցույց տալ կոճակը՝ վրիպակների հաղորդման համար"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Պրոտանոմալիա (կարմիր-կանաչ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Տրիտանոմալիա (կապույտ-դեղին)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Գունաշտկում"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Գունաշտկումը թույլ է տալիս կարգավորել գույների ցուցադրումն այս սարքում"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Լիցքը կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) պետք է որ բավականացնի մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Լիցքը պետք է որ բավականացնի մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Մարտկոցի լիցքը կարող է սպառվել մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Մնացել է <xliff:g id="THRESHOLD">%1$s</xliff:g>-ից պակաս"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Մնացել է <xliff:g id="THRESHOLD">%1$s</xliff:g>-ից պակաս (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Մնացել է ավելի քան <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Հեռախոսի բարձրախոս"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Կապի խնդիր կա: Սարքն անջատեք և նորից միացրեք:"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Լարով աուդիո սարք"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Օգնություն և հետադարձ կապ"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Տարածք"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Հասանելի դարձված տվյալներ"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Դիտեք և փոփոխեք հասանելի դարձված տվյալները"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Հասանելի դարձված տվյալների ID՝ <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Ժամկետը լրանում է՝ <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Տվյալներով կիսվող հավելվածներ"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Հավելվածի կողմից տրամադրված նկարագրություն չկա։"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Վարձակալության ժակետն ավարտվում է՝ <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Ջնջել հասանելի դարձված տվյալները"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Իսկապե՞ս ուզում եք ջնջել հասանելի դարձված այս տվյալները։"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Օգտվողներն իրենց անձնական հավելվածներն ու բովանդակությունն ունեն"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Դուք կարող եք սահմանափակել մուտքի իրավունքը ծրագրեր և ձեր հաշվի բովանդակություն:"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Օգտատեր"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Սահմանափակված պրոֆիլ"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Ավելացնե՞լ նոր օգտատեր"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Այս սարքից կարող եք օգտվել մի քանի հոգով: Դրա համար անհրաժեշտ է ստեղծել լրացուցիչ պրոֆիլներ: Յուրաքանչյուր օգտատեր կարող է կարգավորել իր պրոֆիլը ըստ իր հայեցողության և ճաշակի (օր.՝ ընտրել իր ուզած պաստառը, տեղադրել անհրաժեշտ հավելվածները և այլն): Բացի այդ, օգտատերերը կարող են կարգավորել սարքի որոշ պարամետրեր (օր.՝ Wi-Fi-ը), որոնք կգործեն նաև մյուս պրոֆիլների համար:\n\nԵրբ նոր պրոֆիլ ավելացնեք, տվյալ օգտատերը պետք է կարգավորի այն:\n\nՅուրաքանչյուր օգտատեր կարող է թարմացնել մյուս օգտատերերի հավելվածները: Հատուկ գործառույթների և ծառայությունների կարգավորումները կարող են չփոխանցվել նոր օգտատերերին:"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Երբ նոր օգտատեր եք ավելացնում, նա պետք է կարգավորի իր պրոֆիլը:\n\nՑանկացած օգտատեր կարող է թարմացնել հավելվածները մյուս բոլոր հաշիվների համար:"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Կարգավորե՞լ պրոֆիլը"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Համոզվեք, որ անձը կարող է վերցնել սարքը և կարգավորել իր տարածքը"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Կարգավորե՞լ պրոֆիլը հիմա:"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Կարգավորել"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ոչ հիմա"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Ավելացնել"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Նոր օգտատեր"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Նոր պրոֆիլ"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Օգտատիրոջ տեղեկություններ"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Պրոֆիլի տեղեկություններ"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Նախքան դուք կկարողանաք ստեղծել սահմանափակ պրոֆիլ, դուք պետք է կարգավորեք էկրանի կողպումը` ձեր ծրագրերը և անձնական տվյալները պաշտպանելու համար:"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Կարգավորել կողպումը"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 7752f46..27860e9 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Alamat IP & Port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Memindai kode QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Menyambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Harap sambungkan ke jaringan Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Pintasan laporan bug"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Tampilkan tombol di menu daya untuk mengambil laporan bug"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (merah-hijau)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (biru-kuning)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Koreksi warna"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Koreksi warna memungkinkan Anda untuk menyesuaikan cara warna ditampilkan pada perangkat Anda"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Akan bertahan kira-kira sampai pukul <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Akan bertahan kira-kira sampai pukul <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Hingga <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Baterai mungkin habis pada <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Tersisa kurang dari <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Tersisa kurang dari <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Tersisa lebih dari <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Speaker ponsel"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ada masalah saat menghubungkan. Nonaktifkan perangkat & aktifkan kembali"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Perangkat audio berkabel"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Bantuan & masukan"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Penyimpanan"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Data bersama"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Lihat dan ubah data bersama"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID data bersama: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Berlaku sampai <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplikasi yang berbagi data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Tidak ada deskripsi yang disediakan oleh aplikasi."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Lease akan berakhir pada <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Hapus data bersama"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Yakin ingin menghapus data bersama ini?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Pengguna memiliki aplikasi dan konten mereka sendiri"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Anda dapat membatasi akses ke aplikasi dan konten dari akun Anda"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Pengguna"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil dibatasi"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Tambahkan pengguna baru?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Anda dapat berbagi penggunaan perangkat ini dengan orang lain dengan membuat pengguna tambahan. Setiap pengguna memiliki ruang sendiri, yang dapat disesuaikan dengan aplikasi, wallpaper, dan lainnya.\n\nSaat Anda menambahkan pengguna baru, pengguna tersebut perlu menyiapkan ruangnya.\n\nPengguna mana pun dapat mengupdate aplikasi untuk semua pengguna lainnya. Layanan dan setelan aksesibilitas mungkin tidak ditransfer ke pengguna baru."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Saat Anda menambahkan pengguna baru, orang tersebut perlu menyiapkan ruang mereka sendiri.\n\nPengguna mana pun dapat memperbarui aplikasi untuk semua pengguna lain."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Siapkan pengguna sekarang?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Pastikan orang tersebut ada untuk mengambil perangkat dan menyiapkan ruangnya"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Siapkan profil sekarang?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Siapkan sekarang"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Nanti saja"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Tambahkan"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Pengguna baru"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Profil baru"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Info pengguna"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Info profil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Sebelum dapat membuat profil yang dibatasi, Anda perlu menyiapkan kunci layar untuk melindungi aplikasi dan data pribadi Anda."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Setel kunci"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 28cd4c2..f483587 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-tala og gátt"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skanna QR-kóða"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Tengja tæki með Wi-Fi með því að skanna QR-kóða"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Tengstu Wi-Fi neti"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, villuleit, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Flýtileið í villutilkynningu"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Sýna hnapp til að skrá villutilkynningu í valmynd aflrofans"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Litblinda (rauðgræn)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Litblinda (blágul)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Litaleiðrétting"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Litaleiðrétting gerir þér kleift að stilla hvernig litir birtast í tækinu þínu"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Ætti að endast til u.þ.b. <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Ætti að endast til u.þ.b. <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Til klukkan <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Rafhlaðan gæti tæmst kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Minna en <xliff:g id="THRESHOLD">%1$s</xliff:g> eftir"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Minna en <xliff:g id="THRESHOLD">%1$s</xliff:g> eftir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Meira en <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Símahátalari"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Vandamál í tengingu. Slökktu og kveiktu á tækinu"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Snúrutengt hljómtæki"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Hjálp og ábendingar"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Geymsla"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Deild gögn"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Skoða og breyta deildum gögnum"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Deilt gagnaauðkenni: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Rennur út hinn <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Forrit sem deila gögnum"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Forritið er ekki með neina lýsingu."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Leiga rennur út <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Eyða deildum gögnum"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Ertu viss um að þú viljir eyða þessum deildu gögnum?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Notendur hafa sín eigin forrit og efni"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Hægt er að takmarka aðgang að forritum og efni á reikningnum þínum"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Notandi"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Takmarkað snið"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Bæta nýjum notanda við?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Þú getur búið til fleiri notendur til að deila þessu tæki með öðrum. Hver notandi hefur sitt eigið svæði sem viðkomandi getur sérsniðið með forritum, veggfóðri o.s.frv. Notendur geta einnig breytt þeim stillingum tækisins sem hafa áhrif á alla notendur, t.d. Wi-Fi.\n\nÞegar þú bætir nýjum notanda við þarf sá notandi að setja upp svæðið sitt.\n\nHvaða notandi sem er getur uppfært forrit fyrir alla aðra notendur. Ekki er tryggt að stillingar á aðgengi og þjónustu flytjist yfir á nýja notandann."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Þegar þú bætir nýjum notanda við þarf sá notandi að setja upp svæðið sitt.\n\nHvaða notandi sem er getur uppfært forrit fyrir alla aðra notendur."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Setja notanda upp núna?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Gakktu úr skugga um að notandinn geti tekið tækið og sett upp sitt svæði"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Setja upp snið núna?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Setja upp núna"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ekki núna"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Bæta við"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nýr notandi"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Nýtt snið"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Notandaupplýsingar"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Upplýsingar um snið"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Áður en þú getur búið til takmarkað snið þarftu að setja upp skjálás til að vernda forritin þín og persónuleg gögn."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Velja lás"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 09282df..9e94151 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Indirizzo IP e porta"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scansiona codice QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Accoppia il dispositivo tramite Wi-Fi eseguendo la scansione di un codice QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Collegati a una rete Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, debug, sviluppatori"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Scorciatoia segnalazione bug"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostra un pulsante per segnalare i bug nel menu di accensione"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalìa (rosso-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalìa (blu-giallo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correzione del colore"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"La correzione del colore ti consente di regolare la visualizzazione dei colori sul tuo dispositivo"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo rimanente: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> circa"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Tempo stimato rimanente: <xliff:g id="TIME">%1$s</xliff:g> circa (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Tempo stimato rimanente: <xliff:g id="TIME">%1$s</xliff:g> circa"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Fino alle ore <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"La batteria potrebbe esaurirsi entro <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Tempo rimanente: meno di <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Tempo rimanente: meno di <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Tempo rimanente: più di <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altoparlante telefono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema di connessione. Spegni e riaccendi il dispositivo"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo audio cablato"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Guida e feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Archiviazione"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Dati condivisi"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Visualizza e modifica i dati condivisi"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID dati condivisi: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Scadenza: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Dati delle app condivisi"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Nessuna descrizione fornita dall\'app."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Scadenza lease: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Elimina dati condivisi"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Eliminare dati condivisi?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Gli utenti hanno applicazioni e contenuti personali"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Puoi limitare l\'accesso alle applicazioni e ai contenuti dal tuo account"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Utente"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profilo con limitazioni"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Aggiungere un nuovo utente?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Puoi condividere il dispositivo con altre persone creando altri utenti. Ogni utente ha un proprio spazio personalizzabile con app, sfondo e così via. Gli utenti possono anche regolare le impostazioni del dispositivo, come il Wi‑Fi, che riguardano tutti.\n\nQuando crei un nuovo utente, la persona in questione deve configurare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri utenti. I servizi e le impostazioni di accessibilità non potranno essere trasferiti al nuovo utente."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Il nuovo utente, una volta aggiunto, deve impostare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurare l\'utente ora?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Assicurati che la persona sia disponibile a prendere il dispositivo e configurare il suo spazio"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Configurare il profilo ora?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configura ora"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Non ora"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Aggiungi"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nuovo utente"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Nuovo profilo"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Dati utente"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informazioni profilo"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Prima di poter creare un profilo con limitazioni, devi impostare un blocco schermo per proteggere le tue app e i tuoi dati personali."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Imposta blocco"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 3c7fb3d..e052cd7 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"יציאה וכתובת IP"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"סריקת קוד QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"יש לסרוק קוד QR כדי להתאים מכשיר באמצעות Wi‑Fi"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"יש להתחבר לרשת Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ניפוי באגים, פיתוח"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"קיצור של דוח באגים"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"כדי ליצור דוח באגים, הצג לחצן בתפריט לניהול צריכת החשמל"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"פרוטנומליה (אדום-ירוק)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"טריטנומליה (כחול-צהוב)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"תיקון צבע"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"תיקון צבעים מאפשר לשנות את האופן שבו צבעים מוצגים במכשיר שלך"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"הזמן הנותר: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"אמורה להחזיק מעמד בערך עד <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"אמורה להחזיק מעמד בערך עד <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"עד <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"ייתכן שהסוללה תתרוקן עד <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"נותרו פחות מ-<xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"נותרו פחות מ-<xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"נותרו יותר מ-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -514,26 +511,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"רמקול של טלפון"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"יש בעיה בחיבור. עליך לכבות את המכשיר ולהפעיל אותו מחדש"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"התקן אודיו חוטי"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"עזרה ומשוב"</string>
+ <string name="storage_category" msgid="2287342585424631813">"אחסון"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"נתונים משותפים"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"הצגה ושינוי של נתונים משותפים"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"מזהה נתונים משותפים: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"התוקף יפוג ב-<xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"אפליקציות שמשתפות נתונים"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"האפליקציה לא סיפקה תיאור."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"תוקף החכירה (lease) יפוג ב-<xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"מחיקת הנתונים המשותפים"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"הנתונים המשותפים יימחקו. להמשיך?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"למשתמשים יש אפליקציות ותוכן משלהם"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ניתן להגביל את הגישה לאפליקציות ולתוכן מהחשבון שלך"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"משתמש"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"פרופיל מוגבל"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"האם להוסיף משתמש חדש?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"ניתן לשתף מכשיר זה עם אנשים אחרים על ידי יצירת משתמשים נוספים. לכל משתמש מרחב משלו, שאותו אפשר להתאים אישית בעזרת אפליקציות, טפט ופריטים נוספים. המשתמשים יכולים גם להתאים הגדרות של המכשיר כגון Wi‑Fi, שמשפיעות על כולם.\n\nכשמוסיפים משתמש חדש, על משתמש זה להגדיר את המרחב שלו.\n\nכל אחד מהמשתמשים יכול לעדכן אפליקציות לכל שאר המשתמשים. ייתכן שהגדרות ושירותים של נגישות לא יועברו למשתמש החדש."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"בעת הוספת משתמש חדש, על משתמש זה להגדיר את השטח שלו.\n\nכל משתמש יכול לעדכן אפליקציות עבור כל המשתמשים האחרים."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"האם להגדיר משתמש עכשיו?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"כדאי לוודא שהמשתמש זמין ויכול לקחת את המכשיר ולהגדיר את המרחב שלו"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"האם להגדיר פרופיל עכשיו?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"הגדרה"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"לא עכשיו"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"הוספה"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"משתמש חדש"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"פרופיל חדש"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"פרטי משתמש"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"פרטי פרופיל"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"לפני שתוכל ליצור פרופיל מוגבל, תצטרך להגדיר נעילת מסך כדי להגן על האפליקציות ועל הנתונים האישיים שלך."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"הגדרת נעילה"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 5eccfd1..1f1eb02 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP アドレスとポート"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR コードのスキャン"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR コードをスキャンして Wi-Fi 経由でデバイスをペア設定します"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi ネットワークに接続してください"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, デバッグ, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"バグレポートのショートカット"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"電源メニューにバグレポートを取得するボタンを表示する"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"第一色弱(赤緑)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"第三色弱(青黄)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色補正"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"色補正機能を使用して、デバイスで色をどのように表示するかを調整できます"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"電池切れの推定時刻: <xliff:g id="TIME">%1$s</xliff:g>(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"電池切れの推定時刻: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> まで"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g> 頃に電池がなくなります"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"残り時間: <xliff:g id="THRESHOLD">%1$s</xliff:g>未満"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"残り時間: <xliff:g id="THRESHOLD">%1$s</xliff:g>未満(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"残り時間: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>以上(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"スマートフォンのスピーカー"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"接続エラーです。デバイスを OFF にしてから ON に戻してください"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線オーディオ デバイス"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"ヘルプとフィードバック"</string>
+ <string name="storage_category" msgid="2287342585424631813">"ストレージ"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"共有データ"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"共有データの表示と変更"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"共有データ ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"有効期限: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"データ共有アプリ"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"アプリで説明は提供されていません。"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"リースの有効期限: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"共有データを削除"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"この共有データを削除してもよろしいですか?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"ユーザーは自分のアプリとコンテンツを持っています"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"あなたのアカウントからアプリやコンテンツへのアクセスを制限できます"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"ユーザー"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"制限付きプロファイル"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"新しいユーザーを追加しますか?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"追加ユーザーを作成して、このデバイスを他のユーザーと共有できます。各ユーザーは各自のスペースを所有して、アプリや壁紙などのカスタマイズを行うことができます。Wi-Fi など、すべてのユーザーに影響するデバイス設定を変更することもできます。\n\n新しいユーザーを追加したら、そのユーザーは自分のスペースをセットアップする必要があります。\n\nすべてのユーザーは他のユーザーに代わってアプリを更新できます。ユーザー補助機能の設定とサービスは新しいユーザーに適用されないことがあります。"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"新しいユーザーを追加したら、そのユーザーは自分のスペースをセットアップする必要があります。\n\nすべてのユーザーは他のユーザーに代わってアプリを更新できます。"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ユーザーを今すぐセットアップ"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ユーザーがデバイスを使って各自のスペースをセットアップできるようにします"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"プロファイルを今すぐセットアップしますか?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"今すぐセットアップ"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"後で行う"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"追加"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"新しいユーザー"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"新しいプロファイル"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"ユーザー情報"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"プロファイル情報"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"制限付きプロファイルを作成する場合は、アプリや個人データを保護するように画面ロックを設定しておく必要があります。"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"ロックを設定"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index ff7e59e..9d05471 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP მისამართი და პორტი"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR კოდის სკანირება"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"მოწყობილობის დაწყვილება Wi-Fi-ის მეშვეობით QR კოდის სკანირებით"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"დაუკავშირდით Wi-Fi ქსელს"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, შეცდომების გამართვა, დეველოპერული"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"ხარვეზის შეტყობინების მალსახმობი"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"ელკვების პარამეტრებში ხარვეზის შეტყობინების ღილაკის ჩვენება"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"პროტოანომალია (წითელი-მწვანე)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ტრიტანომალია (ლურჯი-ყვითელი)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ფერის კორექცია"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ფერთა კორექცია საშუალებას გაძლევთ დაარეგულიროთ, თუ როგორ გამოჩნდება ფერები თქვენს მოწყობილობაზე"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"დარჩა დაახლოებით <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"უნდა იმუშაოს დაახლოებით <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"უნდა იმუშაოს დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g>-მდე"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"ბატარეა შესაძლოა ამოიწუროს <xliff:g id="TIME">%1$s</xliff:g>-ისთვის"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"დარჩენილია <xliff:g id="THRESHOLD">%1$s</xliff:g>-ზე ნაკლები"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"დარჩენილია <xliff:g id="THRESHOLD">%1$s</xliff:g>-ზე ნაკლები დრო (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"დარჩენილია <xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ზე მეტი დრო (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"ტელეფონის დინამიკი"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"დაკავშირებისას წარმოიქმნა პრობლემა. გამორთეთ და კვლავ ჩართეთ მოწყობილობა"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"სადენიანი აუდიო მოწყობილობა"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"დახმარება და გამოხმაურება"</string>
+ <string name="storage_category" msgid="2287342585424631813">"საცავი"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"გაზიარებული მონაცემები"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"გაზიარებული მონაცემების ნახვა და შეცვლა"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"გაზიარებულ მონაცემთა ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"ვადა ეწურება <xliff:g id="DATE">%s</xliff:g>-ში"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"აპები, რომლებიც მონაცემებს აზიარებენ"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"აპის მიერ აწერილობა არ არის მოწოდებული."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"დაქირავების ამოწურვის თარიღი: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"გაზიარებული მონაცემების წაშლა"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"ნამდვილად გსურთ ამ გაზიარებული მონაცემების წაშლა?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"მომხმარებლებს აქვთ მათი კუთვნილი აპები და შინაარსი"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"თქვენი ანგარიშიდან შეგიძლიათ შეზღუდოთ აპებზე და კონტენტზე წვდომა"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"მომხმარებელი"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"შეზღუდული პროფილი"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"დაემატოს ახალი მომხმარებელი?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"დამატებითი მომხმარებლების შექმნით, შეგიძლიათ ეს მოწყობილობა სხვებს გაუზიაროთ. ყოველ მომხმარებელს თავისი სივრცე აქვს, რომლის პერსონალიზება შეუძლია საკუთარი აპებით, ფონით და ა.შ. მომხმარებლებს აგრეთვე შეუძლიათ ისეთი პარამეტრების მორგება, როგორიცაა Wi‑Fi, რაც ყველაზე გავრცელდება.\n\nახალი მომხმარებლის დამატების შემდეგ, მომხმარებელმა საკუთარი სივრცე უნდა დააყენოს.\n\nყველა მომხმარებელი შეძლებს აპების ყველა სხვა მომხმარებლისთვის განახლებას. მარტივი წვდომის პარამეტრები/სერვისები შესაძლოა ახალ მომხმარებლებზე არ გავრცელდეს."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"ახალი მომხმარებლის დამატებისას, ამ მომხმარებელს საკუთარი სივრცის შექმნა მოუწევს.\n\nნებისმიერ მომხმარებელს შეუძლია აპები ყველა სხვა მომხმარებლისათვის განაახლოს."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"გსურთ მომხმარებლის პარამეტრების დაყენება?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"დარწმუნდით, რომ პირს შეუძლია მოწყობილობის აღება და საკუთარი სივრცის დაყენება"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"გსურთ დავაყენო პროფილი ახლა?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"დაყენება ახლა"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ახლა არა"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"დამატება"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"ახალი მომხმარებელი"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"ახალი პროფილი"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"მომხმარებლის ინფორმაცია"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"ინფორმაცია პროფილზე"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"შეზღუდული პროფილის შექმნამდე, საკუთარი აპლიკაციებისა და პირადი მონაცემების დასაცავად, უნდა დაბლოკოთ ეკრანი."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"საკეტის დაყენება"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index bb99d3a..8d2efec 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP мекенжайы және порт"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR кодын сканерлеу"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR кодын сканерлеп, құрылғыны Wi‑Fi арқылы жұптау"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi желісіне қосылыңыз."</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, түзету, әзірлеуші"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Қате туралы хабарлау"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Қуат мәзірінде қате туралы хабарлауға арналған түймені көрсету"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (қызыл-жасыл)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (көк-сары)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Түсті түзету"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Түсті түзету функциясының көмегімен құрылғыңызда көрсетілетін түстерді реттеуге болады."</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Шамамен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Шамамен <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) уақытқа жетеді"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Шамамен <xliff:g id="TIME">%1$s</xliff:g> уақытқа жетеді"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> дейін"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Батарея заряды <xliff:g id="TIME">%1$s</xliff:g> сағатқа қарай бітуі мүмкін."</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> шамасынан аз қалды"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> шамасынан аз қалды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> шамасынан көп уақыт қалды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Телефон динамигі"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Байланыс орнату қатесі шығуып жатыр. Құрылғыны өшіріп, қайта қосыңыз."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Сымды аудио құрылғысы"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Анықтама және пікір"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Жад"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Ортақ деректер"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Жалпы деректерді көру және өзгерту"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Жалпы деректер идентификаторы: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Аяқталу мерзімі: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Жалпы деректері бар қолданба"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Қолданба ешқандай сипаттама бермеді."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Рұқсаттың аяқталу мерзімі: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Жалпы деректерді жою"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Осы жалпы деректерді шынымен жойғыңыз келе ме?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Пайдаланушылардың өздерінің қолданбалары мен мазмұны болады"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Өз есептік жазбаңыздан қолданбалар мен мазмұнға қол жетімділікті шектеуіңізге болады"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Пайдаланушы"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Шектелген профайл"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Жаңа пайдаланушы қосылсын ба?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Қосымша профильдер жасай отырып, бұл құрылғыны басқалармен ортақ пайдалануға болады. Әр пайдаланушы қолданбаларды, тұсқағаздарды орнатып, профилін өз қалауынша реттей алады. Сондай-ақ барлығы ортақ қолданатын Wi‑Fi сияқты параметрлерді де реттеуге болады.\n\nЖаңа пайдаланушы енгізілгенде, ол өз профилін реттеуі керек болады.\n\nКез келген пайдаланушы барлық басқа пайдаланушылар үшін қолданбаларды жаңарта алады. Арнайы мүмкіндіктерге қатысты параметрлер мен қызметтер жаңа пайдаланушыға өтпейді."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Жаңа пайдаланушыны қосқанда сол адам өз кеңістігін реттеуі керек.\n\nКез келген пайдаланушы барлық басқа пайдаланушылар үшін қолданбаларды жаңарта алады."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Профиль құру керек пе?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Пайдаланушы құрылығыны алып, өз профилін реттеуі керек."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Профайл қазір жасақталсын ба?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Қазір құру"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Қазір емес"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Қосу"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Жаңа пайдаланушы"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Жаңа профайл"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Пайдаланушы туралы ақпарат"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Профильдік ақпарат"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Шектелген профайл жасақтауға дейін қолданбалар мен жеке деректерді қорғау үшін экран бекітпесін тағайындау қажет."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Бекітпе тағайындау"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index b9ede1d..de63a8e 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"អាសយដ្ឋាន IP និងច្រក"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"ស្កេនកូដ QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"ផ្គូផ្គងឧបករណ៍តាមរយៈ Wi‑Fi ដោយស្កេនកូដ QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"សូមភ្ជាប់ទៅបណ្តាញ Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ជួសជុល, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"ផ្លូវកាត់រាយការណ៍កំហុស"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"បង្ហាញប៊ូតុងក្នុងម៉ឺនុយប៊ូតុងថាមពលសម្រាប់ការទទួលយករបាយការណ៍កំហុស"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ក្រហមពណ៌បៃតង)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ពណ៌ខៀវ-លឿង)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ការកែពណ៌"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ការកែតម្រូវពណ៌អនុញ្ញាតឱ្យអ្នកកែតម្រូវរបៀបបង្ហាញពណ៌នៅលើឧបករណ៍របស់អ្នក"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"បដិសេធដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"នៅសល់ប្រហែល <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"គួរតែអាចប្រើបានរហូតដល់ម៉ោងប្រហែល <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"គួរតែអាចប្រើបានរហូតដល់ម៉ោងប្រហែល <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"រហូតដល់ម៉ោង <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"អាចនឹងអស់ថ្មត្រឹមម៉ោង <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"នៅសល់តិចជាង <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"នៅសល់តិចជាង <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"នៅសល់ច្រើនជាង <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"ឧបករណ៍បំពងសំឡេងទូរសព្ទ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"មានបញ្ហាក្នុងការភ្ជាប់។ បិទ រួចបើកឧបករណ៍វិញ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ឧបករណ៍សំឡេងប្រើខ្សែ"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"ជំនួយ និងមតិកែលម្អ"</string>
+ <string name="storage_category" msgid="2287342585424631813">"ទំហំផ្ទុក"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"ទិន្នន័យដែលបានចែករំលែក"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"មើល និងកែទិន្នន័យដែលបានចែករំលែក"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"លេខសម្គាល់ទិន្នន័យដែលបានចែករំលែក៖ <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"ផុតកំណត់នៅថ្ងៃទី <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"កម្មវិធីដែលកំពុងចែករំលែកទិន្នន័យ"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"គ្មានការពណ៌នាដែលផ្ដល់ដោយកម្មវិធីទេ។"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"ការជួលផុតកំណត់នៅថ្ងៃទី <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"លុបទិន្នន័យដែលបានចែករំលែក"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"តើអ្នកប្រាកដថាចង់លុបទិន្នន័យដែលបានចែករំលែកនេះដែរទេ?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"អ្នកប្រើមានកម្មវិធី និងមាតិកាផ្ទាល់របស់ពួកគេ"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"អ្នកអាចដាក់កម្រិតចូលដំណើរការកម្មវិធី និងមាតិកាពីគណនីរបស់អ្នក"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"អ្នកប្រើ"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"ប្រវត្តិបានដាក់កម្រិត"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"បញ្ចូលអ្នកប្រើប្រាស់ថ្មី?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"អ្នកអាចចែករំលែកឧបករណ៍នេះជាមួយមនុស្សផ្សេងទៀតបានដោយបង្កើតអ្នកប្រើប្រាស់បន្ថែម។ អ្នកប្រើប្រាស់ម្នាក់ៗមានទំហំផ្ទុកផ្ទាល់ខ្លួនរបស់គេ ដែលពួកគេអាចប្ដូរតាមបំណងសម្រាប់កម្មវិធី ផ្ទាំងរូបភាព និងអ្វីៗផ្សេងទៀត។ អ្នកប្រើប្រាស់ក៏អាចកែសម្រួលការកំណត់ឧបករណ៍ដូចជា Wi‑Fi ដែលប៉ះពាល់ដល់អ្នកប្រើប្រាស់ផ្សេងទៀតផងដែរ។\n\nនៅពេលដែលអ្នកបញ្ចូលអ្នកប្រើប្រាស់ថ្មី បុគ្គលនោះត្រូវតែរៀបចំទំហំផ្ទុករបស់គេ។\n\nអ្នកប្រើប្រាស់ណាក៏អាចដំឡើងកំណែកម្មវិធីសម្រាប់អ្នកប្រើប្រាស់ទាំងអស់ផ្សេងទៀតបានដែរ។ ការកំណត់ភាពងាយស្រួល និងសេវាកម្មមិនអាចផ្ទេរទៅកាន់អ្នកប្រើប្រាស់ថ្មីបានទេ។"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"ពេលអ្នកបញ្ចូលអ្នកប្រើប្រាស់ថ្មី អ្នកប្រើប្រាស់នោះត្រូវកំណត់ទំហំផ្ទាល់របស់គេ។\n\nអ្នកប្រើប្រាស់ណាក៏អាចដំឡើងជំនាន់កម្មវិធីសម្រាប់អ្នកប្រើប្រាស់ផ្សេងទាំងអស់បានដែរ។"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"រៀបចំអ្នកប្រើប្រាស់ឥឡូវនេះ?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"សូមប្រាកដថាអ្នកប្រើប្រាស់នេះអាចយកឧបករណ៍ និងរៀបចំទំហំផ្ទុករបស់គេបាន"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"រៀបចំប្រវត្តិរូបឥឡូវ?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"រៀបចំឥឡូវ"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"កុំអាល"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"បន្ថែម"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"អ្នកប្រើថ្មី"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"ប្រវត្តិរូបថ្មី"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"ព័ត៌មានអ្នកប្រើ"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"ព័ត៌មានប្រវត្តិរូប"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"មុនពេលអ្នកអាចបង្កើតប្រវត្តិរូបបានដាក់កម្រិត អ្នកត្រូវរៀបចំការចាក់សោអេក្រង់ ដើម្បីការពារកម្មវិធី និងទិន្នន័យផ្ទាល់ខ្លួនរបស់អ្នក។"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"កំណត់ការចាក់សោ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 22c4950..16ade75 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -418,8 +418,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ಪ್ರೊಟನೋಮಲಿ (ಕೆಂಪು-ಹಸಿರು)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ಟ್ರಿಟನೋಮಲಿ (ನೀಲಿ-ಹಳದಿ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಬಣ್ಣಗಳನ್ನು ಹೇಗೆ ಪ್ರದರ್ಶಿಸಲಾಗುತ್ತದೆ ಎಂಬುದನ್ನು ಹೊಂದಾಣಿಕೆ ಮಾಡಲು ಬಣ್ಣ ತಿದ್ದುಪಡಿಯು ಅವಕಾಶ ನೀಡುತ್ತದೆ"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
@@ -520,10 +519,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -534,4 +541,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"ಬಳಕೆದಾರರು ತಮ್ಮದೇ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ವಿಷಯವನ್ನು ಹೊಂದಿದ್ದಾರೆ"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ನಿಮ್ಮ ಖಾತೆಯಿಂದ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ವಿಷಯಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ನೀವು ನಿರ್ಬಂಧಿಸಬಹುದು"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"ಬಳಕೆದಾರ"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"ನಿರ್ಬಂಧಿಸಿದ ಪ್ರೊಫೈಲ್"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸುವುದೇ?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"ನೀವು ಹೆಚ್ಚುವರಿ ಬಳಕೆದಾರರನ್ನು ರಚಿಸುವ ಮೂಲಕ ಇತರ ಜನರ ಜೊತೆಗೆ ಈ ಸಾಧನವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು. ಪ್ರತಿ ಬಳಕೆದಾರರು ತಮ್ಮದೇ ಸ್ಥಳವನ್ನು ಹೊಂದಿರುತ್ತಾರೆ, ಇದರಲ್ಲಿ ಅವರು ತಮ್ಮದೇ ಅಪ್ಲಿಕೇಶನ್ಗಳು, ವಾಲ್ಪೇಪರ್ ಮತ್ತು ಮುಂತಾದವುಗಳ ಮೂಲಕ ಕಸ್ಟಮೈಸ್ ಮಾಡಿಕೊಳ್ಳಬಹುದು. ಎಲ್ಲರ ಮೇಲೂ ಪರಿಣಾಮ ಬೀರುವಂತೆ ವೈ-ಫೈ ರೀತಿಯ ಸಾಧನ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬಳಕೆದಾರರು ಸರಿಹೊಂದಿಸಬಹುದು.\n\nನೀವು ಒಬ್ಬ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ಅವರ ಸ್ಥಳವನ್ನು ಹೊಂದಿಸಬೇಕಾಗುತ್ತದೆ.\n\nಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗೆ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದು. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಸೇವೆಗಳು ಹೊಸ ಬಳಕೆದಾರರಿಗೆ ವರ್ಗಾವಣೆ ಆಗದಿರಬಹುದು."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"ನೀವು ಒಬ್ಬ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ಅವರ ಸ್ಥಳವನ್ನು ಸ್ಥಾಪಿಸಬೇಕಾಗುತ್ತದೆ.\n\nಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದು."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ಈಗ ಬಳಕೆದಾರರನ್ನು ಸೆಟಪ್ ಮಾಡುವುದೇ?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ಸಾಧನವನ್ನು ತೆಗೆದುಕೊಳ್ಳಲು ಮತ್ತು ಅದರ ಸ್ಥಳವನ್ನು ಹೊಂದಿಸಲು ವ್ಯಕ್ತಿಯು ಲಭ್ಯವಿದ್ದಾರೆಯೇ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ಇದೀಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು ಹೊಂದಿಸುವುದೇ?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ಇದೀಗ ಹೊಂದಿಸಿ"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ಈಗಲೇ ಬೇಡ"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"ಸೇರಿಸಿ"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"ಹೊಸ ಬಳಕೆದಾರರು"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"ಹೊಸ ಪ್ರೊಫೈಲ್"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"ಬಳಕೆದಾರರ ಮಾಹಿತಿ"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"ಪ್ರೊಫೈಲ್ ಮಾಹಿತಿ"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"ನೀವು ನಿರ್ಬಂಧಿತ ಪ್ರೊಫೈಲ್ ಅನ್ನು ರಚಿಸಬಹುದಾದರ ಮೊದಲು, ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ವೈಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ರಕ್ಷಿಸಲು ನೀವು ಪರದೆಯ ಲಾಕ್ ಹೊಂದಿಸುವ ಅಗತ್ಯವಿದೆ."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"ಲಾಕ್ ಹೊಂದಿಸಿ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index e0874a3..4fc865e 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP 주소 및 포트"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR 코드 스캔"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR 코드를 스캔하여 Wi‑Fi를 통해 기기 페어링"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi 네트워크에 연결하세요."</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, 디버그, 개발자"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"버그 신고 바로가기"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"전원 메뉴에 버그 신고 버튼 표시"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"적색약(적녹)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"청색약(청황)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"색보정"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"색상 보정을 사용하면 기기에 표시되는 색상을 조절할 수 있습니다."</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>, <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"남은 시간 약 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"약 <xliff:g id="TIME">%1$s</xliff:g>까지 사용 가능(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"약 <xliff:g id="TIME">%1$s</xliff:g>까지 사용 가능"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g>까지"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"예상 배터리 종료 시간: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> 미만 남음"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> 미만 남음(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> 이상 남음(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"휴대전화 스피커"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"연결 중에 문제가 발생했습니다. 기기를 껐다가 다시 켜 보세요."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"유선 오디오 기기"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"고객센터"</string>
+ <string name="storage_category" msgid="2287342585424631813">"저장용량"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"공유 데이터"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"공유 데이터 보기 및 수정"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"공유 데이터 ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"만료일: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"데이터 공유 앱"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"앱에서 제공한 설명이 없습니다."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"권한 만료일: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"공유 데이터 삭제"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"공유 데이터를 삭제하시겠습니까?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"사용자는 자신의 앱과 콘텐츠를 보유합니다."</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"내 계정의 앱 및 콘텐츠에 대한 액세스를 제한할 수 있습니다."</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"사용자"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"제한된 프로필"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"새 사용자를 추가할까요?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"추가 사용자를 만들어 다른 사용자와 기기를 공유할 수 있습니다. 각 사용자는 앱, 배경화면 등으로 맞춤설정할 수 있는 자신만의 공간을 갖게 됩니다. 또한 모든 사용자에게 영향을 미치는 Wi‑Fi와 같은 기기 설정도 조정할 수 있습니다.\n\n추가된 신규 사용자는 자신의 공간을 설정해야 합니다.\n\n모든 사용자가 앱을 업데이트할 수 있으며, 업데이트는 다른 사용자에게도 적용됩니다. 접근성 설정 및 서비스는 신규 사용자에게 이전되지 않을 수도 있습니다."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"추가된 새로운 사용자는 자신의 공간을 설정해야 합니다.\n\n모든 사용자는 다른 사용자들을 위하여 앱을 업데이트할 수 있습니다."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"지금 사용자를 설정하시겠습니까?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"사용자가 기기에서 자신의 공간을 설정하도록 하세요."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"지금 프로필을 설정하시겠습니까?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"지금 설정"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"나중에"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"추가"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"새 사용자"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"새 프로필"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"사용자 정보"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"프로필 정보"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"제한된 프로필을 만들기 전에 화면 잠금을 설정하여 앱과 개인 데이터를 보호해야 합니다."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"잠금 설정"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 6e28f0b..bb6dfad 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP дареги жана Оюкча"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR кодун скандоо"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR кодун скандап, түзмөктү Wi‑Fi аркылуу жупташтырыңыз"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi тармагына туташыңыз"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, мүчүлүштүктөрдү оңдоо, иштеп чыгуу"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Ката жөнүндө кабарлоо"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Менюда ката жөнүндө кабарлоо баскычы көрүнүп турат"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (кызыл-жашыл)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (көк-сары)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Түсүн тууралоо"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Түстөрдү тууралоо менен, түзмөгүңүздүн экранынын түстөрүн өзгөртө аласыз"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Болжол менен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Болжол менен <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) кийин өчөт"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Болжол менен <xliff:g id="TIME">%1$s</xliff:g> кийин өчөт"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> чейин"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Батарея <xliff:g id="TIME">%1$s</xliff:g> отуруп калышы мүмкүн"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> жетпеген убакыт калды"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> жетпеген убакыт калды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ашыгыраак убакыт калды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Телефондун динамиги"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Туташууда маселе келип чыкты. Түзмөктү өчүрүп, кайра күйгүзүп көрүңүз"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Зымдуу аудио түзмөк"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Жардам/Пикир билдирүү"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Сактагыч"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Бөлүшүлгөн маалымат"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Бөлүшүлгөн маалыматты көрүп, өзгөртүү"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Бөлүшүлгөн маалыматты идентификатору: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Мөөнөтү <xliff:g id="DATE">%s</xliff:g> бүтөт"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Маалыматты бөлүшкөн колдонмолор"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Колдонмодо эч кандай сүрөттөмө берилген жок."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Ижаранын мөөнөтү <xliff:g id="DATE">%s</xliff:g> бүтөт"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Бөлүшүлгөн маалыматты жок кылуу"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Бул бөлүшүлгөн маалыматты чын эле жок кыласызбы?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Колдонуучулардын өз колдонмолору жана мазмундары болот"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Аккаунтуңуздан колдонмолорго жана мазмундарга кирүүнү чектеп койсоңуз болот"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Колдонуучу"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Чектелген профайл"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Жаңы колдонуучу кошосузбу?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Эгер түзмөгүңүздү дагы бир адам колдонуп жаткан болсо, кошумча профилдерди түзүп коюңуз. Профилдин ээси аны өзү каалагандай жөндөп, тушкагаздарды коюп, керектүү колдонмолорду орнотуп алат. Мындан тышкары, колдонуучулар түзмөктүн Wi‑Fi´ды өчүрүү/күйгүзүү сыяктуу жалпы жөндөөлөрүн өзгөртө алат.\n\nПрофиль түзүлгөндөн кийин, аны жөндөп алуу керек.\n\nЖалпы колдонмолорду баары жаңырта алат, бирок атайын мүмкүнчүлүктөр өз-өзүнчө жөндөлөт."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Жаңы колдонуучу кошулганда, ал өз мейкиндигин түзүп алышы керек.\n\nКолдонмолорду бир колдонуучу жаңыртканда, ал калган бардык колдонуучулар үчүн да жаңырат."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Профилди жөндөйсүзбү?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Өз мейкиндигин жөндөп алышы үчүн түзмөктү колдонуучуга беришиңиз керек."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Профайл азыр түзүлсүнбү?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Азыр түзүү"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Азыр эмес"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Кошуу"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Жаңы колдонуучу"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Жаңы профайл"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Колдонуучу тууралуу"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Профилдин чоо-жайы"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Чектелген профайл түзөөрдөн мурун, сиз өзүңүздүн колдонмолоруңузду жана жеке маалыматтарыңызды коргош үчүн, бөгөттөө көшөгөсүн орнотушуңуз керек болот."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Бөгөт коюу"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index f4077a1..c39891b 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -418,8 +418,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ສີແດງ-ສີຂຽວ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ສີຟ້າ-ສີເຫຼືອງ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ການປັບແຕ່ງສີ"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ການແກ້ໄຂສີຈະເຮັດໃຫ້ທ່ານສາມາດປັບແຕ່ງການສະແດງຜົນຂອງສີຢູ່ອຸປະກອນຂອງທ່ານໄດ້"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"ເຫຼືອອີກປະມານ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -520,10 +519,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -534,4 +541,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"ຜູ່ໃຊ້ມີແອັບຯ ແລະເນື້ອຫາຂອງຕົນເອງ"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ທ່ານສາມາດຈໍາກັດການເຂົ້າເຖິງແອັບຯ ແລະເນື້ອຫາຈາກບັນຊີຂອງທ່ານໄດ້"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"ຜູ້ໃຊ້"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"ໂປຣໄຟລ໌ທີ່ຖືກຈຳກັດ"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"ເພີ່ມຜູ້ໃຊ້ໃໝ່ບໍ?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"ທ່ານສາມາດໃຊ້ອຸປະກອນນີ້ຮ່ວມກັບຄົນອື່ນໄດ້ໂດຍການສ້າງຜູ້ໃຊ້ເພີ່ມເຕີມ. ຜູ້ໃຊ້ແຕ່ລະຄົນຈະມີພື້ນທີ່ຂອງຕົວເອງ, ເຊິ່ງເຂົາເຈົ້າສາມາດປັບແຕ່ງແອັບ, ຮູບພື້ນຫຼັງ ແລະ ອື່ນໆໄດ້. ຜູ້ໃຊ້ຕ່າງໆ ສາມາດປັບແຕ່ງການຕັ້ງຄ່າອຸປະກອນໄດ້ ເຊັ່ນ: Wi‑Fi ທີ່ມີຜົນກະທົບທຸກຄົນ.\n\nເມື່ອທ່ານເພີ່ມຜູ້ໃຊ້ໃໝ່, ບຸກຄົນນັ້ນຈະຕ້ອງຕັ້ງຄ່າພື້ນທີ່ຂອງເຂົາເຈົ້າກ່ອນ.\n\nຜູ້ໃຊ້ໃດກໍຕາມສາມາດອັບເດດແອັບສຳລັບຜູ້ໃຊ້ຄົນອື່ນທັງໝົດໄດ້. ການຕັ້ງຄ່າການຊ່ວຍເຂົ້າເຖິງອາດບໍ່ຖືກໂອນຍ້າຍໄປໃຫ້ຜູ້ໃຊ້ໃໝ່."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"ເມື່ອທ່ານເພີ່ມຜູ້ໃຊ້ໃໝ່, ຜູ້ໃຊ້ນັ້ນຈະຕ້ອງຕັ້ງຄ່າພື້ນທີ່ບ່ອນຈັດເກັບຂໍ້ມູນຂອງລາວ.\n\nຜູ້ໃຊ້ທຸກຄົນສາມາດອັບເດດແອັບຯສຳລັບຜູ້ໃຊ້ຄົນອື່ນທັງໝົດໄດ້."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ຕັ້ງຄ່າຜູ້ໃຊ້ຕອນນີ້ບໍ?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ກວດສອບໃຫ້ແນ່ໃຈວ່າບຸກຄົນດັ່ງກ່າວສາມາດຮັບອຸປະກອນ ແລະ ຕັ້ງຄ່າພື້ນທີ່ຂອງພວກເຂົາໄດ້"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ຕັ້ງຄ່າໂປຣໄຟລ໌ດຽວນີ້?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ຕັ້ງຄ່າດຽວນີ້"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ບໍ່ແມ່ນຕອນນີ້"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"ເພີ່ມ"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"ຜູ້ໃຊ້ໃໝ່"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"ໂປຣໄຟລ໌ໃໝ່"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"ຂໍ້ມູນຜູ້ໃຊ້"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"ຂໍ້ມູນໂປຣໄຟລ໌"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"ກ່ອນທ່ານຈະສ້າງໂປຣໄຟລ໌ທີ່ຖືກຈຳກັດນັ້ນ, ທ່ານຈະຕ້ອງຕັ້ງຄ່າການລັອກໜ້າຈໍ ເພື່ອປ້ອງກັນແອັບຯ ແລະຂໍ້ມູນສ່ວນໂຕຂອງທ່ານກ່ອນ."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"ຕັ້ງການລັອກ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 1cb60a2..b64f818 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresas ir prievadas"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR kodo nuskaitymas"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Susiekite įrenginį „Wi‑Fi“ ryšiu nuskaitydami QR kodą"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Prisijunkite prie „Wi-Fi“ tinklo"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, derinti, kūrėjas"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Pranešimo apie riktą spartusis klavišas"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Rodyti pranešimo apie riktą mygtuką maitinimo meniu"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (raudona, žalia)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (mėlyna, geltona)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Spalvų taisymas"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Spalvų taisymo funkcija padės koreguoti, kaip spalvos rodomos jūsų įrenginyje"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Turėtų išsikrauti maždaug po <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Turėtų išsikrauti maždaug po <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Iki <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Akumuliatoriaus energija gali išsekti <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Liko mažiau nei <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Liko mažiau nei <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Liko daugiau nei <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -514,26 +511,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefono garsiakalbis"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Prisijungiant kilo problema. Išjunkite įrenginį ir vėl jį įjunkite"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Laidinis garso įrenginys"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Pagalba ir atsiliepimai"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Saugykla"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Bendrinami duomenys"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Peržiūrėti ir keisti bendrinamus duomenis"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Bendrinamų duomenų ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Galiojimas baigiasi <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Duomenis bendrinančios programos"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Programa nepateikė jokio aprašo."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Nuomos laikas baigiasi <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Ištrinti bendrinamus duomenis"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Ar tikrai norite ištrinti šiuos bendrinamus duomenis?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Naudotojai turi savo programas ir turinį"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Galite apriboti prieigą prie paskyros programų ir turinio"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Naudotojas"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Ribotas profilis"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Pridėti naują naudotoją?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Galite bendrinti šį įrenginį su kitais žmonėmis sukūrę papildomų naudotojų. Kiekvienam naudotojui suteikiama atskira erdvė, kurią jie gali tinkinti naudodami programas, ekrano foną ir kt. Be to, naudotojai gali koreguoti įrenginio nustatymus, pvz., „Wi‑Fi“, kurie taikomi visiems.\n\nKai pridedate naują naudotoją, šis asmuo turi nusistatyti savo erdvę.\n\nBet kuris naudotojas gali atnaujinti visų kitų naudotojų programas. Pasiekiamumo nustatymai ir paslaugos gali nebūti perkeltos naujam naudotojui."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Kai pridedate naują naudotoją, šis asmuo turi nustatyti savo vietą.\n\nBet kuris naudotojas gali atnaujinti visų kitų naudotojų programas."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Nustatyti naudotoją dabar?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Įsitikinkite, kad asmuo gali paimti įrenginį ir nustatyti savo vietą"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Nustatyti profilį dabar?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Nustatyti dabar"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ne dabar"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Pridėti"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Naujas naudotojas"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Naujas profilis"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Naudotojo inform."</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profilio informacija"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Prieš kuriant apribotą profilį reikės nustatyti ekrano užraktą, kad apsaugotumėte programas ir asmeninius duomenis."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Nustatyti užraktą"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 2ae3d6d..e1e0a12 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adrese un ports"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR koda skenēšana"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Izveidojiet savienojumu pārī ar ierīci Wi‑Fi tīklā, skenējot QR kodu."</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Lūdzu, izveidojiet savienojumu ar Wi-Fi tīklu"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, atkļūdošana, izstrādātājiem"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Kļūdu pārskata saīsne"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Izslēgšanas izvēlnē rādīt kļūdu pārskata veidošanas pogu"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomālija (sarkans/zaļš)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomālija (zils/dzeltens)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Krāsu korekcija"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Izmantojot krāsu korekciju, varat koriģēt krāsu attēlojumu savā ierīcē"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> — <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Aptuvenais atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Iespējams, akumulators izlādēsies līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Atlikušais laiks — mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Atlicis mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Atlicis vairāk nekā <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -513,26 +510,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Tālruņa skaļrunis"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Radās problēma ar savienojuma izveidi. Izslēdziet un atkal ieslēdziet ierīci."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vadu audioierīce"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Palīdzība un atsauksmes"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Krātuve"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Koplietotie dati"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Koplietoto datu skatīšana un modificēšana"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Koplietotu datu ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Termiņš beigsies: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Lietotņu koplietošanas dati"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Lietotne nav sniegusi aprakstu."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Nomas termiņš beigsies: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Dzēst koplietotos datus"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Vai tiešām vēlaties dzēst šos koplietotos datus?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Lietotājiem ir savas lietotnes un saturs."</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Varat ierobežot piekļuvi lietotnēm un saturam no sava konta."</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Lietotājs"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Ierobežots profils"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Vai pievienot jaunu lietotāju?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Varat koplietot šo ierīci ar citām personām, izveidojot papildu lietotājus. Katram lietotājam ir sava vide, kas ir pielāgojama, izmantojot lietotnes, fona tapetes u.c. Lietotāji var pielāgot arī ierīces iestatījumus, kas attiecas uz visiem lietotājiem, piemēram, Wi‑Fi.\n\nKad pievienosiet jaunu lietotāju, viņam būs jāizveido sava vide.\n\nIkviens lietotājs var atjaunināt lietotnes citu lietotāju vietā. Pieejamības iestatījumi un pakalpojumi var netikt pārsūtīti jaunajam lietotājam."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Kad pievienosiet jaunu lietotāju, viņam būs jāizveido sava vide.\n\nIkviens lietotājs var atjaunināt lietotnes citu lietotāju vietā."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Iestatīt kontu tūlīt?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Pārliecinieties, ka persona var izmantot ierīci un iestatīt savu vidi."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Vai iestatīt profilu tūlīt?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Iestatīt tūlīt"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Vēlāk"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Pievienošana"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Jauns lietotājs"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Jauns profils"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Lietot. informācija"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profila informācija"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Lai varētu izveidot ierobežotu profilu, jums jāiestata ekrāna bloķēšana, kas aizsargās jūsu lietotni un personas datus."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Iestatīt bloķēšanu"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 439cc11..5bfc30c 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-адреса и порта"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Скенирајте QR-код"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Спарете го уредот преку Wi‑Fi со скенирање QR-код"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Поврзете се на Wi-Fi-мрежа"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, отстранува грешка, програмер"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Кратенка за извештај за грешка"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Прикажи копче во менито за вклучување за да се направи извештај за грешка"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалија (слепило за црвена и зелена)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалија (слепило за сина и жолта)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекција на бои"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Корекцијата на боите ви овозможува да го приспособите начинот на прикажување на боите на вашиот уред"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Треба да трае до околу <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Треба да трае до околу <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"До <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Може да снема батерија до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Уште помалку од <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Уште помалку од <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Уште повеќе од <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Телефонски звучник"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем со поврзување. Исклучете го уредот и повторно вклучете го"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичен аудиоуред"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Помош и повратни информации"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Капацитет"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Споделени податоци"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Прегледајте и изменете ги споделените податоци"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID на споделените податоци: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Истекуваат на <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Апликации што споделуваат податоци"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Апликацијата не дала опис."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Закупот истекува на <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Избриши ги споделените податоци"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Дали сигурно сакате да ги избришете споделениве податоци?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Корисниците имаат свои апликации и содржина"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Може да го ограничите пристапот кон апликациите и содржината од вашата сметка"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Корисник"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Ограничен профил"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Да се додаде нов корисник?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Уредов може да го споделувате со други лица преку создавање дополнителни корисници. Секој корисник има сопствен простор што може да го приспособува со апликации, тапети и слично. Корисниците може да приспособуваат и поставки на уредот, како на пр., Wi‑Fi, што се однесуваат на сите.\n\nКога додавате нов корисник, тоа лице треба да го постави својот простор.\n\nСекој корисник може да ажурира апликации за сите други корисници. Поставките и услугите за пристапност не може да се префрлат на новиот корисник."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Кога додавате нов корисник, тоа лице треба да го постави својот простор.\n\nСекој корисник може да ажурира апликации за сите други корисници."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Ќе поставите корисник сега?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Проверете дали лицето е достапно да го земе уредот и да го постави својот простор"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Постави профил сега?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Постави сега"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Не сега"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Додај"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Нов корисник"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Нов профил"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Информации за корисникот"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Информации за профил"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Пред да може да создадете ограничен профил, треба да поставите заклучување на екранот за да ги заштити вашите апликации и лични податоци."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Постави заклучување"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 9ac1f8d..fbdf682 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -418,8 +418,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"പ്രോട്ടാനോമലി (ചുവപ്പ്-പച്ച)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ട്രിട്ടാനോമലി (നീല-മഞ്ഞ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"വർണ്ണം ക്രമീകരിക്കൽ"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"നിങ്ങളുടെ ഉപകരണത്തിൽ നിറങ്ങൾ എങ്ങനെ പ്രദർശിപ്പിക്കുന്നു എന്നത് ക്രമീകരിക്കാൻ നിറം തിരുത്തൽ അനുവദിക്കുന്നു"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ഉപയോഗിച്ച് അസാധുവാക്കി"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"ഏതാണ്ട് <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
@@ -520,10 +519,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -534,4 +541,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"ഉപയോക്താക്കൾക്ക് സ്വന്തമായ അപ്ലിക്കേഷനുകളും ഉള്ളടക്കവും ഉണ്ടായിരിക്കും"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"നിങ്ങളുടെ അക്കൗണ്ടിൽ നിന്നും അപ്ലിക്കേഷനുകളിലേക്കും ഉള്ളടക്കത്തിലേക്കുമുള്ള ആക്സസ്സ് നിയന്ത്രിക്കാനാകും"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"ഉപയോക്താവ്"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"നിയന്ത്രിത പ്രൊഫൈൽ"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"പുതിയ ഉപയോക്താവിനെ ചേർക്കണോ?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"കൂടുതൽ ഉപയോക്താക്കളെ സൃഷ്ടിച്ചുകൊണ്ട് ഈ ഉപകരണം മറ്റുള്ളവരുമായി നിങ്ങൾക്ക് പങ്കിടാം. ആപ്പുകളും വാൾപേപ്പറുകളും മറ്റും ഉപയോഗിച്ച് ഇഷ്ടാനുസൃതമാക്കാൻ ഓരോ ഉപയോക്താവിനും സാധിക്കും. വൈഫൈ പോലെ എല്ലാവരെയും ബാധിക്കുന്ന ഉപകരണ ക്രമീകരണവും ഉപയോക്താക്കൾക്ക് ക്രമീകരിക്കാം.\n\nനിങ്ങളൊരു പുതിയ ഉപയോക്താവിനെ ചേർക്കുമ്പോൾ, ആ വ്യക്തിക്ക് സ്വന്തമായ ഇടം സജ്ജീകരിക്കേണ്ടതുണ്ട്.\n\n എല്ലാ ഉപയോക്താക്കൾക്കുമായി ആപ്പുകൾ അപ്ഡേറ്റ് ചെയ്യാൻ ഏതൊരു ഉപയോക്താവിനുമാവും. ഉപയോഗസഹായി ക്രമീകരണവും സേവനങ്ങളും പുതിയ ഉപയോക്താവിന് കൈമാറിയേക്കില്ല."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"നിങ്ങൾ ഒരു പുതിയ ഉപയോക്താവിനെ ചേർക്കുമ്പോൾ, ആ വ്യക്തിയ്ക്ക് അവരുടെ ഇടം സജ്ജീകരിക്കേണ്ടതുണ്ട്.\n\nമറ്റ് എല്ലാ ഉപയോക്താക്കൾക്കുമായി ഏതൊരു ഉപയോക്താവിനും അപ്ലിക്കേഷനുകൾ അപ്ഡേറ്റുചെയ്യാനാവും."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ഉപയോക്താവിനെ ഇപ്പോൾ സജ്ജീകരിക്കണോ?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ഉപകരണം എടുത്ത് ഇടം സജ്ജീകരിക്കുന്നതിന് വ്യക്തി ലഭ്യമാണെന്ന് ഉറപ്പാക്കുക"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ഇപ്പോൾ പ്രൊഫൈൽ സജ്ജീകരിക്കണോ?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ഇപ്പോൾ സജ്ജീകരിക്കുക"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ഇപ്പോൾ വേണ്ട"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"ചേര്ക്കുക"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"പുതിയ ഉപയോക്താവ്"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"പുതിയ പ്രൊഫൈൽ"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"ഉപയോക്തൃവിവരം"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"പ്രൊഫൈൽ വിവരം"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"ഒരു നിയന്ത്രിത പ്രൊഫൈൽ സൃഷ്ടിക്കുന്നതിനുമുമ്പ്, നിങ്ങളുടെ അപ്ലിക്കേഷനുകളും വ്യക്തിഗത ഡാറ്റയും പരിരക്ഷിക്കുന്നതിന് ഒരു സ്ക്രീൻ ലോക്ക് സജ്ജീകരിക്കേണ്ടതുണ്ട്."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"ലോക്ക് സജ്ജീകരിക്കുക"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 428d22c..debc85c 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP хаяг ба порт"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Хурдан хариу үйлдлийн кодыг скан хийх"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Хурдан хариу үйлдлийн кодыг скан хийж Wi-Fi-р төхөөрөмжийг хослуулна уу"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi сүлжээнд холбогдоно уу"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, дебаг хийх, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Алдаа мэдээлэх товчлол"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Цэсэнд алдааны мэдэгдэл авахад зориулсан товчийг харуулах"</string>
@@ -432,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> хүртэл барих ёстой (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> хүртэл барих ёстой"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> хүртэл"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Батерейн цэнэг <xliff:g id="TIME">%1$s</xliff:g> гээд дуусаж болзошгүй"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-с бага хугацаа үлдсэн"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-с бага хугацаа үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-с их хугацаа үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -511,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Утасны чанга яригч"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Холбогдоход асуудал гарлаа. Төхөөрөмжийг унтраагаад дахин асаана уу"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Утастай аудио төхөөрөмж"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Тусламж, санал хүсэлт"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Хадгалах сан"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Хуваалцсан өгөгдөл"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Хуваалцсан өгөгдлийг харах, өөрчлөх"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Хуваалцсан өгөгдлийн ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Хугацаа нь <xliff:g id="DATE">%s</xliff:g>-д дуусна"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Аппуудын хуваалцсан өгөгдөл"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Аппаас ямар ч тайлбар өгөөгүй."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Түрээсийн хугацаа <xliff:g id="DATE">%s</xliff:g>-д дуусна"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Хуваалцсан өгөгдлийг устгах уу?"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Та хуваалцсан энэ өгөгдлийг устгахдаа итгэлтэй байна уу?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Хэрэглэгчид өөрийн апп-ууд болон контенттэй"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Та өөрийн бүртгэлийн апп-ууд болон контентэд хандалт хийхийг хязгаарлаж болно"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Хэрэглэгч"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Хязгаарлагдсан профайл"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Шинэ хэрэглэгч нэмэх үү?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Та нэмэлт хэрэглэгч үүсгэх замаар бусад хүмүүстэй энэ төхөөрөмжийг хуваалцаж болно. Хэрэглэгч тус бүр апп, ханын цаас болон бусад зүйлээ өөрчлөх боломжтой хувийн орон зайтай байдаг. Түүнчлэн хэрэглэгч нь бүх хэрэглэгчид нөлөөлөх боломжтой Wi-Fi зэрэг төхөөрөмжийн тохиргоог өөрчлөх боломжтой.\n\nХэрэв та шинэ хэрэглэгч нэмэх бол тухайн хүн хувийн орон зайгаа бүрдүүлэх ёстой.\n\nХэрэглэгч бүр бусад бүх хэрэглэгчийн өмнөөс апп шинэчилж болно. Хүртээмжийн тохиргоо болон үйлчилгээг шинэ хэрэглэгчид шилжүүлэх боломжгүй байж болзошгүй."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Та шинэ хэрэглэгч нэмбэл тухайн хүн өөрийн профайлыг тохируулах шаардлагатай.\n\nАль ч хэрэглэгч бүх хэрэглэгчийн апп-уудыг шинэчлэх боломжтой."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Хэрэглэгчийг одоо тохируулах уу?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Хэрэглэгч төхөөрөмжийг авч өөрийн профайлыг тохируулах боломжтой эсэхийг шалгана уу"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Профайлыг одоо тохируулах уу?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Одоо тохируулах"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Одоо биш"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Нэмэх"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Шинэ хэрэглэгч"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Шинэ профайл"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Хэрэглэгчийн мэдээлэл"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Профайлын мэдээлэл"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Та хязгаарлагдсан профайл үүсгэхийн өмнө өөрийн апп-ууд болон хувийн өгөгдлийг хамгаалахын тулд дэлгэцийн түгжээг тохируулах шаардлагатай."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Түгжээг тохируулах"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 377fa89..e7ae1c1 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"आयपी अॅड्रेस आणि पोर्ट"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR कोड स्कॅन करा"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR कोड स्कॅन करून वाय-फाय वापरून डिव्हाइस पेअर करा"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"कृपया एका वाय-फाय नेटवर्कशी कनेक्ट करा"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, डीबग, डेव्हलपर"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"बग रिपोर्ट शॉर्टकट"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"बग रिपोर्ट घेण्यासाठी पॉवर मेनूमध्ये एक बटण दर्शवा"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"क्षीण रक्तवर्णांधता (लाल-हिरवा)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"रंग दृष्टी कमतरता (निळा-पिवळा)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रंग सुधारणा"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"कलर इन्व्हर्जन तुमच्या डिव्हाइसवर रंग कसे प्रदर्शित केले जातात ते अॅडजस्ट करू देते"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"अंदाजे <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी आहे"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"सुमारे <xliff:g id="TIME">%1$s</xliff:g> पर्यंत टिकेल (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"सुमारे <xliff:g id="TIME">%1$s</xliff:g> पर्यंत टिकावी"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g> वाजेपर्यंत बॅटरी संपू शकते"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> पेक्षा कमी शिल्लक आहे"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> पेक्षा कमी वेळ शिल्लक आहे (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> पेक्षा जास्त वेळ शिल्लक आहे (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"फोनचा स्पीकर"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करण्यात समस्या आली. डिव्हाइस बंद करा आणि नंतर सुरू करा"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर असलेले ऑडिओ डिव्हाइस"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"मदत आणि फीडबॅक"</string>
+ <string name="storage_category" msgid="2287342585424631813">"स्टोरेज"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"शेअर केलेला डेटा"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"शेअर केलेला डेटा पहा आणि सुधारित करा"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"शेअर केलेल्या डेटाचा आयडी: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"<xliff:g id="DATE">%s</xliff:g> रोजी एक्स्पायर होईल"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"डेटा शेअर करणारी ॲप्स"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"अॅपद्वारे कोणतेही वर्णन पुरवलेले नाही."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"भाडेपट्टी <xliff:g id="DATE">%s</xliff:g> रोजी एक्स्पायर होईल"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"शेअर केलेला डेटा हटवा"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"तुम्हाला नक्की हा शेअर केलेला डेटा हटवायचा आहे का?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"वापरकर्त्यांकडे त्यांचे स्वत:चे अॅप्स आणि सामग्री आहे"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"तुम्ही आपल्या खात्यावरुन अॅप्स आणि सामग्रीमध्ये प्रवेश करण्यास प्रतिबंध करु शकता"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"वापरकर्ता"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"प्रतिबंधित प्रोफाईल"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"नवीन वापरकर्ता जोडायचा?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"अतिरिक्त वापरकर्ते तयार करून तुम्ही इतर लोकांसोबत हे डिव्हाइस शेअर करू शकता. प्रत्येक वापरकर्त्यास त्यांची स्वतःची स्पेस असते, जी ते अॅप्स, वॉलपेपर आणि यासारख्या गोष्टींनी कस्टमाइझ करू शकतात. वापरकर्ते प्रत्येकाला प्रभावित करणाऱ्या वाय-फाय सारख्या डिव्हाइस सेटिंग्ज अॅडजस्ट देखील करू शकतात.\n\nतुम्ही एक नवीन वापरकर्ता जोडता, तेव्हा त्या व्यक्तीला त्याची स्पेस सेट अप करण्याची आवश्यकता असते.\n\nकोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अॅप अपडेट करू शकतो. अॅक्सेसिबिलिटी सेटिंग्ज आणि सेवा नवीन वापरकर्त्याला कदाचित ट्रान्सफर होणार नाहीत."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"तुम्ही एक नवीन वापरकर्ता जोडता तेव्हा, त्या व्यक्तीस त्यांचे स्थान सेट करण्याची आवश्यकता असते.\n\nकोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अॅप्स अपडेट करू शकतो."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"आता वापरकर्ता सेट करायचा?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"डिव्हाइस घेण्यासाठी आणि त्यांचे स्थान सेट करण्यासाठी व्यक्ती उपलब्ध असल्याची खात्री करा"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"आता प्रोफाईल सेट करायचा?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"आता सेट करा"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"आत्ता नाही"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"जोडा"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"नवीन वापरकर्ता"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"नवीन प्रोफाईल"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"वापरकर्ता माहिती"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"प्रोफाइल माहिती"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"तुम्ही एक प्रतिबंधित प्रोफाईल तयार करु शकण्यापूर्वी तुम्हाला तुमचे अॅप्स आणि वैयक्तिक डेटा संरक्षित करण्यासाठी एक स्क्रीन लॉक सेट करण्याची आवश्यकता राहील."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"लॉक सेट करा"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index b8e608f..58cbc48 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Alamat IP & Port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Imbas kod QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Gandingkan peranti melalui Wi-Fi dengan mengimbas Kod QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Sila sambungkan kepada rangkaian Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Pintasan laporan pepijat"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Tunjukkan butang dalam menu kuasa untuk mengambil laporan pepijat"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (merah-hijau)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (biru-kuning)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Pembetulan warna"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Pembetulan warna membolehkan anda melaraskan cara warna dipaparkan pada peranti anda"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Seharusnya boleh digunakan hingga kira-kira <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Seharusnya boleh digunakan hingga kira-kira <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Hingga <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Bateri mungkin kehabisan selewat-lewatnya <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Tinggal kurang daripada <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Kurang daripada <xliff:g id="THRESHOLD">%1$s</xliff:g> lagi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Lebih daripada <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Pembesar suara telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Masalah penyambungan. Matikan & hidupkan kembali peranti"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Peranti audio berwayar"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Bantuan & maklum balas"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Storan"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Data dikongsi"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Lihat dan ubah suai data dikongsi"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID data dikongsi: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Tamat tempoh pada <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Data perkongsian apl"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Tiada perihalan yang diberikan oleh apl."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Pajak tamat tempoh pada <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Padamkan data dikongsi"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Adakah anda pasti mahu memadamkan data dikongsi ini?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Pengguna mempunyai apl dan kandungan mereka sendiri"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Anda boleh menyekat akses kepada apl dan kandungan dari akaun anda"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Pengguna"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil terhad"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Tambah pengguna baharu?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Anda boleh berkongsi peranti ini dengan orang lain dengan membuat pengguna tambahan. Setiap pengguna mempunyai ruang mereka sendiri, yang boleh diperibadikan dengan apl, kertas dinding dan sebagainya. Pengguna juga boleh melaraskan tetapan peranti seperti Wi-Fi yang akan memberi kesan kepada semua orang.\n\nApabila anda menambah pengguna baharu, orang itu perlu menyediakan ruang mereka.\n\nMana-mana pengguna boleh mengemas kini apl untuk semua pengguna lain. Tetapan dan perkhidmatan kebolehaksesan tidak boleh dipindahkan kepada pengguna baharu."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Apabila anda menambah pengguna baharu, orang itu perlu menyediakan ruang mereka.\n\nMana-mana pengguna boleh mengemas kini apl untuk semua pengguna lain."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Sediakan pengguna sekarang?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Pastikan orang itu tersedia untuk mengambil peranti dan menyediakan ruangan"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Sediakan profil sekarang?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Sediakan sekarang"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Bukan sekarang"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Tambah"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Pengguna baharu"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Profil baharu"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Maklumat pengguna"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Maklumat profil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Sebelum anda boleh membuat profil yang terhad, anda perlu menyediakan kunci skrin untuk melindungi apl dan data peribadi anda."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Tetapkan kunci"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 75c4aa1..bc97a9f 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"အိုင်ပီ (IP) လိပ်စာနှင့် ပို့တ်"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR ကုဒ်ကို စကင်ဖတ်ပါ"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR ကုဒ် စကင်ဖတ်ခြင်းဖြင့် Wi-Fi ပေါ်တွင် စက်ပစ္စည်းကို အတူတွဲပါ"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi ကွန်ရက်သို့ ချိတ်ဆက်ပါ"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"ချွတ်ယွင်းမှု အစီရင်ခံရန် ဖြတ်လမ်း"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"ချွတ်ယွင်းမှု အစီရင်ခံစာကို တင်ရန် ပါဝါမီနူးမှ ခလုတ်ကို ပြပါ"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (အနီ-အစိမ်း)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (အပြာ-အဝါ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"အရောင်ပြင်ဆင်မှု"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"အရောင်အမှန်ပြင်ခြင်းက သင့်စက်ပေါ်တွင် အရောင်များပြနေပုံကို ချိန်ညှိခွင့်ပြုသည်"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ခန့် ကျန်သည်"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"<xliff:g id="TIME">%1$s</xliff:g> ခန့်အထိ သုံးနိုင်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"<xliff:g id="TIME">%1$s</xliff:g> ခန့်အထိ သုံးနိုင်သည်"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> အထိ"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g> တွင် ဘက်ထရီကုန်သွားနိုင်သည်"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ခန့်သာ ကျန်တော့သည်"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> အောက်သာ ကျန်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ကျော် ကျန်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"ဖုန်းစပီကာ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ချိတ်ဆက်ရာတွင် ပြဿနာရှိပါသည်။ စက်ကိုပိတ်ပြီး ပြန်ဖွင့်ပါ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ကြိုးတပ် အသံစက်ပစ္စည်း"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"အကူအညီနှင့် အကြံပြုချက်"</string>
+ <string name="storage_category" msgid="2287342585424631813">"သိုလှောင်ခန်း"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"မျှဝေထားသော ဒေတာ"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"မျှဝေထားသောဒေတာကို ကြည့်ပြီး မွမ်းမံရန်"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"မျှဝေထားသော ဒေတာ ID- <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"<xliff:g id="DATE">%s</xliff:g> တွင် သက်တမ်းကုန်ပါမည်"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"အက်ပ်များ မျှဝေသောဒေတာ"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"အက်ပ်ကပေးထားသော အကြောင်းအရာ မရှိပါ။"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"ငှားရမ်းမှု <xliff:g id="DATE">%s</xliff:g> သက်တမ်းကုန်မည်"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"မျှဝေထားသော ဒေတာကို ဖျက်ရန်"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"ဤမျှဝေထားသောဒေတာကို ဖျက်လိုသည်မှာ သေချာသလား။"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"သုံးစွဲသူများတွင် ၎င်းတို့ ကိုယ်ပိုင်အပလီကေးရှင်းများနှင့် မာတိကာရှိသည်။"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"သင့်အကောင့်မှ အပလီကေးရှင်းများ နှင့် ပါရှိချက်များ ရယူသုံးစွဲခွင့်ကို သင်ကန့်သတ်ထိန်းချုပ်နိုင်သည်။"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"အသုံးပြုသူ"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"ကန့်သတ်ထားသော ကိုယ်ရေးအချက်အလက်များ"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"အသုံးပြုသူအသစ် ထည့်မလား။"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"နောက်ထပ် အသုံးပြုသူများ ထည့်သွင်းခြင်းဖြင့် ဤစက်ပစ္စည်းကို အခြားသူများနှင့် မျှဝေအသုံးပြုနိုင်သည်။ အသုံးပြုသူတိုင်းသည် မိမိတို့ကိုယ်ပိုင်နေရာ ရရှိမည်ဖြစ်ပြီး အက်ပ်၊ နောက်ခံပုံနှင့် အခြားအရာတို့ဖြင့် စိတ်ကြိုက်ပြင်ဆင်နိုင်ပါမည်။ အားလုံးကို အကျိုးသက်ရောက်မှု ရှိစေနိုင်သည့် Wi-Fi ကဲ့သို့ ဆက်တင်များကိုလည်း ချိန်ညှိနိုင်ပါမည်။\n\nအသုံးပြုသူအသစ် ထည့်သည့်အခါ ထိုသူသည် မိမိ၏ကိုယ်ပိုင်နေရာကို သတ်မှတ်ရပါမည်။\n\nအသုံးပြုသူ မည်သူမဆို အခြားအသုံးပြုသူများအတွက် အက်ပ်များကို အပ်ဒိတ်လုပ်နိုင်သည်။ အများသုံးစွဲနိုင်မှုဆက်တင်များနှင့် ဝန်ဆောင်မှုများကို အသုံးပြုသူအသစ်ထံသို့ လွှဲပြောင်းပေးမည် မဟုတ်ပါ။"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"သင်က အသုံးပြုသူ အသစ် တစ်ဦးကို ထည့်ပေးလိုက်လျှင်၊ ထိုသူသည် ၎င်း၏ နေရာကို သတ်မှတ်စီစဉ်ရန် လိုအပ်မည်။\n\n အသုံးပြုသူ မည်သူမဆို ကျန်အသုံးပြုသူ အားလုံးတို့အတွက် အက်ပ်များကို အပ်ဒိတ်လုပ်ပေးနိုင်သည်။"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"အသုံးပြုသူကို ယခုသတ်မှတ်မလား။"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ထိုသူသည် ကိရိယာကိုယူ၍ ၎င်းတို့၏နေရာများကို ယခုသတ်မှတ်နိုင်ရမည်"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ယခု ကိုယ်ရေးအချက်အလက်ကို အစီအမံလုပ်မည်လား?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ယခု သတ်မှတ်ပါမည်"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ယခုမလုပ်ပါ"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"ထပ်ထည့်ရန်"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"အသုံးပြုသူအသစ်"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"ကိုယ်ရေးအချက်အလက်အသစ်"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"သုံးစွဲသူအကြောင်း"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"ကိုယ်ရေးအချက်အလက်"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"ကန့်သတ်ကိုယ်ရေးအချက်အလက်တစ်ခုကို မပြုလုပ်မီ သင်၏ အပလီကေးရှင်းများနှင့် ကိုယ်ပိုင်အချက်အလက်များကို ကာကွယ်ရန် မျက်နှာပြင်သော့ချခြင်းကို စီမံရန် လိုအပ်လိမ့်မည်"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"သော့ချရန် သတ်မှတ်ပါ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 82b3270..cd2a426 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-adresse og port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skann QR-koden"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Koble til enheten via Wi-Fi ved å skanne en QR-kode"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Koble til et Wi-Fi-nettverk"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, feilsøking, utvikler"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Snarvei til feilrapport"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Vis en knapp for generering av feilrapport i batterimenyen"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (rød-grønn)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (blå-gul)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Fargekorrigering"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Med fargekorrigering kan du justere hvordan farger vises på enheten din"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Skal vare til omtrent <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Skal vare til omtrent <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Til <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batteriet kan gå tomt <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Mindre enn <xliff:g id="THRESHOLD">%1$s</xliff:g> gjenstår"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Mindre enn <xliff:g id="THRESHOLD">%1$s</xliff:g> gjenstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mer enn <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonhøyttaler"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Tilkoblingsproblemer. Slå enheten av og på igjen"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhet med kabel"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Hjelp og tilbakemelding"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Lagring"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Delte data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Se og endre delte data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Delte data-ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Utløper <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apper deler data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Apper gir ingen beskrivelse."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Leieperioden utløper <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Slett delte data"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Er du sikker på at du vil slette disse delte dataene?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Brukere har sine egne apper og eget innhold"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Du kan begrense tilgangen til apper og innhold fra kontoen din"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Bruker"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Begrenset profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Vil du legge til en ny bruker?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Du kan dele denne enheten med andre folk ved å opprette flere brukere. Hver bruker har sin egen plass de kan tilpasse med apper, bakgrunner og annet. Brukere kan også justere enhetsinnstillinger, for eksempel Wi-Fi, som påvirker alle.\n\nNår du legger til en ny bruker, må vedkommende angi innstillinger for plassen sin.\n\nAlle brukere kan oppdatere apper for alle andre brukere. Innstillinger og tjenester for tilgjengelighet overføres kanskje ikke til den nye brukeren."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område.\n\nAlle brukere kan oppdatere apper for alle andre brukere."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Konfigurere brukeren nå?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Sørg for at brukeren er tilgjengelig for å konfigurere området sitt på enheten"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Vil du konfigurere profilen nå?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Konfigurer nå"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ikke nå"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Legg til"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Ny bruker"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Ny profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Brukerinformasjon"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profilinformasjon"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Før du kan opprette en begrenset profil, må du konfigurere skjermlåsen for å beskytte appene og de personlige dataene dine."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Angi lås"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index c694db9..d7a39cc 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -418,8 +418,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"प्रोटानेमली (रातो, हरियो)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ट्रिटानोमेली (निलो-पंहेलो)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रङ्ग सुधार"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"रङ सच्याउने सुविधाले तपाईंलाई आफ्नो यन्त्रमा रङहरू कस्ता देखिन्छन् भन्ने कुरा समायोजन गर्न दिन्छ"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ"</string>
@@ -520,10 +519,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -534,4 +541,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"प्रयोगकर्ताहरूसँग आफ्नै अनुप्रयोगहरू र सामग्री हुन्छ"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"तपाईं आफ्नो खाताबाट अनुप्रयोगहरू र सामग्रीहरूको पहुँचलाई प्रतिबन्ध गर्न सक्नुहुन्छ"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"प्रयोगकर्ता"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"प्रतिबन्धित प्रोफाइल"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"नयाँ प्रयोगकर्ता थप्ने हो?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"तपाईं थप प्रयोगकर्ताहरू सिर्जना गरेर यो यन्त्र अन्य मान्छेहरूसँग साझा रूपमा प्रयोग गर्न सक्नुहुन्छ। हरेक प्रयोगकर्ताको आफ्नै ठाउँ हुन्छ, जसलाई उनीहरू अनुप्रयोग, वालपेपर इत्यादिमार्फत आफू अनुकूल पार्न सक्छन्। प्रयोगकर्ताहरू सबैजनालाई असर पार्ने Wi-Fi जस्ता यन्त्रका सेटिङहरू पनि समायोजन गर्न सक्छन्।\n\nतपाईंले नयाँ प्रयोगकर्ता थप्दा उक्त व्यक्तिले आफ्नो ठाउँ सेटअप गर्नु पर्ने हुन्छ।\n\nकुनै पनि प्रयोगकर्ताले अन्य सबै प्रयोगकर्ताहरूका लागि अनुप्रयोगहरू अद्यावधिक गर्न सक्छन्। पहुँचसम्बन्धी सेटिङ तथा सेवाहरू नयाँ प्रयोगकर्तामा स्थानान्तरण नहुन सक्छन्।"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"जब तपाईंले नयाँ प्रयोगकर्ता थप्नुहुन्छ, त्यो व्यक्तिले आफ्नो ठाउँ सेट गर्न आवश्यक छ।\n\nकुनै पनि प्रयोगकर्ताले सबै अन्य प्रयोगकर्ताहरूका लागि अनुप्रयोगहरू अद्यावधिक गर्न सक्छन्।"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"अहिले प्रयोगकर्ता सेटअप गर्ने हो?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"यन्त्र लिन र आफ्नो ठाउँ बनाउन व्यक्ति उपलब्ध छ भन्ने कुराको निश्चित गर्नुहोस्"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"अहिले प्रोफाइल सेटअप गर्ने हो?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"अब सेटअप गर्नुहोस्"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"अहिले होइन"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"थप्नुहोस्"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"नयाँ प्रयोगकर्ता"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"नयाँ प्रोफाइल"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"प्रयोगकर्ता जानकारी"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"प्रोफाइल जानकारी"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"निषेधयुक्त प्रोफाइल बनाउनु अघि तपाईँको अनुप्रयोग र व्यक्तिगत डेटा सुरक्षा गर्नाका लागि तपाईँले स्क्रिन लक सेटअप गर्नु पर्दछ ।"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"लक सेट गर्नुहोस्"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 30e1c13..a8dda18 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-adres en poort"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR-code scannen"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Apparaat koppelen via wifi door een QR-code te scannen"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Maak verbinding met een wifi-netwerk"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, foutopsporing, ontwikkeling"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Snelle link naar bugrapport"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Een knop in het voedingsmenu weergeven om een bugrapport te maken"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rood-groen)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blauw-geel)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurcorrectie"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Met kleurcorrectie kun je aanpassen hoe kleuren op je apparaat worden weergegeven"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Nog ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Tot <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batterij is waarschijnlijk leeg om <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Nog minder dan <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Nog minder dan <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Nog meer dan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefoonspeaker"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem bij verbinding maken. Schakel het apparaat uit en weer in."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedraad audioapparaat"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Hulp en feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Opslag"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Gedeelde gegevens"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Gedeelde gegevens bekijken en aanpassen"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID gedeelde gegevens: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Vervalt op <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps die gegevens delen"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Geen beschrijving geleverd door de app."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Toegangsperiode vervalt op <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Gedeelde gegevens verwijderen"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Weet je zeker dat je deze gedeelde gegevens wilt verwijderen?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Gebruikers hebben hun eigen apps en content"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Je kunt toegang tot apps en content vanuit je account beperken"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Gebruiker"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Beperkt profiel"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Nieuwe gebruiker toevoegen?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Je kunt dit apparaat met anderen delen door extra gebruikers te maken. Elke gebruiker heeft een eigen profiel met zelf gekozen apps, achtergrond, enzovoort. Gebruikers kunnen ook apparaatinstellingen aanpassen die van invloed zijn op alle gebruikers, zoals wifi.\n\nWanneer je een nieuwe gebruiker toevoegt, moet die persoon een eigen profiel instellen.\n\nElke gebruiker kan apps updaten voor alle andere gebruikers. Toegankelijkheidsinstellingen en -services worden mogelijk niet overgezet naar de nieuwe gebruiker."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Wanneer je een nieuwe gebruiker toevoegt, moet die persoon zijn eigen profiel instellen.\n\nElke gebruiker kan apps updaten voor alle andere gebruikers."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Gebruiker nu instellen?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Zorg ervoor dat de persoon het apparaat kan overnemen om een profiel in te stellen"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Profiel nu instellen?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Nu instellen"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Niet nu"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Toevoegen"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nieuwe gebruiker"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Nieuw profiel"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Gebruikersgegevens"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profielinfo"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Voordat je een beperkt profiel kunt maken, moet je een schermvergrendeling instellen om je apps en persoonsgegevens te beschermen."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Vergrendeling instellen"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 9179125..9d93f44 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -418,8 +418,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ପ୍ରୋଟାନୋମାଲି (ଲାଲ୍-ସବୁଜ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ନୀଳ-ହଳଦିଆ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ରଙ୍ଗ ସଠିକତା"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ଆପଣଙ୍କ ଡିଭାଇସରେ ରଙ୍ଗଗୁଡ଼ିକ କିପରି ଡିସପ୍ଲେ ହୁଏ ତାହା ଆଡଜଷ୍ଟ କରିବାକୁ ’କଲର୍ କରେକ୍ସନ୍’ ଆପଣଙ୍କୁ ଅନୁମତି ଦିଏ"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ଦ୍ୱାରା ଓଭର୍ରାଇଡ୍ କରାଯାଇଛି"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"ପାଖାପାଖି <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ବଳକା ଅଛି"</string>
@@ -520,10 +519,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -534,4 +541,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"ଉପଯୋଗକର୍ତ୍ତାମାନଙ୍କ ପାଖରେ ନିଜର ଆପ୍ ଓ କଣ୍ଟେଣ୍ଟ ଅଛି"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ନିଜ ଆକାଉଣ୍ଟରୁ ଆପ୍ ତଥା କଣ୍ଟେଣ୍ଟକୁ ଆପଣ ଆକ୍ସେସ୍ ରୋକିପାରିବେ"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"ଉପଯୋଗକର୍ତ୍ତା"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"ସୀମିତ ସୁବିଧା ଥିବା ପ୍ରୋଫାଇଲ୍"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"ନୂତନ ୟୁଜର୍ ଯୋଡ଼ିବେ?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"ଅତିରିକ୍ତ ୟୁଜର୍ ତିଆରିକରି ଆପଣ ଏହି ଡିଭାଇସ୍କୁ ଅନ୍ୟ ଲୋକମାନଙ୍କ ସହିତ ସେୟାର୍ କରିପାରିବେ। ପ୍ରତ୍ୟେକ ୟୁଜର୍ଙ୍କର ନିଜର ସ୍ପେସ୍ ଅଛି ଯାହାକୁ ସେମାନେ ଆପ୍, ୱାଲପେପର୍ ଓ ଏପରି ଅନେକ ସହିତ କଷ୍ଟମାଇଜ୍ କରିପାରିବେ। ୟୁଜର୍ ୱାଇ-ଫାଇ ଭଳି ଡିଭାଇସ୍ ସେଟିଙ୍ଗକୁ ମଧ୍ୟ ଆଡଜଷ୍ଟ କରିପାରିବେ ଯାହା ସମସ୍ତଙ୍କୁ ପ୍ରଭାବିତ କରିଥାଏ। \n\nଯେତେବେଳେ ଆପଣ ଗୋଟିଏ ନୂଆ ୟୁଜର୍ଙ୍କୁ ଯୋଡ଼ିବେ ସେତେବେଳେ ସେହି ବ୍ୟକ୍ତି ଜଣଙ୍କୁ ନିଜର ସ୍ପେସ୍କୁ ସେଟଅପ୍ କରିବାକୁ ପଡ଼ିବ। \n\nଅନ୍ୟ ୟୁଜରଙ୍କ ପାଇଁ ଯେକୌଣସି ୟୁଜର୍ ଆପ୍କୁ ଅପଡେଟ୍ କରିପାରିବେ। ଆକ୍ସେସ୍ କରିବା ପାଇଁ ସେଟିଙ୍ଗ ଏବଂ ସେବା ନୂଆ ୟୁଜର୍ଙ୍କୁ ଟ୍ରନ୍ସଫର୍ ନହୋଇପାରେ।"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"ଜଣେ ନୂଆ ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଯୋଡ଼ିବାବେଳେ, ସେହି ବ୍ୟକ୍ତିଙ୍କୁ ସ୍ଥାନ ସେଟ୍ କରିବାକୁ ପଡ଼ିବ।\n\nଅନ୍ୟ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଯେକୌଣସି ଉପଯୋଗକର୍ତ୍ତା ଆପ୍ଗୁଡ଼ିକୁ ଅପ୍ଡେଟ୍ କରିପାରିବେ।"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ଏବେ ୟୁଜର୍ଙ୍କୁ ସେଟ୍ କରିବେ?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ସୁନିଶ୍ଚିତ କରନ୍ତୁ ଯେ, ବ୍ୟକ୍ତି ଜଣକ ଡିଭାଇସ୍ ଓ ନିଜର ସ୍ଥାନ ସେଟ୍ କରିବା ପାଇଁ ଉପଲବ୍ଧ ଅଛନ୍ତି।"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ପ୍ରୋଫାଇଲ୍କୁ ଏବେ ସେଟ୍ କରିବେ?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ଏବେ ସେଟ୍ କରନ୍ତୁ"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ଏବେ ନୁହେଁଁ"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"ଯୋଡନ୍ତୁ"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"ନୂଆ ୟୁଜର୍"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"ନୂଆ ପ୍ରୋଫାଇଲ୍"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"ଉପଯୋଗକର୍ତ୍ତା ସୂଚନା"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"ପ୍ରୋଫାଇଲ୍ ସୂଚନା"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"ପ୍ରତିବନ୍ଧିତ ପ୍ରୋଫାଇଲ୍ ତିଆରି କରିବାବେଳେ, ନିଜ ଆପ୍ ଓ ବ୍ୟକ୍ତିଗତ ତଥ୍ୟର ସୁରକ୍ଷା ପାଇଁ ଏକ ସ୍କ୍ରୀନ୍ ଲକ୍ ସେଟ୍ କରନ୍ତୁ।"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"ଲକ୍ ସେଟ୍ କରନ୍ତୁ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 34a836f..6ed8d1b 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -418,8 +418,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ਲਾਲ-ਹਰਾ)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ਨੀਲਾ-ਪੀਲਾ)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ਰੰਗ ਸੁਧਾਈ"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"ਰੰਗ ਸੁਧਾਈ ਨਾਲ ਤੁਹਾਨੂੰ ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਰੰਗਾਂ ਦੇ ਪ੍ਰਦਰਸ਼ਿਤ ਹੋਣ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰਨ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ"</string>
@@ -520,10 +519,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -534,4 +541,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"ਉਪਭੋਗਤਾਵਾਂ ਕੋਲ ਉਹਨਾਂ ਦੀਆਂ ਆਪਣੀਆਂ ਐਪਾਂ ਅਤੇ ਸਮੱਗਰੀ ਹੁੰਦੀਆਂ ਹਨ"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ਤੁਸੀਂ ਆਪਣੇ ਖਾਤੇ ਤੋਂ ਐਪਾਂ ਅਤੇ ਸਮੱਗਰੀ ਲਈ ਪਹੁੰਚ ਪ੍ਰਤਿਬੰਧ ਕਰ ਸਕਦੇ ਹੋ"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"ਵਰਤੋਂਕਾਰ"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"ਪ੍ਰਤਿਬੰਧਿਤ ਪ੍ਰੋਫਾਈਲ"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"ਕੀ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਨਾ ਹੈ?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"ਤੁਸੀਂ ਵਾਧੂ ਵਰਤੋਂਕਾਰ ਬਣਾ ਕੇ ਹੋਰਾਂ ਲੋਕਾਂ ਨਾਲ ਇਹ ਡੀਵਾਈਸ ਸਾਂਝਾ ਕਰ ਸਕਦੇ ਹੋ। ਹਰੇਕ ਵਰਤੋਂਕਾਰ ਦੀ ਆਪਣੀ ਖੁਦ ਦੀ ਜਗ੍ਹਾ ਹੁੰਦੀ ਹੈ, ਜਿਸਨੂੰ ਉਹ ਐਪਾਂ ਅਤੇ ਵਾਲਪੇਪਰ ਆਦਿ ਨਾਲ ਵਿਉਂਤਬੱਧ ਕਰ ਸਕਦੇ ਹਨ। ਵਰਤੋਂਕਾਰ ਡੀਵਾਈਸ ਸੈਟਿੰਗਾਂ ਵੀ ਵਿਵਸਥਿਤ ਕਰ ਸਕਦੇ ਹਨ ਜਿਵੇਂ ਵਾਈ‑ਫਾਈ ਜੋ ਹਰੇਕ \'ਤੇ ਅਸਰ ਪਾਉਂਦੀ ਹੈ।\n\nਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਉਸ ਵਿਅਕਤੀ ਨੂੰ ਆਪਣੀ ਜਗ੍ਹਾ ਸੈੱਟ ਅੱਪ ਕਰਨੀ ਪੈਂਦੀ ਹੈ।\n\nਕੋਈ ਵੀ ਵਰਤੋਂਕਾਰ ਬਾਕੀ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ। ਸ਼ਾਇਦ ਪਹੁੰਚਯੋਗਤਾ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਨੂੰ ਕਿਸੇ ਨਵੇਂ ਵਰਤੋਂਕਾਰ ਨੂੰ ਟ੍ਰਾਂਸਫਰ ਨਾ ਕੀਤਾ ਜਾ ਸਕੇ।"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਉਸ ਵਿਅਕਤੀ ਨੂੰ ਆਪਣੀ ਜਗ੍ਹਾ ਸੈੱਟਅੱਪ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।\n\nਕੋਈ ਵੀ ਵਰਤੋਂਕਾਰ ਹੋਰ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ਕੀ ਹੁਣ ਵਰਤੋਂਕਾਰ ਸੈੱਟ ਅੱਪ ਕਰਨਾ ਹੈ?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਵਿਅਕਤੀ ਡੀਵਾਈਸ ਵਰਤਣ ਅਤੇ ਆਪਣੀ ਜਗ੍ਹਾ ਦੇ ਸੈੱਟ ਅੱਪ ਲਈ ਉਪਲਬਧ ਹੈ"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ਕੀ ਹੁਣ ਪ੍ਰੋਫਾਈਲ ਸੈੱਟ ਅੱਪ ਕਰਨੀ ਹੈ?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ਹੁਣੇ ਸੈੱਟ ਅੱਪ ਕਰੋ"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ਅਜੇ ਨਹੀਂ"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"ਸ਼ਾਮਲ ਕਰੋ"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"ਨਵੀਂ ਪ੍ਰੋਫਾਈਲ"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"ਉਪਭੋਗਤਾ ਜਾਣਕਾਰੀ"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"ਪ੍ਰੋਫਾਈਲ ਜਾਣਕਾਰੀ"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰਤਿਬੰਧਿਤ ਪ੍ਰੋਫਾਈਲ ਬਣਾ ਸਕੋ, ਤੁਹਾਨੂੰ ਆਪਣੀਆਂ ਐਪਾਂ ਅਤੇ ਨਿੱਜੀ ਡਾਟਾ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਇੱਕ ਸਕ੍ਰੀਨ ਲਾਕ ਸੈੱਟ ਅੱਪ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">" ਲਾਕ ਸੈੱਟ ਕਰੋ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 193b307..cfd0d70 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adres IP i port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Zeskanuj kod QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Sparuj urządzenia przez Wi-Fi, skanując kod QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Połącz się z siecią Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Skrót do zgłoszenia błędu"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Pokaż w menu zasilania przycisk zgłaszania błędu"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (czerwony-zielony)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (niebieski-żółty)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcja kolorów"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korekcja kolorów pozwala na dostosowanie sposobu wyświetlania kolorów na urządzeniu"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Powinno wystarczyć do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Powinno wystarczyć do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Bateria może się wyczerpać do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Pozostało mniej niż <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Pozostało mniej niż <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Pozostało ponad: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -514,26 +511,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Głośnik telefonu"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem z połączeniem. Wyłącz i ponownie włącz urządzenie"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Przewodowe urządzenie audio"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Pomoc i opinie"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Pamięć"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Udostępniane dane"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Wyświetl i zmień udostępniane dane"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Identyfikator udostępnianych danych: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Wygasają: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplikacje, które udostępniają dane"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Aplikacja nie zapewnia opisu."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Dzierżawa wygasa: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Usuń udostępniane dane"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Czy na pewno chcesz usunąć te udostępniane dane?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Użytkownicy mają własne aplikacje i treści"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Możesz ograniczyć dostęp do aplikacji i zawartości z poziomu swojego konta"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Użytkownik"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil ograniczony"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Dodać nowego użytkownika?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Z tego urządzenia możesz korzystać wraz z innymi osobami, dodając na nim konta użytkowników. Każdy użytkownik ma własne miejsce na swoje aplikacje, tapety i inne dane. Może też zmieniać ustawienia, które wpływają na wszystkich użytkowników urządzenia (np. Wi‑Fi).\n\nGdy dodasz nowego użytkownika, musi on skonfigurować swoje miejsce na dane.\n\nKażdy użytkownik może aktualizować aplikacje w imieniu wszystkich pozostałych użytkowników. Ułatwienia dostępu i usługi mogą nie zostać przeniesione na konto nowego użytkownika."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Gdy dodasz nowego użytkownika, musi on skonfigurować swoją przestrzeń.\n\nKażdy użytkownik może aktualizować aplikacje wszystkich innych użytkowników."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Skonfigurować ustawienia dla użytkownika?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Upewnij się, że ta osoba jest w pobliżu i może skonfigurować swój profil."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Skonfigurować teraz profil?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Skonfiguruj"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Nie teraz"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Dodaj"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nowy użytkownik"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Nowy profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Użytkownik – informacje"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informacje o profilu"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Zanim utworzysz profil z ograniczeniami, musisz skonfigurować ekran blokady, by chronić aplikacje i osobiste dane."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Ustaw blokadę"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index a083a03..59f6bab 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Endereço IP e porta"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Ler código QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do código QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conecte-se a uma rede Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de bugs"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção de cor"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"A correção de cor permite ajustar como as cores são exibidas no dispositivo"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Até <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"A bateria pode acabar neste horário: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s)"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Alto-falante do smartphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Armazenamento"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Dados compartilhados"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Ver e modificar dados compartilhados"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Código dos dados compartilhados: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Expira em <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps que compartilham dados"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Nenhuma descrição fornecida pelo app."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"O lease expira em <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Excluir dados compartilhados"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Você quer mesmo excluir esses dados compartilhados?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Usuários padrão têm seus próprios apps e conteúdo"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"É possível restringir o acesso a apps e conteúdo a partir de sua conta"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Usuário"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restrito"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Adicionar novo usuário?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Você pode compartilhar este dispositivo com outras pessoas, adicionando usuários. Cada usuário tem o próprio espaço, que pode ser personalizado com apps, planos de fundo, etc. Os usuários também podem ajustar as configurações do dispositivo, como o Wi‑Fi, que afetam a todos.\n\nQuando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para todos os outros. Serviços e configurações de acessibilidade podem não ser transferidos para novos usuários."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Quando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para os demais usuários."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurar o usuário agora?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Certifique-se de que a pessoa está disponível para acessar o dispositivo e fazer as próprias configurações"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Configurar perfil agora?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configurar agora"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Agora não"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Adicionar"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Novo usuário"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Novo perfil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Dados do usuário"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informações do perfil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Antes de criar um perfil restrito, configure um bloqueio de tela para proteger seus apps e seus dados pessoais."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 7dd4dfb..b946f7a 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Porta e endereço IP"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Leia o código QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Sincronize o dispositivo através de Wi-Fi ao ler um código QR."</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Estabeleça ligação a uma rede Wi-Fi."</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, depurar, programador"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de erro"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar um botão no menu ligar/desligar para criar um relatório de erro"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção da cor"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"A correção da cor permite-lhe ajustar a forma como as cores são apresentadas no seu dispositivo."</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Deve durar até cerca da(s) <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Deve durar até cerca da(s) <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Até à(s) <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Poderá ficar sem bateria à(s) <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Resta(m) menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>."</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Resta(m) menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Resta(m) mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altifalante do telemóvel"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema ao ligar. Desligue e volte a ligar o dispositivo."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fios"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Ajuda e comentários"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Armazenamento"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Dados partilhados"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Ver e modificar dados partilhados"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID de dados partilhados: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Expira a <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps a partilhar dados"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Nenhuma descrição fornecida pela app."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"A alocação expira a <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Eliminar dados partilhados"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Tem a certeza de que pretende eliminar estes dados partilhados?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Os utilizadores têm as suas próprias aplicações e conteúdos"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Pode restringir o acesso às aplicações e conteúdos da sua conta"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Utilizador"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restrito"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Adicionar novo utilizador?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Pode partilhar este dispositivo com outras pessoas ao criar utilizadores adicionais. Cada utilizador possui o seu próprio espaço, que pode ser personalizado com aplicações, imagens de fundo, etc. Os utilizadores também podem ajustar as definições do dispositivo, como o Wi‑Fi, que afetam os restantes utilizadores.\n\nAo adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar aplicações para todos os outros utilizadores. Os serviços e as definições de acessibilidade podem não ser transferidos para o novo utilizador."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar aplicações para todos os outros utilizadores."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurar o utilizador agora?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Certifique-se de que a pessoa está disponível para levar o dispositivo e configurar o seu espaço"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Configurar perfil agora?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configurar agora"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Agora não"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Adicionar"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Novo utilizador"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Novo perfil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Info. utilizador"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informação do perfil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Antes de poder criar um perfil restrito, tem de configurar um bloqueio de ecrã para proteger as suas aplicações e dados pessoais."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index a083a03..59f6bab 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Endereço IP e porta"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Ler código QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do código QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conecte-se a uma rede Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de bugs"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção de cor"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"A correção de cor permite ajustar como as cores são exibidas no dispositivo"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Até <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"A bateria pode acabar neste horário: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s)"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Alto-falante do smartphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Armazenamento"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Dados compartilhados"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Ver e modificar dados compartilhados"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Código dos dados compartilhados: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Expira em <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Apps que compartilham dados"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Nenhuma descrição fornecida pelo app."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"O lease expira em <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Excluir dados compartilhados"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Você quer mesmo excluir esses dados compartilhados?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Usuários padrão têm seus próprios apps e conteúdo"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"É possível restringir o acesso a apps e conteúdo a partir de sua conta"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Usuário"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Perfil restrito"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Adicionar novo usuário?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Você pode compartilhar este dispositivo com outras pessoas, adicionando usuários. Cada usuário tem o próprio espaço, que pode ser personalizado com apps, planos de fundo, etc. Os usuários também podem ajustar as configurações do dispositivo, como o Wi‑Fi, que afetam a todos.\n\nQuando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para todos os outros. Serviços e configurações de acessibilidade podem não ser transferidos para novos usuários."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Quando você adiciona um novo usuário, essa pessoa precisa configurar o próprio espaço.\n\nQualquer usuário pode atualizar apps para os demais usuários."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurar o usuário agora?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Certifique-se de que a pessoa está disponível para acessar o dispositivo e fazer as próprias configurações"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Configurar perfil agora?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configurar agora"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Agora não"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Adicionar"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Novo usuário"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Novo perfil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Dados do usuário"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informações do perfil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Antes de criar um perfil restrito, configure um bloqueio de tela para proteger seus apps e seus dados pessoais."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 1d68fb7..55881b9 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresa IP și portul"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scanați codul QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Asociați dispozitivul prin Wi-Fi scanând un cod QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conectați-vă la o rețea Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, remedierea erorilor, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Comandă rapidă pentru raportul de erori"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afișați un buton în meniul de pornire pentru a realiza un raport de erori"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (roșu-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (albastru-galben)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corecția culorii"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Folosind corecția culorii, puteți ajusta modul în care se afișează culorile pe dispozitiv"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Timp aproximativ rămas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Ar trebui să reziste până la <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Ar trebui să reziste până la <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Până la <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Bateria se poate descărca până la <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"a mai rămas mai puțin de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"A mai rămas mai puțin de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"A mai rămas mai mult de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -513,26 +510,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Difuzorul telefonului"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problemă la conectare. Opriți și reporniți dispozitivul."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispozitiv audio cu fir"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Ajutor și feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Stocare"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Date la care se permite accesul"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Vedeți și modificați datele la care se permite accesul"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID-ul datelor la care se permite accesul: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Expiră pe <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplicații care permit accesul la date"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Aplicația nu oferă nicio descriere."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Închirierea expiră pe <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Ștergeți datele la care se permite accesul"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Sigur ștergeți aceste date la care se permite accesul?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Utilizatorii dețin aplicații și materiale proprii"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Puteți restricționa accesul la aplicații și la conținut din contul dvs."</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Utilizator"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil limitat"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Adăugați un utilizator nou?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Puteți să permiteți accesul la acest dispozitiv altor persoane creând utilizatori suplimentari. Fiecare utilizator are propriul spațiu, pe care îl poate personaliza cu aplicații, imagini de fundal etc. De asemenea, utilizatorii pot ajusta setările dispozitivului, cum ar fi setările pentru Wi-Fi, care îi afectează pe toți ceilalți utilizatori.\n\nDupă ce adăugați un utilizator nou, acesta trebuie să-și configureze spațiul.\n\nOricare dintre utilizatori poate actualiza aplicațiile pentru toți ceilalți utilizatori. Este posibil ca setările de accesibilitate și serviciile să nu se transfere la noul utilizator."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Când adăugați un utilizator nou, acesta trebuie să-și configureze spațiul.\n\nOrice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Configurați utilizatorul acum?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Asigurați-vă că utilizatorul are posibilitatea de a prelua dispozitivul și de a-și configura spațiul"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Configurați profilul acum?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Configurați acum"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Nu acum"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Adăugați"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Utilizator nou"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Profil nou"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Info. utilizator"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informații de profil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Înainte de a putea crea un profil cu permisiuni limitate, va trebui să configurați blocarea ecranului pentru a vă proteja aplicațiile și datele personale."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Configurați blocarea"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 6857dd7..88e94a5 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-адрес и порт"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Сканировать QR-код"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Подключение устройства через Wi‑Fi с использованием QR-кода"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Подключите устройство к сети Wi-Fi."</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, отладка, разработчик"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Отчет об ошибке"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Показывать в меню кнопки питания пункт для отправки отчета об ошибке"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (красный/зеленый)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (синий/желтый)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Коррекция цвета"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Коррекция цвета позволяет изменить настройки цветопередачи на экране устройства."</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"Уровень заряда – <xliff:g id="PERCENTAGE">%1$s</xliff:g>. <xliff:g id="TIME_STRING">%2$s</xliff:g>."</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Заряда хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Заряда (<xliff:g id="LEVEL">%2$s</xliff:g>) хватит примерно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Заряда хватит примерно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"До <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Батарея может разрядиться к <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Осталось менее <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Уровень заряда батареи: <xliff:g id="LEVEL">%2$s</xliff:g> (хватит менее чем на <xliff:g id="THRESHOLD">%1$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Уровень заряда батареи: <xliff:g id="LEVEL">%2$s</xliff:g> (хватит более чем на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>)"</string>
@@ -514,26 +511,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Встроенный динамик"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ошибка подключения. Выключите и снова включите устройство."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Проводное аудиоустройство"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Справка/отзыв"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Хранилище"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Общие данные"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Просмотр и изменение общих данных"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Идентификатор общих данных: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Срок действия истекает <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Приложения с общими данными"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Описание не предоставлено приложением."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Разрешение истекает <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Удалить общие данные"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Удалить общие данные?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"У пользователей есть свои приложения и контент"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Вы можете ограничить доступ к приложениям и контенту из вашего аккаунта"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Добавить пользователя"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Профиль с огр. доступом"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Добавить пользователя?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Если этим устройством пользуются сразу несколько человек, для каждого из них можно создать отдельный профиль – практически собственное пространство со своими приложениями, обоями и т. д. При этом из профиля можно поменять и настройки устройства, общие для всех, например выбрать сеть Wi-Fi.\n\nКогда вы добавляете нового пользователя, ему нужно настроить свой профиль.\n\nОбновлять общие приложения может любой пользователь, однако специальные возможности настраиваются индивидуально."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"После создания профиля его потребуется настроить.\n\nЛюбой пользователь устройства может обновлять приложения для всех аккаунтов."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Настроить профиль?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Вам потребуется передать устройство пользователю, чтобы он мог настроить свое личное пространство."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Настроить профиль?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Настроить"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Не сейчас"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Добавление"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Новый пользователь"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Новый профиль"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Сведения о пользователе"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Информация о профиле"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Чтобы создать профиль с ограниченным доступом, необходимо предварительно настроить блокировку экрана для защиты приложений и личных данных"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Включить блокировку"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 2c732ed..5aff308 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ලිපිනය & තොට"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR කේතය ස්කෑන් කරන්න"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR කේතය ස්කෑන් කිරීමෙන් Wi‑Fi හරහා උපාංගය යුගල කරන්න"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"කරුණාකර Wi-Fi ජාලයකට සම්බන්ධ වන්න"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, දෝෂාවෙක්ෂණ, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"දෝෂය වාර්තා කිරීමේ කෙටිමඟ"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"දෝෂ වාර්තාවක් ගැනීම සඳහා බල මෙනුව තුළ බොත්තම පෙන්වන"</string>
@@ -432,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) පමණ වන තෙක් තිබිය යුතුය"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"<xliff:g id="TIME">%1$s</xliff:g> පමණ වන තෙක් තිබිය යුතුය"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> දක්වා"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"බැටරි බලය <xliff:g id="TIME">%1$s</xliff:g> වන විට අවසන් විය හැකිය"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g>ට වඩා අඩුවෙන් ඉතිරිව ඇත"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>ට වඩා අඩුවෙන් ඉතිරිය (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>ට වඩා වැඩියෙන් ඉතිරිය (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -511,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"දුරකථන ස්පීකරය"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"සම්බන්ධ කිරීමේ ගැටලුවකි උපාංගය ක්රියාවිරහිත කර & ආපසු ක්රියාත්මක කරන්න"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"රැහැන්ගත කළ ඕඩියෝ උපාංගය"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"උදවු & ප්රතිපෝෂණ"</string>
+ <string name="storage_category" msgid="2287342585424631813">"ගබඩාව"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"බෙදා ගත් දත්ත"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"බෙදා ගත් දත්ත බලා වෙනස් කරන්න"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"බෙදා ගත් දත්ත ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"<xliff:g id="DATE">%s</xliff:g> දින කල් ඉකුත් වේ"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"යෙදුම් බෙදා ගැනීමේ දත්ත"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"යෙදුම මගින් විස්තර කිසිවක් ලබා දී නැත."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"කල් බද්ද <xliff:g id="DATE">%s</xliff:g> දින කල් ඉකුත් වේ"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"බෙදා ගත් දත්ත මකන්න"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"ඔබට මෙම බෙදා ගත් දත්ත මැකීමට අවශ්ය බව විශ්වාසද?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"පරිශීලකයින්ට ඔවුන්ගේ යෙදුම් සහ අන්තර්ගත ඇත"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ඔබගේ ගිණුමෙන් යෙදුම් සහ අන්තර්ගත වෙත පිවිසීම ඔබට සීමා කළ හැක"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"පරිශීලක"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"සීමිත පැතිකඩ"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"අලුත් පරිශීලකයෙක් එක් කරන්නද?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"අමතර පරිශීලකයින් නිර්මාණය කිරීම මඟින් වෙනත් පුද්ගලයන් සමඟ මෙම උපාංගය ඔබට බෙදා ගත හැකිය. සෑම පරිශීලකයෙක්ටම ඔවුන්ගේම යෙදුම්, වෝල්පේපර, සහ වෙනත් ඒවා අභිරුචි කළ හැකි තමන්ට අයිති ඉඩක් ඇත. පරිශීලකයින්ට Wi‑Fi වැනි සෑම දෙනාටම බලපාන උපාංග සැකසීම්ද සීරුමාරු කළ හැක.\n\nඔබ නව පරිශීලකයෙකු එක් කළ විට ඔවුන්ගේ ඉඩ එම පුද්ගලයා සකසා ගත යුතු වේ.\n\nඕනෑම පරිශීලකයෙකුට අනෙක් සියලු පරිශීලකයන් සඳහා යෙදුම් යාවත්කාලීන කළ හැකිය. ප්රවේශයතා සැකසීම් සහ සේවා නව පරිශීලකයා වෙත මාරු නොකරනු ඇත."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"ඔබ අලුත් පරිශීලකයෙක් එකතු කරන විට, එම පුද්ගලයා ඔහුගේ වැඩ කරන ඉඩ සකසා ගත යුතුය.\n\nසියළුම අනෙක් පරිශීලකයින් සඳහා ඕනෑම පරිශීලකයෙකුට යාවත්කාලීන කළ හැක."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"දැන් පරිශීලකයා සකසන්නද?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"උපාංගය ලබාගෙන තමන්ගේ ඉඩ සකසා ගැනීමට අදාළ පුද්ගලයා සිටින බව තහවුරු කරගන්න"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"දැන් පැතිකඩ සකසන්නද?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"දැන් සකසන්න"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"දැන් නොවේ"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"එක් කරන්න"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"නව පරිශීලකයා"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"නව පැතිකඩ"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"පරිශීලක තොරතුරු"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"පැතිකඩ තොරතුරු"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"සීමිත පැතිකඩක් නිර්මාණය කිරීමට කලින්. ඔබගේ යෙදුම් සහ පෞද්ගලික දත්ත ආරක්ෂා කිරීමට තිර අගුලක් සැකසිය යුතුයි."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"අගුල සකසන්න"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 1032fd8..05e8a3f 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresa IP a port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Naskenujte QR kód"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Spárujte zariadenie cez sieť Wi-Fi naskenovaním QR kódu"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Pripojte sa k sieti Wi‑Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ladenie, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Skratka hlásenia chyby"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Zobraziť v hlavnej ponuke tlačidlo na vytvorenie hlásenia chyby"</string>
@@ -432,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Vydrží asi do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Vydrží asi do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batéria sa môže do <xliff:g id="TIME">%1$s</xliff:g> minúť"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Zostáva menej ako <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Zostáva menej ako <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Zostáva viac ako <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -513,26 +511,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Reproduktor telefónu"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Pri pripájaní sa vyskytol problém. Zariadenie vypnite a znova zapnite."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio zariadenie s káblom"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Pomocník a spätná väzba"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Priestor"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Zdieľané údaje"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Zobrazenie a úprava zdieľaných údajov"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Identifikátor zdieľaných údajov: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Platnosť vyprší <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplikácie zdieľajúce údaje"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Aplikácia neposkytla žiadny popis."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Platnosť prenájmu vyprší <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Odstrániť zdieľané údaje"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Naozaj chcete odstrániť tieto zdieľané údaje?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Používatelia majú svoje vlastné aplikácie a obsah"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Môžete obmedziť prístup k aplikáciám a obsahu z vášho účtu"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Používateľ"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Obmedzený profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Pridať nového používateľa?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Vytvorením ďalších používateľov môžete toto zariadenie zdieľať s inými ľuďmi. Každý používateľ má svoje prostredie, ktoré si môže prispôsobiť vlastnými aplikáciami, tapetou atď. Používatelia tiež môžu upraviť nastavenia zariadenia (napr. Wi-Fi), ktoré ovplyvnia všetkých používateľov.\n\nKeď pridáte nového používateľa, musí si nastaviť vlastný priestor.\n\nAkýkoľvek používateľ môže aktualizovať aplikácie všetkých používateľov. Nastavenia dostupnosti a služby sa nemusia preniesť novému používateľovi."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Keď pridáte nového používateľa, musí si nastaviť vlastný priestor.\n\nAkýkoľvek používateľ môže aktualizovať aplikácie všetkých ostatných používateľov."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Chcete teraz nastaviť používateľa?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Uistite sa, že je daná osoba k dispozícii a môže si na zariadení nastaviť svoj priestor."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Nastaviť profil?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Nastaviť teraz"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Teraz nie"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Pridať"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nový používateľ"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Nový profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Inf. o používateľovi"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Informácie o profile"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Pred vytvorením obmedzeného profilu je nutné najprv nastaviť zámku obrazovky na ochranu aplikácií a osobných údajov."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Nastaviť uzamknutie"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index a25cdd0..1ddf5dd 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Naslov IP in vrata"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Optično branje kode QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Seznanitev naprave prek Wi‑Fi-ja z optičnim branjem kode QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Vzpostavite povezavo z omrežjem Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, odpravljanje napak, razvoj"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Bližnjica za poročanje o napakah"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikaz gumba za ustvarjanje poročila o napakah v meniju za vklop/izklop"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (rdeča – zelena)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (modra – rumena)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Popravljanje barv"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Popravljanje barv vam omogoča prilagajanje prikaza barv v napravi"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Naprava bi morala delovati do približno <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Moralo bi zadostovati do približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Energije baterije lahko zmanjka do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Preostalo manj kot <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Preostanek: manj kot <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Preostali čas delovanja: manj kot <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -514,26 +511,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvočnik telefona"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Težava pri povezovanju. Napravo izklopite in znova vklopite."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žična zvočna naprava"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Pomoč in povratne informacije"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Shramba"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Deljeni podatki"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Ogled in sprememba deljenih podatkov"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID deljenih podatkov: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Poteče dne <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplikacije, ki si delijo podatke"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Aplikacija ni posredovala opisa."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Zakup poteče dne <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Izbriši deljene podatke"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Ali ste prepričani, da želite odstraniti te deljene podatke?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Uporabniki imajo svoje aplikacije in vsebino"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Dostop do aplikacij in vsebine iz vašega računa lahko omejite"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Uporabnik"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Omejen profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Dodajanje novega uporabnika?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"To napravo lahko daste v skupno rabo z drugimi tako, da ustvarite dodatne uporabnike. Vsak ima svoj prostor, ki ga lahko prilagodi z aplikacijami, ozadji in drugim. Uporabniki lahko tudi prilagodijo nastavitve naprave, ki vplivajo na vse, na primer nastavitve omrežja Wi-Fi.\n\nKo dodate novega uporabnika, mora ta nastaviti svoj prostor.\n\nVsak uporabnik lahko posodobi aplikacije za vse druge uporabnike. Nastavitve in storitve funkcij za ljudi s posebnimi potrebami morda ne bodo prenesene v prostor novega uporabnika."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Ko dodate novega uporabnika, mora ta nastaviti svoj prostor.\n\nVsak uporabnik lahko posodobi aplikacije za vse druge uporabnike."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Želite uporabnika nastaviti zdaj?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Prepričajte se, da ima oseba čas za nastavitev svojega prostora."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Želite zdaj nastaviti profil?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Želim nastaviti zdaj"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ne zdaj"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Dodaj"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Nov uporabnik"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Nov profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Podatki o uporabniku"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Podatki za profil"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Preden lahko ustvarite profil z omejitvami, morate nastaviti zaklepanje zaslona, da zaščitite aplikacije in osebne podatke."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Nastavi zaklepanje"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 0ebfef8..c1469c4 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresa e IP-së dhe porta"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skano kodin QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Çifto pajisjen përmes Wi‑Fi duke skanuar një kod QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Lidhu me një rrjet Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, korrigjimi, zhvilluesi"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Shkurtorja e raportit të defektit në kod"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Shfaq një buton në menynë e fikjes për marrjen e raportit të defekteve"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (e kuqe - e gjelbër)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (e kaltër - e verdhë)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korrigjimi i ngjyrës"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Korrigjimi i ngjyrave të lejon të rregullosh mënyrën se si shfaqen ngjyrat në pajisjen tënde"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Deri në <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Bateria mund të mbarojë deri në <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> të mbetura"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Mbeten më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mbeten më shumë se <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altoparlanti i telefonit"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem me lidhjen. Fike dhe ndize përsëri pajisjen"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Pajisja audio me tel"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Ndihma dhe komentet"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Hapësira ruajtëse"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Të dhënat e ndara"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Shiko dhe modifiko të dhënat e ndara"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID-ja e të dhënave të ndara: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Skadon më <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Aplikacionet që ndajnë të dhënat"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Nuk jepet asnjë përshkrim nga aplikacioni."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Qiraja skadon në <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Fshi të dhënat e ndara"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Je i sigurt që dëshiron ta fshish këto të dhëna të ndara?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Përdoruesit kanë aplikacionet dhe përmbajtjet e tyre"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Mund të kufizosh qasjen në aplikacione dhe përmbajtje nga llogaria jote"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Përdoruesi"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Profil i kufizuar"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Të shtohet përdorues i ri?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Mund ta ndash këtë pajisje me persona të tjerë duke krijuar përdorues shtesë. Çdo përdorues ka hapësirën e vet, të cilën mund ta personalizojë me aplikacione, me imazhin e sfondit etj. Përdoruesit mund të rregullojnë po ashtu cilësimet e pajisjes, si Wi‑Fi, të cilat ndikojnë te të gjithë.\n\nKur shton një përdorues të ri, ai person duhet të konfigurojë hapësirën e vet.\n\nÇdo përdorues mund t\'i përditësojë aplikacionet për të gjithë përdoruesit e tjerë. Cilësimet e qasshmërisë dhe shërbimet mund të mos transferohen te përdoruesi i ri."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Kur shton një përdorues të ri, ai person duhet të konfigurojë hapësirën e vet.\n\nÇdo përdorues mund t\'i përditësojë aplikacionet për të gjithë përdoruesit e tjerë."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Të konfig. përdoruesi tani?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Sigurohu që personi të jetë i gatshëm të marrë pajisjen dhe të caktojë hapësirën e vet"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Të konfigurohet tani profili?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Konfiguro tani"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Jo tani"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Shto"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Përdorues i ri"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Profili i ri"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Informacioni i përdoruesit"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Inform. i profilit"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Para se të mund të krijosh një profil të kufizuar, duhet të konfigurosh një kyçje të ekranit për të mbrojtur aplikacionet dhe të dhënat e tua personale."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Cakto kyçjen"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 109a93a..285e2b6 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP адреса и порт"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Скенирај QR кôд"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Упарите уређај помоћу Wi‑Fi мреже или тако што ћете скенирати QR кôд"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Повежите се на Wi-Fi мрежу"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, отклањање грешака, програмер"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Пречица за извештај о грешкама"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Прикажи дугме у менију напајања за прављење извештаја о грешкама"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалија (црвено-зелено)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалија (плаво-жуто)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекција боја"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Корекција боја вам омогућава да прилагодите начин на који се боје приказују на уређају"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Преостало је око <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Трајаће приближно до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Трајаће приближно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"До <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Батерија ће се можда испразнити до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Преостало је мање од <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Преостало је мање од <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Преостало је више од <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -513,26 +510,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Звучник телефона"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем при повезивању. Искључите уређај, па га поново укључите"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичани аудио уређај"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Помоћ и повратне информације"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Меморијски простор"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Дељени подаци"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Прегледајте и измените дељене податке"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ИД дељених података: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Истиче: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Апликације које деле податке"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"У апликацији није наведен ниједан опис."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Изнајмљивање истиче: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Избриши дељене податке"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Желите ли стварно да избришете ове дељене податке?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Корисници имају сопствене апликације и садржај"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Можете да ограничите приступ на апликације и садржај са налога"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Корисник"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Ограничени профил"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Додајете новог корисника?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Овај уређај можете да делите са другим људима ако направите још корисника. Сваки корисник има сопствени простор, који може да прилагођава помоћу апликација, позадине и слично. Корисници могу да прилагођавају и подешавања уређаја која утичу на свакога, попут Wi‑Fi-ја.\n\nКада додате новог корисника, та особа треба да подеси сопствени простор.\n\nСваки корисник може да ажурира апликације за све остале кориснике. Подешавања и услуге приступачности не могу да се преносе на новог корисника."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Када додате новог корисника, та особа треба да подеси сопствени простор.\n\nСваки корисник може да ажурира апликације за све остале кориснике."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Подешавате корисника?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Та особа треба да узме уређај и подеси свој простор"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Желите ли да одмах подесите профил?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Подеси"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Не сада"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Додавање"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Нови корисник"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Нови профил"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Подаци о кориснику"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Подаци о профилу"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Да бисте могли да направите ограничени профил, треба да подесите закључавање екрана да бисте заштитили апликације и личне податке."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Подеси закључавање"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 5a74966..b9db69e 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-adress och port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skanna QR-kod"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Parkoppla enheten via Wi-Fi genom att skanna en QR-kod"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Anslut till ett Wi-Fi-nätverk"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev, felsöka, felsökning"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Genväg till felrapport"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Visa en knapp för felrapportering i extramenyn"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (rött-grönt)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (blått-gult)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Färgkorrigering"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Med färgkorrigering kan du ändra hur färger visas på enheten"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Bör räcka ungefär till klockan <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Bör räcka ungefär till klockan <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Till kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batteriet kan ta slut klockan <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Mindre än <xliff:g id="THRESHOLD">%1$s</xliff:g> återstår"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Mindre än <xliff:g id="THRESHOLD">%1$s</xliff:g> återstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mer än <xliff:g id="TIME_REMAINING">%1$s</xliff:g> återstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonens högtalare"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Det gick inte att ansluta. Stäng av enheten och slå på den igen"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ljudenhet med kabelanslutning"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Hjälp och feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Lagring"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Delad data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Visa och ändra delad data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Id för delad data: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Upphör den <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Appar som delar data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Ingen beskrivning har tillhandahållits av appen."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Lånetiden upphör den <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Radera delad data"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Vill du radera denna delade data?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Användare har egna appar och eget innehåll"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Du kan begränsa åtkomsten till appar och innehåll i ditt konto"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Användare"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Begränsad profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Lägga till ny användare?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Du kan dela enheten med andra om du skapar flera användare. Alla användare får sitt eget utrymme som de kan anpassa som de vill med appar, bakgrund och så vidare. Användarna kan även ändra enhetsinställningar som påverkar alla, till exempel Wi‑Fi.\n\nNär du lägger till en ny användare måste han eller hon konfigurera sitt utrymme.\n\nAlla användare kan uppdatera appar för samtliga användares räkning. Tillgänglighetsinställningar och tjänster kanske inte överförs till den nya användaren."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"När du lägger till en ny användare måste den personen konfigurera sitt utrymme.\n\nAlla användare kan uppdatera appar för samtliga användares räkning."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Konfigurera användare nu?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Kontrollera att personen finns tillgänglig för att konfigurera sitt utrymme på enheten"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Vill du konfigurera en profil nu?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Konfigurera nu"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Inte nu"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Lägg till"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Ny användare"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Ny profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Användarinfo"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profilinfo"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Innan du skapar en begränsad profil måste du konfigurera ett skärmlås för att skydda dina appar och personliga data."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Konfigurera lås"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 6d52cc7..33f2041 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Anwani ya IP na Mlango"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Changanua msimbo wa QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Oanisha kifaa kupitia Wi-Fi kwa kuchanganua Msimbo wa QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Tafadhali unganisha kwenye mtandao wa Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, tatua, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Njia ya mkato ya kuripoti hitilafu"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Onyesha kitufe cha kuripoti hitilafu katika menyu ya kuzima/kuwasha kifaa"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (nyekundu-kijani)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (samawati-manjano)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Usahihishaji wa rangi"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Urekebishaji rangi hukuruhusu ubadilishe jinsi rangi zinavyoonyeshwa kwenye kifaa chako"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Inapaswa kudumu kwa takribani <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Inapaswa kudumu hadi <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Hadi <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Huenda chaji ikaisha kufikia <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Zimesalia chini ya <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Zimesalia chini ya <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Zimesalia zaidi ya <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Spika ya simu"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kuna tatizo la kuunganisha kwenye Intaneti. Zima kisha uwashe kifaa"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kifaa cha sauti kinachotumia waya"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Usaidizi na maoni"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Hifadhi"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Data iliyoshirikiwa"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Angalia na ubadilishe data iliyoshirikiwa"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Kitambulisho cha data iliyoshirikiwa: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Muda wake utaisha<xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Programu zinazoshiriki data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Hakuna maelezo yaliyotolewa na programu."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Muda wa kukodisha utaisha <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Futa data iliyoshirikiwa"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Una uhakika unataka kufuta data hii iliyoshirikiwa?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Watumiaji wana programu na maudhui yao binafsi"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Unaweza kudhibiti ufikiaji kwa programu na maudhui kutoka kwenye akaunti yako"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Mtumiaji"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Wasifu uliozuiwa"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Ungependa kuongeza mtumiaji?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Unaweza kutumia kifaa hiki pamoja na watu wengine kwa kuongeza watumiaji wa ziada. Kila mtumiaji ana nafasi yake mwenyewe, ambayo anaweza kuweka programu, mandhari na vipengee vingine anavyopenda. Watumiaji pia wanaweza kurekebisha mipangilio ya kifaa inayoathiri kila mtu kama vile Wi-Fi.\n\nUnapomwongeza mtumiaji mpya, mtu huyo anahitaji kujitayarishia nafasi yake.\n\nMtumiaji yeyote anaweza kuwasasishia watumiaji wengine wote programu. Huenda mipangilio na huduma za walio na matatizo ya kuona na kusikia zisihamishiwe mtumiaji mgeni."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Mtumiaji mpya utakayemwongeza atahitaji kuongeza akaunti yake.\n\nMtumiaji yoyote anaweza kusasisha programu kwa niaba ya wengine wote."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Mtumiaji aongezwe sasa?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Hakikisha kuwa mtu huyu anaweza kuchukua kifaa na kuweka mapendeleo yake"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Ungependa kuweka wasifu sasa?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Mwongeze sasa"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Si sasa"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Ongeza"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Mtumiaji mpya"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Wasifu mpya"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Maelezo ya mtumiaji"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Maelezo ya wasifu"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Kabla uunde wasifu uliowekekwa vikwazo, utahitajika kuweka skrini iliyofungwa ili kulinda programu zako na data binafsi."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Weka ufunguo"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 63faee6..3826e61 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -520,10 +520,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -534,4 +542,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"பயனர்கள் தங்களுக்குச் சொந்தமான ஆப்ஸ் மற்றும் உள்ளடக்கத்தை வைத்திருக்க வேண்டும்"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"உங்கள் கணக்கிலிருந்து ஆப்ஸ் மற்றும் உள்ளடக்கத்திற்கான அணுகலை நீங்கள் வரையறுக்கலாம்"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"பயனர்"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"கட்டுப்படுத்தப்பட்ட சுயவிவரம்"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"புதியவரைச் சேர்க்கவா?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"கூடுதல் பயனர்களை உருவாக்குவதன் மூலம், பிறருடன் இந்தச் சாதனத்தைப் பகிர்ந்துகொள்ளலாம். ஒவ்வொரு பயனருக்கும் அவர்களுக்கென ஒரு இடம் இருக்கும், அதில் அவர்கள் ஆப்ஸ், வால்பேப்பர் மற்றும் பலவற்றைப் பயன்படுத்திப் பிரத்தியேகப்படுத்தலாம். வைஃபை போன்ற மற்ற சாதன அமைப்புகளைப் பயனர்கள் மாற்றலாம், இந்த மாற்றம் அனைவருக்கும் பொருந்தும்.\n\nநீங்கள் புதிய பயனரைச் சேர்க்கும்போது, அவர் தனக்கான இடத்தை அமைக்க வேண்டும்.\n\nஎந்தவொரு பயனரும், பிற எல்லாப் பயனர்களுக்குமான ஆப்ஸைப் புதுப்பிக்கலாம். அணுகல்தன்மை அமைப்புகளையும் சேவைகளையும், புதிய பயனருக்கு இடமாற்ற முடியாமல் போகலாம்."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"புதியவரைச் சேர்க்கும் போது, அவர் தனக்கான இடத்தை அமைக்க வேண்டும்.\n\nஇருக்கும் ஆப்ஸை எவரும் புதுப்பிக்கலாம்."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"இப்போது பயனரை அமைக்கவா?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"இந்தச் சாதனத்தை இவர் பயன்படுத்தும் நிலையிலும், அவருக்கான அமைப்புகளை அவரே செய்து கொள்பவராகவும் இருக்க வேண்டும்."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"இப்போது சுயவிவரத்தை அமைக்கவா?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"இப்போது அமை"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"இப்போது இல்லை"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"சேர்"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"புதியவர்"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"புதிய சுயவிவரம்"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"பயனர் தகவல்"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"சுயவிவரத் தகவல்"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"நீங்கள் வரையறுக்கப்பட்டச் சுயவிவரத்தை உருவாக்குவதற்கு முன்பு, உங்கள் ஆப்ஸ் மற்றும் தனிப்பட்ட தரவைப் பாதுகாக்கும் வகையில் நீங்கள் திரைப் பூட்டை அமைக்க வேண்டும்."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"பூட்டை அமை"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 9cfe541..fe18c83 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -520,10 +520,18 @@
<skip />
<!-- no translation found for shared_data_summary (5516326713822885652) -->
<skip />
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
+ <skip />
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
+ <skip />
<!-- no translation found for blob_id_text (8680078988996308061) -->
<skip />
<!-- no translation found for blob_expires_text (7882727111491739331) -->
<skip />
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
+ <skip />
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
+ <skip />
<!-- no translation found for accessor_info_title (8289823651512477787) -->
<skip />
<!-- no translation found for accessor_no_description_text (7510967452505591456) -->
@@ -534,4 +542,23 @@
<skip />
<!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
<skip />
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"వినియోగదారులు వారి స్వంత అనువర్తనాలను మరియు కంటెంట్ను కలిగి ఉన్నారు"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"మీరు మీ ఖాతా నుండి అనువర్తనాలకు మరియు కంటెంట్కు ప్రాప్యతను పరిమితం చేయవచ్చు"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"వినియోగదారు"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"పరిమితం చేయబడిన ప్రొఫైల్"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"కొత్త వినియోగదారుని జోడించాలా?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"అదనపు వినియోగదారులను సృష్టించడం ద్వారా మీరు ఈ పరికరాన్ని ఇతరులతో షేర్ చేయవచ్చు. ప్రతి వినియోగదారుకు వారికంటూ ప్రత్యేక స్థలం ఉంటుంది, వారు ఆ స్థలాన్ని యాప్లు, వాల్పేపర్ మొదలైనవాటితో అనుకూలీకరించవచ్చు. వినియోగదారులు ప్రతి ఒక్కరిపై ప్రభావం చూపే Wi‑Fi వంటి పరికర సెట్టింగ్లను కూడా సర్దుబాటు చేయవచ్చు.\n\nమీరు కొత్త వినియోగదారును జోడించినప్పుడు, ఆ వ్యక్తి వారికంటూ స్వంత స్థలం సెట్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగిలిన అందరు వినియోగదారుల కోసం యాప్లను అప్డేట్ చేయవచ్చు. యాక్సెస్ సామర్ధ్యం సెట్టింగ్లు మరియు సేవలు కొత్త వినియోగదారుకి బదిలీ కాకపోవచ్చు."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"మీరు కొత్త వినియోగదారుని జోడించినప్పుడు, ఆ వ్యక్తి తన స్థలాన్ని సెటప్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగతా అందరు వినియోగదారుల కోసం యాప్లను అప్డేట్ చేయగలరు."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ఇప్పుడు వినియోగదారుని సెటప్ చేయాలా?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"పరికరాన్ని తీసుకోవడానికి వ్యక్తి అందుబాటులో ఉన్నారని నిర్ధారించుకొని, ఆపై వారికి నిల్వ స్థలాన్ని సెటప్ చేయండి"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ఇప్పుడు ప్రొఫైల్ను సెటప్ చేయాలా?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ఇప్పుడే సెటప్ చేయి"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ఇప్పుడు కాదు"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"జోడించండి"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"కొత్త వినియోగదారు"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"కొత్త ప్రొఫైల్"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"వినియోగదారు సమాచారం"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"ప్రొఫైల్ సమాచారం"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"మీరు పరిమితం చేయబడిన ప్రొఫైల్ను సృష్టించడానికి ముందు, మీ అనువర్తనాలు మరియు వ్యక్తిగత డేటాను రక్షించడానికి స్క్రీన్ లాక్ను సెటప్ చేయాల్సి ఉంటుంది."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"లాక్ను సెట్ చేయి"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 05633ca..31c6051 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"ที่อยู่ IP และพอร์ต"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"สแกนคิวอาร์โค้ด"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"จับคู่อุปกรณ์ผ่าน Wi‑Fi ด้วยการสแกนคิวอาร์โค้ด"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"โปรดเชื่อมต่อเครือข่าย Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, แก้ไขข้อบกพร่อง, พัฒนา"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"ทางลัดรายงานข้อบกพร่อง"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"แสดงปุ่มในเมนูเปิด/ปิดสำหรับการใช้รายงานข้อบกพร่อง"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ตาบอดจางสีแดง (สีแดง/เขียว)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ตาบอดจางสีน้ำเงิน (สีน้ำเงิน/เหลือง)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"การแก้สี"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"การแก้สีช่วยให้คุณปรับการแสดงสีในอุปกรณ์ได้"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"เหลืออีกประมาณ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"จนถึง <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"แบตเตอรี่อาจหมดภายใน <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"เหลืออีกไม่ถึง <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"เหลือเวลาอีกไม่ถึง <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"เหลือเวลามากกว่า <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"ลำโพงโทรศัพท์"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"เกิดปัญหาในการเชื่อมต่อ ปิดอุปกรณ์แล้วเปิดใหม่อีกครั้ง"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"อุปกรณ์เสียงแบบมีสาย"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"ความช่วยเหลือและความคิดเห็น"</string>
+ <string name="storage_category" msgid="2287342585424631813">"พื้นที่เก็บข้อมูล"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"ข้อมูลที่แชร์"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"ดูและแก้ไขข้อมูลที่แชร์"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"รหัสข้อมูลที่แชร์: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"จะหมดอายุในวันที่ <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"แอปที่แชร์ข้อมูล"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"แอปไม่ได้ให้คำอธิบายไว้"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"เวลาได้รับสิทธิ์จะสิ้นสุดในวันที่ <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"ลบข้อมูลที่แชร์"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"คุณแน่ใจไหมว่าต้องการลบข้อมูลที่แชร์นี้"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"ผู้ใช้มีแอปและเนื้อหาของตัวเอง"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"คุณสามารถจำกัดการเข้าถึงแอปและเนื้อหาจากบัญชีของคุณได้"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"ผู้ใช้"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"โปรไฟล์ที่ถูกจำกัด"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"ต้องการเพิ่มผู้ใช้ใหม่ใช่ไหม"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"คุณมีสิทธิ์แชร์อุปกรณ์นี้กับผู้อื่นได้โดยการเพิ่มผู้ใช้ ซึ่งแต่ละคนจะมีพื้นที่ของตนเองและปรับใช้กับแอป วอลเปเปอร์ และรายการอื่นๆ ได้ อีกทั้งยังปรับการตั้งค่าอุปกรณ์ได้ด้วย เช่น Wi‑Fi ซึ่งจะมีผลกับทุกคน\n\nเมื่อคุณเพิ่มผู้ใช้ใหม่ ผู้ใช้ดังกล่าวจะต้องตั้งค่าพื้นที่ของตน\n\nผู้ใช้ทุกคนมีสิทธิ์อัปเดตแอปให้กับผู้ใช้รายอื่น การตั้งค่าและบริการสำหรับการช่วยเหลือพิเศษอาจโอนไปยังผู้ใช้ใหม่ไม่ได้"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"เมื่อคุณเพิ่มผู้ใช้ใหม่ ผู้ใช้ดังกล่าวจะต้องตั้งค่าพื้นที่ของตนเอง\n\nผู้ใช้ทุกคนสามารถอัปเดตแอปสำหรับผู้ใช้รายอื่นได้"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"ตั้งค่าผู้ใช้เลยไหม"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"ตรวจสอบว่าบุคคลดังกล่าวสามารถนำอุปกรณ์ไปตั้งค่าพื้นที่ของตนได้"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"หากต้องการตั้งค่าโปรไฟล์ทันที"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ตั้งค่าทันที"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ข้ามไปก่อน"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"เพิ่ม"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"ผู้ใช้ใหม่"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"โปรไฟล์ใหม่"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"ข้อมูลผู้ใช้"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"ข้อมูลโปรไฟล์"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"ก่อนที่คุณจะสามารถสร้างโปรไฟล์ที่ถูกจำกัดได้ คุณจะต้องตั้งค่าล็อกหน้าจอเพื่อปกป้องแอปและข้อมูลส่วนตัวของคุณ"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"ตั้งค่าล็อก"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index ac682f5..a3ae082 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address at Port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"I-scan ang QR code"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Ipares ang device gamit ang Wi‑Fi sa pamamagitan ng pag-scan ng isang QR Code"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Kumonekta sa Wi-Fi network"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Shortcut ng ulat sa bug"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Magpakita ng button sa power menu sa pagkuha ng ulat sa bug"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (pula-berde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (asul-dilaw)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Pagtatama ng kulay"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Nagbibigay-daan sa iyo ang pagtatama ng kulay na maisaayos kung paano ipinapakita ang mga kulay sa iyong device"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Tatagal hanggang mga <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Hanggang <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Posibleng maubos ang baterya sa loob ng <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mahigit <xliff:g id="TIME_REMAINING">%1$s</xliff:g> pa ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Speaker ng telepono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Nagkaproblema sa pagkonekta. I-off at pagkatapos ay i-on ang device"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired na audio device"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Tulong at feedback"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Storage"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Pinaghahatiang data"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Tingnan at baguhin ang pinaghahatiang data"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"ID ng pinaghahatiang data: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Mag-e-expire sa <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Mga app na nagbabahagi ng data"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Walang paglalarawang ibinigay ang app."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Mag-e-expire ang lease sa <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"I-delete ang pinaghahatiang data"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Sigurado ka bang gusto mong i-delete ang pinaghahatiang data na ito?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"May sariling apps at nilalaman ang mga user"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Maaari mong paghipitan ang access sa apps at nilalaman mula sa iyong account"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"User"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Pinaghihigpitang profile"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Magdagdag ng bagong user?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Puwede mong ibahagi ang device na ito sa ibang tao sa pamamagitan ng paggawa ng mga karagdagang user. May sariling espasyo ang bawat user na maaari nilang i-customize gamit ang mga app, wallpaper, at iba pa. Puwede ring isaayos ng mga user ang mga setting ng device tulad ng Wi‑Fi na nakakaapekto sa lahat.\n\nKapag nagdagdag ka ng bagong user, kailangang i-set up ng taong iyon ang kanyang espasyo.\n\nMaaaring mag-update ng mga app ang sinumang user para sa lahat ng iba pang user. Maaaring hindi malipat sa bagong user ang mga setting at serbisyo sa pagiging naa-access."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Kapag nagdagdag ka ng bagong user, kailangang i-set up ng taong iyon ang kanyang espasyo.\n\nAng sinumang user ay maaaring mag-update ng mga app para sa lahat ng iba pang user."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"I-set up ang user ngayon?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Tiyaking available ang tao na kunin ang device at i-set up ang kanyang space"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Mag-set up ng profile ngayon?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"I-set up ngayon"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Huwag ngayon"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Idagdag"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Bagong user"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Bagong profile"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Impormasyon ng user"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Info sa profile"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Bago ka makakalikha ng pinaghihigpitang profile, kakailanganin mong mag-set up ng screen lock upang protektahan ang iyong apps at personal na data."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Itakda ang lock"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 908409b..21f10c6 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresi ve Bağlantı noktası"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR kodunu tara"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR kodu tarayarak kablosuz ağ üzerinden cihaz eşleyin"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Lütfen Kablosuz bir ağa bağlanın"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, hata ayıklama, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Hata raporu kısayolu"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Hata raporu almak için güç menüsünde bir düğme göster"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Kırmızı renk körlüğü (kırmızı-yeşil)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Mavi renk körlüğü (mavi-sarı)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Renk düzeltme"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Renk düzeltme, renklerin cihazınızda nasıl görüntüleneceğini düzenlemenize olanak sağlar."</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Saat yaklaşık <xliff:g id="TIME">%1$s</xliff:g> olana kadar kullanılabilmelidir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Saat yaklaşık <xliff:g id="TIME">%1$s</xliff:g> olana kadar kullanılabilmelidir"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Şu saate kadar: <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Pilin tahmini bitiş zamanı: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"En fazla <xliff:g id="THRESHOLD">%1$s</xliff:g> kaldı"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"En çok <xliff:g id="THRESHOLD">%1$s</xliff:g> kaldı (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"En az <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon hoparlörü"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Bağlanırken sorun oluştu. Cihazı kapatıp tekrar açın"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kablolu ses cihazı"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Yardım ve geri bildirim"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Depolama"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Paylaşılan veri"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Paylaşılan verileri görüntüleyin ve değiştirin"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Paylaşılan veri kimliği: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Son kullanım tarihi: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Veri paylaşan uygulamalar"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Uygulama tarafından sağlanan açıklama yok."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Kiralama süresinin bitiş zamanı: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Paylaşılan verileri sil"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Bu paylaşılan verileri silmek istediğinizden emin misiniz?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Kullanıcıların kendi uygulamaları ve içerikleri var"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Hesabınızdaki uygulamalara ve içeriğe erişimi kısıtlayabilirsiniz"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Kullanıcı"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Kısıtlı profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Yeni kullanıcı eklensin mi?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Ek kullanıcılar oluşturarak bu cihazı başkalarıyla paylaşabilirsiniz. Her kullanıcının uygulamalarla, duvar kağıdıyla ve başka ayarlarla özelleştirebileceği kendi alanı olur. Kullanıcılar ayrıca kablosuz ağ gibi herkesi etkileyen cihaz ayarlarını değiştirebilirler.\n\nYeni bir kullanıcı eklediğinizde, ilgili kişinin kendi alanını ayarlaması gerekir.\n\nHer kullanıcı diğer tüm kullanıcılar için uygulamaları güncelleyebilir."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Yeni bir kullanıcı eklediğinizde, bu kişinin kendi alanını ayarlaması gerekir.\n\nHerhangi bir kullanıcı, diğer tüm kullanıcılar için uygulamaları güncelleyebilir."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Kullanıcı şimdi ayarlansın mı?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"İlgili kişinin cihazı almak ve kendi alanını ayarlamak için müsait olduğundan emin olun"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Profil şimdi yapılandırılsın mı?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Şimdi ayarla"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Şimdi değil"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Ekle"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Yeni kullanıcı"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Yeni profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Kullanıcı bilgileri"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profil bilgisi"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Kısıtlanmış bir profil oluşturabilmeniz için uygulamalarınızı ve kişisel verilerinizi korumak üzere bir ekran kilidi oluşturmanız gerekir."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Kilidi ayarla"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index c9a785f..f2a7492 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-адреса та порт"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Сканувати QR-код"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Підключати пристрій через Wi‑Fi за допомогою QR-коду"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Підключіть пристрій до мережі Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, налагодження, розробка"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Ярлик звіту про помилки"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Показувати в меню живлення кнопку створення звіту про помилки"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалія (червоний – зелений)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалія (синій – жовтий)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекція кольору"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Корекція кольору дає змогу регулювати відтінки зображення на екрані пристрою"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Залишилося приблизно <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Вистачить приблизно до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Вистачить приблизно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"До <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Акумулятор може розрядитися до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Залишилося менше ніж <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Залишилося менше ніж <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Залишилося понад <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -514,26 +511,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Динамік телефона"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Не вдається підключитися. Перезавантажте пристрій."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Дротовий аудіопристрій"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Довідка й відгуки"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Пам\'ять"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Спільні дані"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Переглянути та змінити спільні дані"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Ідентифікатор спільних даних: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Термін дії завершується <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Додатки зі спільним доступом до даних"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Немає опису, наданого додатком."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Період оренди закінчується <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Видалити спільні дані"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Видалити ці спільні дані?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Користувачі мають власні програми та вміст"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Ви можете обмежити доступ до програм і вмісту з вашого облікового запису"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Користувач"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Профіль з обмеженням"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Додати нового користувача?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Цим пристроєм можуть користуватися кілька людей. Для цього потрібно створити додаткові профілі. Власник профілю може налаштувати його на свій смак: вибрати фоновий малюнок, установити потрібні додатки тощо. Користувачі також можуть налаштовувати певні параметри пристрою (як-от Wi-Fi), які застосовуватимуться до решти профілів.\n\nПісля створення новий профіль потрібно налаштувати.\n\nБудь-який користувач пристрою може оновлювати додатки для решти користувачів. Налаштування спеціальних можливостей і сервісів можуть не передаватися новому користувачеві."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Користувач має налаштувати свій профіль після створення.\n\nБудь-який користувач пристрою може оновлювати додатки для решти користувачів."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Створити користувача зараз?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Переконайтеся, що користувач може взяти пристрій і налаштувати профіль"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Налаштувати профіль зараз?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Створити зараз"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Не зараз"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Додавання"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Новий користувач"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Новий профіль"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Дані користувача"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Інформація профілю"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Перш ніж створювати обмежений профіль, потрібно налаштувати блокування екрана, щоб захистити свої програми та особисті дані."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Налаштувати блокування"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 335808d..85b3e5c 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP پتہ اور پورٹ"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR کوڈ اسکین کریں"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR کوڈ اسکین کر کے Wi-Fi پر آلہ کا جوڑا بنائیں"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"براہ کرم ایک Wi-Fi نیٹ ورک سے منسلک ہوں"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb، ڈیبگ، dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"بگ رپورٹ کا شارٹ کٹ"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"بگ رپورٹ لینے کیلئے پاور مینو میں ایک بٹن دکھائیں"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (سرخ سبز)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (نیلا پیلا)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"رنگ کی اصلاح"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"رنگ کی اصلاح آپ کو یہ ایڈجسٹ کرنے کی سہولت دیتی ہے کہ آپ کے آلے پر رنگ کیسے ڈسپلے کئے جاتے ہیں"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> تک"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g> تک بیٹری ختم ہو سکتی ہے"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> سے زیادہ باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"فون اسپیکر"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"منسلک کرنے میں مسئلہ پیش آ گیا۔ آلہ کو آف اور بیک آن کریں"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"وائرڈ آڈیو آلہ"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"مدد اور تاثرات"</string>
+ <string name="storage_category" msgid="2287342585424631813">"اسٹوریج"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"اشتراک کردہ ڈیٹا"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"اشتراک کردہ ڈیٹا میں ترمیم اور ملاحظہ کریں"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"اشتراک کردہ ڈیٹا کی ID: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"میعاد کے اختتام کی تاریخ <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"ڈیٹا کا اشتراک کرنے والی ایپس"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"ایپ کے ذریعے کوئی بھی تفصیل فراہم نہیں کی گئی۔"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"لیز کی میعاد <xliff:g id="DATE">%s</xliff:g> کو ختم ہونے والی ہے"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"اشتراک کردہ ڈیٹا کو حذف کریں"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"کیا آپ واقعی اس اشتراک کردہ ڈیٹا کو حذف کرنا چاہتے ہیں؟"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"صارفین کے پاس اپنی خود کی ایپس اور مواد ہیں"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"آپ اپنے اکاؤنٹ سے ایپس اور مواد تک رسائی کو محدود کر سکتے ہیں"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"صارف"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"محدود پروفائل"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"نیا صارف شامل کریں؟"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"آپ اضافی صارفین تخلیق کر کے دوسرے لوگوں کے ساتھ اس آلہ کا اشتراک کر سکتے ہیں۔ ہر صارف کے پاس اپنی جگہ ہوتی ہے، جسے وہ ایپس، وال پیپر وغیرہ کے ساتھ حسب ضرورت بنا سکتا ہے۔ صارفین Wi‑Fi جیسی آلے کی ترتیبات کو ایڈجسٹ بھی کر سکتے ہیں جس کا اثر ہر کسی پر ہوتا ہے۔\n\nجب آپ ایک نیا صارف شامل کرتے ہیں، تو اسے اپنی جگہ سیٹ اپ کرنا پڑتی ہے۔\n\nکوئی بھی صارف دیگر تمام صارفین کیلئے ایپس اپ ڈیٹ کر سکتا ہے۔ رسائی کی ترتیبات اور سروسز کو نئے صارف کو منتقل نہیں کیا جا سکتا۔"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"جب آپ ایک نیا صارف شامل کرتے ہیں تو اس شخص کو اپنی جگہ کو ترتیب دینے کی ضرورت ہوتی ہے\n\nکوئی بھی صارف دیگر سبھی صارفین کیلئے ایپس کو اپ ڈیٹ کر سکتا ہے۔"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"صارف کو ابھی سیٹ اپ کریں؟"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"یقینی بنائیں کہ وہ شخص آلہ لینے اور اپنی جگہ کو سیٹ اپ کرنے کیلئے دستیاب ہے"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"پروفائل کو ابھی ترتیب دیں؟"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ابھی ترتیب دیں"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"ابھی نہیں"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"شامل کریں"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"نیا صارف"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"نیا پروفائل"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"صارف کی معلومات"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"پروفائل کی معلومات"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"ایک محدود پروفائل بنانے سے پہلے، آپ کو اپنی ایپس اور ذاتی ڈیٹا کو محفوظ کرنے کیلئے ایک اسکرین لاک سیٹ اپ کرنا ہوگا۔"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"لاک سیٹ کریں"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index c321d85..9578124 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP manzil va port"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR kodni skanerlash"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR kodni skanerlab, Wi-Fi orqali qurilmani ulang"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi tarmoqqa ulaning"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debag, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Xatoliklar hisoboti"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Menyuda xatoliklar hisobotini yuborish tugmasi ko‘rsatilsin"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qizil/yashil)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (ko‘k/sariq)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rangni tuzatish"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Ranglarni tuzatish orqali qurilmangizda ranglar qanday chiqishini tuzatish mumkin"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> gacha"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batareya quvvati tugash vaqti: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"<xliff:g id="THRESHOLD">%1$s</xliff:g>dan kamroq vaqt qoldi"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>dan kamroq vaqt qoldi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>dan ko‘proq vaqt qoldi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon karnayi"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ulanishda muammo yuz berdi. Qurilmani oʻchiring va yoqing"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio qurilma"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Yordam va fikr-mulohaza"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Xotira"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Umumiy maʼlumotlar"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Umumiy maʼlumotlarni ochish va oʻzgartirish"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Umumiy maʼlumotlar identifikatori: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Amal qilish muddati: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Umumiy maʼlumotlar bor ilovalar"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Ilova hech qanday tavsif bermagan."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Ruxsat eskirish sanasi: <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Umumiy maʼlumotlarni oʻchirish"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Umumiy maʼlumotlarni oʻchirishni xohlaysizmi?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Foydalanuvchilar o‘zlarining ilovalari va kontenlariga egalar"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Hisobingizdan ilovalar va kontentlarga kirishga cheklov o‘rnatishingiz mumkin"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Foydalanuvchi"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Cheklangan profil"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Foydalanuvchi qo‘shilsinmi?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Bu qurilmadan bir necha kishi alohida foydalanuvchilar qo‘shib foydalanishi mumkin. Har bir foydalanuvchiga diskda joy ajratiladi, tayinlangan hajm ilovalar, ekran foni rasmi, va hokazolarga taqsimlanishi mumkin. Foydalanuvchilar Wi-Fi kabi sozlamalarni o‘zgartirsa, qolganlarda ham aks etishi mumkin. \n\nYangi profil qo‘shilgach, uni sozlash lozim.\n\nQurilmaning istalgan foydalanuvchisi ilovalarni barcha hisoblar uchun yangilashi mumkin. Maxsus imkoniyatlar sozlamalari va xizmatlar yangi foydalanuvchiga o‘tkazilmasligi mumkin."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Yangi profil qo‘shilgach, uni sozlash lozim.\n\nQurilmaning istalgan foydalanuvchisi ilovalarni barcha hisoblar uchun yangilashi mumkin."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Profil hozir sozlansinmi?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Agar foydalanuvchi profilini hozir sozlay olmasa, keyinroq ham sozlab olishi mumkin."</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Profil hozir sozlansinmi?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Hozir sozlash"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Hozir emas"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Qo‘shish"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Yangi foydalanuvchi"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Yangi profil"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Foydalanuvchi ma‘lumoti"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Profil haqida axborot"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Cheklangan profil yaratish uchun, shaxsiy ilovlar va ma‘lumotlarni himoyalash maqsadida avval ekran qulfini yaratish lozim."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Qulf o‘rnatish"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 61f99fe..4af1b4f0 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Địa chỉ IP và cổng"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Quét mã QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Ghép nối thiết bị qua Wi-Fi bằng cách quét mã QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Hãy kết nối mạng Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, gỡ lỗi, nhà phát triển"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Phím tắt báo cáo lỗi"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Hiển thị một nút trong menu nguồn để báo cáo lỗi"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Mù màu đỏ không hoàn toàn (đỏ-xanh lục)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Mù màu (xanh lam-vàng)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Sửa màu"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Với chế độ hiệu chỉnh màu sắc, bạn có thể điều chỉnh cách các màu hiển thị trên thiết bị"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Sẽ hết pin cho tới khoảng <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Sẽ hết pin cho tới khoảng <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Cho đến <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Điện thoại có thể hết pin vào <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Còn lại không đến <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Còn lại không đến <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Còn lại hơn <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Loa điện thoại"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sự cố kết nối. Hãy tắt thiết bị rồi bật lại"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Thiết bị âm thanh có dây"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Trợ giúp và phản hồi"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Bộ nhớ"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Dữ liệu được chia sẻ"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Xem và sửa đổi dữ liệu được chia sẻ"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Mã dữ liệu được chia sẻ: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Hết hạn vào <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Những ứng dụng chia sẻ dữ liệu"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Ứng dụng này không cung cấp thông tin mô tả nào."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Thời gian thuê kết thúc vào ngày <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Xóa dữ liệu được chia sẻ"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Bạn có chắc chắn muốn xóa dữ liệu được chia sẻ này không?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Người dùng có ứng dụng và nội dung riêng của mình"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Bạn có thể hạn chế quyền truy cập vào ứng dụng và nội dung từ tài khoản của bạn"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Người dùng"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Tiểu sử bị hạn chế"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Thêm người dùng mới?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Bạn có thể chia sẻ thiết bị này với người khác bằng cách tạo thêm người dùng. Mỗi người dùng sẽ có không gian riêng của mình. Họ có thể tùy chỉnh không gian riêng đó bằng các ứng dụng, hình nền, v.v. Người dùng cũng có thể điều chỉnh các tùy chọn cài đặt thiết bị có ảnh hưởng đến tất cả mọi người, chẳng hạn như Wi‑Fi.\n\nKhi bạn thêm người dùng mới, họ cần thiết lập không gian của mình.\n\nMọi người dùng đều có thể cập nhật ứng dụng cho tất cả người dùng khác. Các dịch vụ và các tùy chọn cài đặt hỗ trợ tiếp cận có thể không chuyển sang người dùng mới."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Khi bạn thêm người dùng mới, họ cần thiết lập không gian của mình.\n\nMọi người dùng đều có thể cập nhật ứng dụng cho tất cả người dùng khác."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Thiết lập người dùng ngay bây giờ?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Đảm bảo người dùng có mặt để tự thiết lập không gian của mình trên thiết bị"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Thiết lập tiểu sử ngay bây giờ?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Thiết lập ngay"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Không phải bây giờ"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Thêm"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Người dùng mới"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Tiểu sử mới"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Thông tin người dùng"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Thông tin hồ sơ"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Trước khi bạn có thể tạo tiểu sử bị hạn chế, bạn sẽ cần thiết lập một màn hình khóa để bảo vệ các ứng dụng và dữ liệu cá nhân của bạn."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Thiết lập khóa"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 56be76f..d5425b2 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP 地址和端口"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"扫描二维码"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"扫描二维码即可通过 WLAN 配对设备"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"请连接到 WLAN 网络"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, 调试, debug, 开发, dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"错误报告快捷方式"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"在电源菜单中显示用于提交错误报告的按钮"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"红色弱视(红绿不分)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"蓝色弱视(蓝黄不分)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"借助颜色校正功能,您可以调整设备上的颜色显示方式"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"大约还可使用 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"目前电量为 <xliff:g id="LEVEL">%2$s</xliff:g>,估计能用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"估计能用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"直到<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"电池电量可能在<xliff:g id="TIME">%1$s</xliff:g> 耗尽"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"剩余电池续航时间不到 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"电量剩余使用时间不到 <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"电量剩余使用时间超过 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"手机扬声器"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"连接时遇到问题。请关闭并重新开启设备"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有线音频设备"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"帮助和反馈"</string>
+ <string name="storage_category" msgid="2287342585424631813">"存储"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"共享数据"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"查看和修改共享数据"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"共享数据 ID:<xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"到期时间是 <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"共享数据的应用"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"该应用未提供任何说明。"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"租约到期时间是 <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"删除共享数据"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"确定要删除这些共享数据吗?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"用户拥有个人专属的应用和内容"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"您可以限制其他人使用来自您的帐号的应用和内容"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"用户"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"受限个人资料"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"要添加新用户吗?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"创建新用户后,您就能够与其他人共用此设备。每位用户都有自己的专属空间,而且在自己的个人空间内还可以自行安装自己想要的应用、设置壁纸等。此外,用户还可以调整会影响所有用户的设备设置(例如 WLAN 设置)。\n\n当您添加新用户后,该用户需要自行设置个人空间。\n\n任何用户都可以为所有其他用户更新应用。无障碍功能设置和服务可能无法转移给新用户。"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"您添加新用户后,该用户必须设置自己的空间。\n\n任何用户均可为其他所有用户更新应用。"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"要现在设置该用户吗?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"请让相应用户操作设备并设置他们自己的空间。"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"要立即设置个人资料吗?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"立即设置"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"以后再说"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"添加"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"新用户"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"新的个人资料"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"用户信息"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"个人资料信息"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"您需要先设置锁定屏幕来保护您的应用和个人数据,然后才可以创建受限个人资料。"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"设置屏幕锁定方式"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index cfb86b9..07e4070 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP 位址和連接埠"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"掃瞄二維條碼"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"掃瞄二維條碼即可透過 Wi-Fi 配對裝置"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"請連線至 Wi-Fi 網絡"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, 偵錯, 開發"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"錯誤舉報捷徑"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"在電源選單中顯示提交錯誤舉報的按鈕"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"紅色弱視 (紅綠)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"藍色弱視 (藍黃)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"你可以用色彩校正調整裝置顯示嘅顏色"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"還有大約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"電量剩餘約 <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"電量剩餘約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"還可用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"電池電量可能將於<xliff:g id="TIME">%1$s</xliff:g>耗盡"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"剩餘電量時間少於 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"還有少於 <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"還有超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"手機喇叭"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連接,請關閉裝置然後重新開機"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音響裝置"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"說明與意見反映"</string>
+ <string name="storage_category" msgid="2287342585424631813">"儲存空間"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"共用資料"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"查看和修改共用資料"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"共用資料 ID:<xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"有效期至 <xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"應用程式共用資料"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"應用程式未提供描述。"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"租用到期日:<xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"刪除共用資料"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"確定要刪除此共用資料嗎?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"使用者擁有自己的應用程式和內容"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"您可以限制透過您的帳戶存取應用程式和內容"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"使用者"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"限制存取的個人檔案"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"新增使用者?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"您可以建立其他使用者,與他人共用這部裝置。每位使用者都有專屬的空間,並可使用應用程式、桌布等項目自訂個人空間。此外,使用者也可以調整會影響所有人的裝置設定,例如 Wi‑Fi 設定。\n\n新增的使用者需要自行設定個人空間。\n\n任何使用者都可以為所有其他使用者更新應用程式。無障礙功能設定和服務可能無法轉移至新的使用者。"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"新增的使用者需要自行設定個人空間。\n\n任何使用者都可以為其他所有使用者更新應用程式。"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"立即設定使用者?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"請確定對方現在可以使用裝置設定自己的空間"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"立即設定個人檔案?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"立即設定"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"暫時不要"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"新增"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"新使用者"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"新個人檔案"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"使用者資訊"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"個人檔案資料"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"建立限制存取的個人檔案前,您必須先設定上鎖畫面來保護您的應用程式和個人資料。"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"設定上鎖畫面"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index cf3f343..bf6265b 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP 位址和通訊埠"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"掃描 QR 圖碼"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"掃描 QR 圖碼即可透過 Wi-Fi 配對裝置"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"請連上 Wi-Fi 網路"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, 偵錯, 開發"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"錯誤回報捷徑"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"在電源選單中顯示取得錯誤報告的按鈕"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"紅色弱視 (紅-綠)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"藍色弱視 (藍-黃)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"色彩校正可讓你調整裝置上顯示的顏色"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"還能使用約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"目前電量 <xliff:g id="LEVEL">%2$s</xliff:g>,預估還能持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"預估還能持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"還能持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"電池電力可能於<xliff:g id="TIME">%1$s</xliff:g> 前耗盡"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"電池可用時間不到 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"電池可用時間不到 <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"電池可用時間超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"手機喇叭"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連線,請關閉裝置後再重新開啟"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音訊裝置"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"說明與意見回饋"</string>
+ <string name="storage_category" msgid="2287342585424631813">"儲存空間"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"共用資料"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"查看及修改共用資料"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"共用資料 ID:<xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"到期時間:<xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"分享資料的應用程式"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"應用程式未提供任何說明。"</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"租用到期時間:<xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"刪除共用資料"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"確定要刪除這項共用資料嗎?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"使用者擁有個人專屬的應用程式和內容"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"你可以限制他人透過你的帳戶存取應用程式和內容"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"使用者"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"設有限制的個人資料"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"新增使用者?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"你可以建立其他使用者,藉此與他人共用這個裝置。每位使用者都有自己的專屬空間,並可使用應用程式、桌布等項目自訂個人空間。此外,使用者也可以調整會影響所有人的裝置設定,例如 Wi‑Fi 設定。\n\n新增的使用者需要自行設定個人空間。\n\n任何使用者都可以為所有其他使用者更新應用程式。無障礙設定和服務可能無法轉移到新的使用者。"</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"新增的使用者需要自行設定個人空間。\n\n任何使用者皆可為其他所有使用者更新應用程式。"</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"立即設定使用者?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"請確保對方可以使用裝置並設定自己的空間"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"立即建立個人資料?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"立即設定"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"暫時不要"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"新增"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"新使用者"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"新的個人資料"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"使用者資訊"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"設定檔資訊"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"如要建立設有限制的個人資料,你必須先設定螢幕鎖定來保護你的應用程式和個人資料。"</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"設定鎖定"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 78e2099..0e08053 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -232,8 +232,7 @@
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Ikheli le-IP nembobo"</string>
<string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skena ikhodi ye-QR"</string>
<string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Bhangqa idivayisi nge-Wi‑Fi ngokuskena ikhodi ye-QR"</string>
- <!-- no translation found for adb_wireless_no_network_msg (2365795244718494658) -->
- <skip />
+ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Sicela uxhume kunethiwekhi ye-Wi-Fi"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"i-adb, ukulungisa amaphutha, i-dev"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"Isinqamuleli sombiko wesiphazamisi"</string>
<string name="bugreport_in_power_summary" msgid="1885529649381831775">"Bonisa inkinobho kwimenyu yamandla ngokuthatha umbiko wesiphazamiso"</string>
@@ -418,8 +417,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"I-Protanomaly (bomvu-luhlaza)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"I-Tritanomaly (luhlaza okwesibhakabhaka-phuzi)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Ukulungiswa kombala"</string>
- <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (1284746051652993443) -->
- <skip />
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Ukulungisa umbala kukuvumela ukuthi ulungise indlela imibala eboniswa ngayo kudivayisi yakho"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele"</string>
@@ -433,8 +431,7 @@
<string name="power_discharge_by" msgid="4113180890060388350">"Kumele ihlale cishe kube ngu-<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="92545648425937000">"Kumele ihlale cishe kube ngu-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only_short" msgid="5883041507426914446">"Kuze kube ngu-<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_suggestion_battery_run_out (6332089307827787087) -->
- <skip />
+ <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Ibhethri lingaphela ngo-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5802195288324091585">"Kusele okungaphansi kunokungu-<xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Ngaphansi kuka-<xliff:g id="THRESHOLD">%1$s</xliff:g> osele (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Ngaphezu kuka-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -512,26 +509,42 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"Isipikha sefoni"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Inkinga yokuxhumeka. Vala idivayisi futhi uphinde uyivule"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Idivayisi yomsindo enentambo"</string>
- <!-- no translation found for help_label (3528360748637781274) -->
+ <string name="help_label" msgid="3528360748637781274">"Usizo nempendulo"</string>
+ <string name="storage_category" msgid="2287342585424631813">"Isitoreji"</string>
+ <string name="shared_data_title" msgid="1017034836800864953">"Idatha eyabiwe"</string>
+ <string name="shared_data_summary" msgid="5516326713822885652">"Buka futhi ulungise idatha eyabiwe"</string>
+ <!-- no translation found for shared_data_no_blobs_text (3108114670341737434) -->
<skip />
- <!-- no translation found for storage_category (2287342585424631813) -->
+ <!-- no translation found for shared_data_query_failure_text (3489828881998773687) -->
<skip />
- <!-- no translation found for shared_data_title (1017034836800864953) -->
+ <string name="blob_id_text" msgid="8680078988996308061">"Idatha ye-ID eyabiwe: <xliff:g id="BLOB_ID">%d</xliff:g>"</string>
+ <string name="blob_expires_text" msgid="7882727111491739331">"Iphelelwa yisikhathi ngo-<xliff:g id="DATE">%s</xliff:g>"</string>
+ <!-- no translation found for shared_data_delete_failure_text (3842701391009628947) -->
<skip />
- <!-- no translation found for shared_data_summary (5516326713822885652) -->
+ <!-- no translation found for shared_data_no_accessors_dialog_text (8903738462570715315) -->
<skip />
- <!-- no translation found for blob_id_text (8680078988996308061) -->
- <skip />
- <!-- no translation found for blob_expires_text (7882727111491739331) -->
- <skip />
- <!-- no translation found for accessor_info_title (8289823651512477787) -->
- <skip />
- <!-- no translation found for accessor_no_description_text (7510967452505591456) -->
- <skip />
- <!-- no translation found for accessor_expires_text (4625619273236786252) -->
- <skip />
- <!-- no translation found for delete_blob_text (2819192607255625697) -->
- <skip />
- <!-- no translation found for delete_blob_confirmation_text (7807446938920827280) -->
- <skip />
+ <string name="accessor_info_title" msgid="8289823651512477787">"Izinhlelo zokusebenza ezabelana idatha"</string>
+ <string name="accessor_no_description_text" msgid="7510967452505591456">"Ayikho incazelo enikezwe yilolu hlelo lokusebenza."</string>
+ <string name="accessor_expires_text" msgid="4625619273236786252">"Ukuqashiswa kuphelelwa isikhathi ngo-<xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="delete_blob_text" msgid="2819192607255625697">"Susa idatha eyabiwe"</string>
+ <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"Uyaqiniseka yini ngokuthi ufuna ukususa le datha eyabiwe?"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"Abasebenzisi banezinhlelo zabo zokusebenza nokuqukethwe"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"Ungakhawulela ukufinyelela kuzinhlelo zokusebenza nokuqukethwe kusukela ku-akhawunti yakho"</string>
+ <string name="user_add_user_item_title" msgid="2394272381086965029">"Umsebenzisi"</string>
+ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Iphrofayela evinjelwe"</string>
+ <string name="user_add_user_title" msgid="5457079143694924885">"Engeza umsebenzisi omusha?"</string>
+ <string name="user_add_user_message_long" msgid="1527434966294733380">"Manje ungabelana ngale divayisi nabanye abantu ngokudala abasebenzisi abangeziwe. Umsebenzisi ngamunye unesikhala sakhe, angakwazi ukusenza ngendlela ayifisayo ngezinhlelo zokusebenza, isithombe sangemuva, njalo njalo. Abasebenzisi bangalungisa izilungiselelo zedivayisi ezifana ne-Wi-Fi ezithinta wonke umuntu.\n\nUma ungeza umsebenzisi omusha, loyo muntu kumele asethe isikhala sakhe.\n\nNoma imuphi umsebenzisi angabuyekeza izinhlelo zokusebenza kubo bonke abanye abasebenzisi. Izilungiselelo zokufinyelela kungenzeka zingadluliselwa kumsebenzisi omusha."</string>
+ <string name="user_add_user_message_short" msgid="3295959985795716166">"Uma ungeza umsebenzisi omusha, loyo muntu udinga ukusetha isikhala sakhe.\n\nNoma yimuphi umsebenzisi angabuyekeza izinhlelo zokusebenza kubo bonke abasebenzisi."</string>
+ <string name="user_setup_dialog_title" msgid="8037342066381939995">"Setha umsebenzisi manje?"</string>
+ <string name="user_setup_dialog_message" msgid="269931619868102841">"Qinisekisa ukuthi umuntu uyatholakala ukuze athathe idivayisi futhi asethe isikhala sakhe"</string>
+ <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Setha iphrofayela manje?"</string>
+ <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Setha manje"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Hhayi manje"</string>
+ <string name="user_add_user_type_title" msgid="551279664052914497">"Engeza"</string>
+ <string name="user_new_user_name" msgid="60979820612818840">"Umsebenzisi omusha"</string>
+ <string name="user_new_profile_name" msgid="2405500423304678841">"Iphrofayela entsha"</string>
+ <string name="user_info_settings_title" msgid="6351390762733279907">"Ulwazi lomsebenzisi"</string>
+ <string name="profile_info_settings_title" msgid="105699672534365099">"Ulwazi lwephrofayela"</string>
+ <string name="user_need_lock_message" msgid="4311424336209509301">"Ngaphambi kokuthi ungadala iphrofayela ekhawulelwe, kuzomele usethe ukukhiya isikrini ukuze uvikele izinhlelo zakho zokusebenza nedatha yakho yomuntu siqu."</string>
+ <string name="user_set_lock_button" msgid="1427128184982594856">"Setha ukukhiya"</string>
</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 3f59f89..9112602 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1291,10 +1291,18 @@
<string name="shared_data_title">Shared data</string>
<!-- Storage: shared data summary [CHAR LIMIT=80] -->
<string name="shared_data_summary">View and modify shared data</string>
+ <!-- Shared data: display text when there are no shared data blobs available [CHAR LIMIT=NONE] -->
+ <string name="shared_data_no_blobs_text">There is no shared data for this user.</string>
+ <!-- Shared data: text to display when there was an error while fetching shared data for the user [CHAR LIMIT=NONE] -->
+ <string name="shared_data_query_failure_text">There was an error fetching shared data. Try again.</string>
<!-- Shared data: shared data id [CHAR LIMIT=50] -->
<string name="blob_id_text">Shared data ID: <xliff:g id="blob_id" example="100">%d</xliff:g></string>
<!-- Shared data: label to indicate when the shared data expires [CHAR LIMIT=80] -->
<string name="blob_expires_text">Expires at <xliff:g id="date" example="Mar 20, 2020 11:59:59 GMT">%s</xliff:g></string>
+ <!-- Shared data: text to display when there was an error while deleting a shared data object [CHAR LIMIT=NONE] -->
+ <string name="shared_data_delete_failure_text">There was an error deleting the shared data.</string>
+ <!-- Shared data: dialog text when there are no acquired leases for a blob [CHAR LIMIT=NONE] -->
+ <string name="shared_data_no_accessors_dialog_text">There are no leases acquired for this shared data. Would you like to delete it?</string>
<!-- Shared data: title for screen showing list of packages accessing some shared data [CHAR LIMIT=50] -->
<string name="accessor_info_title">Apps sharing data</string>
<!-- Shared data: text indicating that no description was provided by the app for this shared data [CHAR LIMIT=80] -->
@@ -1344,5 +1352,14 @@
<string name="user_need_lock_message">Before you can create a restricted profile, you\u2019ll need to set up a screen lock to protect your apps and personal data.</string>
<!-- User settings dialog button to set screen lock [CHAR LIMIT=25] -->
<string name="user_set_lock_button">Set lock</string>
+ <!-- Label for switching to other user in the user switcher [CHAR LIMIT=35] -->
+ <string name="user_switch_to_user">Switch to <xliff:g id="user_name" example="John Doe">%s</xliff:g></string>
+
+ <!-- Label for adding a new guest in the user switcher [CHAR LIMIT=35] -->
+ <string name="guest_new_guest">Add guest</string>
+ <!-- Label for exiting and removing the guest session in the user switcher [CHAR LIMIT=35] -->
+ <string name="guest_exit_guest">Remove guest</string>
+ <!-- Name for the guest user [CHAR LIMIT=35] -->
+ <string name="guest_nickname">Guest</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 24cd551..cf16624 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -52,7 +52,6 @@
private static final String TAG = "InfoMediaManager";
private static final boolean DEBUG = false;
-
@VisibleForTesting
final RouterManagerCallback mMediaRouterCallback = new RouterManagerCallback();
@VisibleForTesting
@@ -138,14 +137,10 @@
}
private RoutingSessionInfo getRoutingSessionInfo() {
- for (RoutingSessionInfo info : mRouterManager.getRoutingSessions(mPackageName)) {
- if (TextUtils.equals(info.getClientPackageName(), mPackageName)) {
- return info;
- }
- }
+ final List<RoutingSessionInfo> sessionInfos =
+ mRouterManager.getRoutingSessions(mPackageName);
- Log.w(TAG, "RoutingSessionInfo() cannot found match packagename : " + mPackageName);
- return null;
+ return sessionInfos.get(sessionInfos.size() - 1);
}
/**
@@ -181,10 +176,7 @@
return false;
}
-
- final List<RoutingSessionInfo> sessionInfos =
- mRouterManager.getRoutingSessions(mPackageName);
- final RoutingSessionInfo sessionInfo = sessionInfos.get(sessionInfos.size() - 1);
+ final RoutingSessionInfo sessionInfo = getRoutingSessionInfo();
if (sessionInfo != null) {
mRouterManager.releaseSession(sessionInfo);
@@ -375,7 +367,7 @@
mediaDevice = new InfoMediaDevice(mContext, mRouterManager, route,
mPackageName);
if (!TextUtils.isEmpty(mPackageName)
- && TextUtils.equals(route.getClientPackageName(), mPackageName)
+ && getRoutingSessionInfo().getSelectedRoutes().contains(route.getId())
&& mCurrentConnectedDevice == null) {
mCurrentConnectedDevice = mediaDevice;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
index 01a5789..87e97b1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
@@ -25,6 +25,7 @@
import android.service.notification.ZenModeConfig;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -228,39 +229,40 @@
}
private void updateButtons(ConditionTag tag, View row, int rowIndex) {
- // minus button
- final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
- button1.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- onClickTimeButton(row, tag, false /*down*/, rowIndex);
- tag.lines.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
- }
- });
-
- // plus button
- final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
- button2.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- onClickTimeButton(row, tag, true /*up*/, rowIndex);
- tag.lines.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
- }
- });
-
+ final ImageView minusButton = (ImageView) row.findViewById(android.R.id.button1);
+ final ImageView plusButton = (ImageView) row.findViewById(android.R.id.button2);
final long time = tag.countdownZenDuration;
if (rowIndex == COUNTDOWN_CONDITION_INDEX) {
- button1.setVisibility(View.VISIBLE);
- button2.setVisibility(View.VISIBLE);
+ minusButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onClickTimeButton(row, tag, false /*down*/, rowIndex);
+ tag.lines.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
+ }
+ });
- button1.setEnabled(time > MIN_BUCKET_MINUTES);
- button2.setEnabled(tag.countdownZenDuration != MAX_BUCKET_MINUTES);
+ plusButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onClickTimeButton(row, tag, true /*up*/, rowIndex);
+ tag.lines.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
+ }
+ });
+ minusButton.setVisibility(View.VISIBLE);
+ plusButton.setVisibility(View.VISIBLE);
- button1.setAlpha(button1.isEnabled() ? 1f : .5f);
- button2.setAlpha(button2.isEnabled() ? 1f : .5f);
+ minusButton.setEnabled(time > MIN_BUCKET_MINUTES);
+ plusButton.setEnabled(tag.countdownZenDuration != MAX_BUCKET_MINUTES);
+
+ minusButton.setAlpha(minusButton.isEnabled() ? 1f : .5f);
+ plusButton.setAlpha(plusButton.isEnabled() ? 1f : .5f);
} else {
- button1.setVisibility(View.GONE);
- button2.setVisibility(View.GONE);
+ if (minusButton != null) {
+ ((ViewGroup) row).removeView(minusButton);
+ }
+ if (plusButton != null) {
+ ((ViewGroup) row).removeView(plusButton);
+ }
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
index 7f93f69..d0c37a0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
@@ -77,6 +77,14 @@
@Test
public void onRouteAdded_getAvailableRoutes_shouldAddMediaDevice() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(sessionInfo);
+ final List<String> selectedRoutes = new ArrayList<>();
+ selectedRoutes.add(TEST_ID);
+ when(sessionInfo.getSelectedRoutes()).thenReturn(selectedRoutes);
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+
final MediaRoute2Info info = mock(MediaRoute2Info.class);
when(info.getId()).thenReturn(TEST_ID);
when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
@@ -120,6 +128,14 @@
@Test
public void onControlCategoriesChanged_samePackageName_shouldAddMediaDevice() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(sessionInfo);
+ final List<String> selectedRoutes = new ArrayList<>();
+ selectedRoutes.add(TEST_ID);
+ when(sessionInfo.getSelectedRoutes()).thenReturn(selectedRoutes);
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+
final MediaRoute2Info info = mock(MediaRoute2Info.class);
when(info.getId()).thenReturn(TEST_ID);
when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
@@ -148,6 +164,14 @@
@Test
public void onRoutesChanged_getAvailableRoutes_shouldAddMediaDevice() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(sessionInfo);
+ final List<String> selectedRoutes = new ArrayList<>();
+ selectedRoutes.add(TEST_ID);
+ when(sessionInfo.getSelectedRoutes()).thenReturn(selectedRoutes);
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+
final MediaRoute2Info info = mock(MediaRoute2Info.class);
mInfoMediaManager.registerCallback(mCallback);
@@ -210,6 +234,14 @@
@Test
public void onRoutesRemoved_getAvailableRoutes_shouldAddMediaDevice() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(sessionInfo);
+ final List<String> selectedRoutes = new ArrayList<>();
+ selectedRoutes.add(TEST_ID);
+ when(sessionInfo.getSelectedRoutes()).thenReturn(selectedRoutes);
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+
final MediaRoute2Info info = mock(MediaRoute2Info.class);
when(info.getId()).thenReturn(TEST_ID);
when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
@@ -409,13 +441,12 @@
}
@Test
- public void getSessionVolumeMax_notContainPackageName_returnNotFound() {
+ public void getSessionVolumeMax_routeSessionInfoIsNull_returnNotFound() {
final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
- final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ final RoutingSessionInfo info = null;
routingSessionInfos.add(info);
mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
- when(info.getClientPackageName()).thenReturn("com.fake.packagename");
assertThat(mInfoMediaManager.getSessionVolumeMax()).isEqualTo(-1);
}
@@ -442,13 +473,12 @@
}
@Test
- public void getSessionVolume_notContainPackageName_returnNotFound() {
+ public void getSessionVolume_routeSessionInfoIsNull_returnNotFound() {
final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
- final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ final RoutingSessionInfo info = null;
routingSessionInfos.add(info);
mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
- when(info.getClientPackageName()).thenReturn("com.fake.packagename");
assertThat(mInfoMediaManager.getSessionVolume()).isEqualTo(-1);
}
@@ -480,14 +510,12 @@
}
@Test
- public void getSessionName_notContainPackageName_returnNull() {
+ public void getSessionName_routeSessionInfoIsNull_returnNull() {
final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
- final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+ final RoutingSessionInfo info = null;
routingSessionInfos.add(info);
mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
- when(info.getClientPackageName()).thenReturn("com.fake.packagename");
- when(info.getName()).thenReturn(TEST_NAME);
assertThat(mInfoMediaManager.getSessionName()).isNull();
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 3c0ddc4..736e995 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -96,6 +96,7 @@
Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
Settings.Secure.QS_TILES,
+ Settings.Secure.CONTROLS_ENABLED,
Settings.Secure.DOZE_ENABLED,
Settings.Secure.DOZE_ALWAYS_ON,
Settings.Secure.DOZE_PICK_UP_GESTURE,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 3e64a37..b413e8e 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -141,6 +141,7 @@
VALIDATORS.put(Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.QS_TILES, TILE_LIST_VALIDATOR);
+ VALIDATORS.put(Secure.CONTROLS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DOZE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DOZE_ALWAYS_ON, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DOZE_PICK_UP_GESTURE, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 6fba15f..8a7b913 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1972,6 +1972,13 @@
dumpSetting(s, p,
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
SecureSettingsProto.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS);
+
+ final long controlsToken = p.start(SecureSettingsProto.CONTROLS);
+ dumpSetting(s, p,
+ Settings.Secure.CONTROLS_ENABLED,
+ SecureSettingsProto.Controls.ENABLED);
+ p.end(controlsToken);
+
dumpSetting(s, p,
Settings.Secure.DEVICE_PAIRED,
SecureSettingsProto.DEVICE_PAIRED);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index a36949b..d5c04dc 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -267,6 +267,7 @@
Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS,
+ Settings.Global.ENABLE_ADB_INCREMENTAL_INSTALL_DEFAULT,
Settings.Global.ENHANCED_CONNECTIVITY_ENABLED,
Settings.Global.ENHANCED_4G_MODE_ENABLED,
Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
@@ -317,7 +318,6 @@
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST,
Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST,
- Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
Settings.Global.LOCATION_GLOBAL_KILL_SWITCH,
Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED,
Settings.Global.LOCK_SOUND,
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 656827a..c8cf7f50 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -4,7 +4,6 @@
adamcohen@google.com
asc@google.com
-ashaikh@google.com
beverlyt@google.com
brockman@google.com
cinek@google.com
@@ -12,8 +11,8 @@
dupin@google.com
ethibodeau@google.com
evanlaird@google.com
+hwwang@google.com
hyunyoungs@google.com
-jmonk@google.com
jaggies@google.com
jjaggi@google.com
joshmcgrath@google.com
@@ -29,16 +28,16 @@
mrenouf@google.com
nbenbernou@google.com
nesciosquid@google.com
-ngmatthew@google.com
ogunwale@google.com
+peanutbutter@google.com
pixel@google.com
roosa@google.com
-shahrk@google.com
snoeberger@google.com
steell@google.com
stwu@google.com
sunnygoyal@google.com
susikp@google.com
+tracyzhou@google.com
tsuji@google.com
twickham@google.com
winsonc@google.com
diff --git a/packages/SystemUI/res/drawable/control_background_ripple.xml b/packages/SystemUI/res/drawable/control_background_ripple.xml
new file mode 100644
index 0000000..37914e2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/control_background_ripple.xml
@@ -0,0 +1,23 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <color android:color="@android:color/white" />
+ </item>
+ <item android:drawable="@drawable/control_background" />
+</ripple>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_device_air_freshener_off.xml b/packages/SystemUI/res/drawable/ic_device_air_freshener_off.xml
new file mode 100644
index 0000000..c343020
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_air_freshener_off.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,5C12.5523,5 13,4.5523 13,4C13,3.4477 12.5523,3 12,3C11.4477,3 11,3.4477 11,4C11,4.5523 11.4477,5 12,5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,2C12.5523,2 13,1.5523 13,1C13,0.4477 12.5523,0 12,0C11.4477,0 11,0.4477 11,1C11,1.5523 11.4477,2 12,2Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M9.707,4.707C9.8469,4.5671 9.9421,4.389 9.9808,4.195C10.0194,4.001 9.9996,3.7999 9.9239,3.6172C9.8482,3.4344 9.72,3.2782 9.5556,3.1683C9.3911,3.0584 9.1978,2.9998 9,2.9998C8.8022,2.9998 8.6088,3.0584 8.4444,3.1683C8.2799,3.2782 8.1518,3.4344 8.0761,3.6172C8.0004,3.7999 7.9806,4.001 8.0192,4.195C8.0578,4.389 8.1531,4.5671 8.293,4.707C8.4805,4.8944 8.7348,4.9998 9,4.9998C9.2652,4.9998 9.5195,4.8944 9.707,4.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M7.707,2.707C7.8469,2.5671 7.9422,2.389 7.9808,2.195C8.0194,2.001 7.9996,1.7999 7.9239,1.6172C7.8482,1.4344 7.7201,1.2782 7.5556,1.1683C7.3911,1.0584 7.1978,0.9998 7,0.9998C6.8022,0.9998 6.6089,1.0584 6.4444,1.1683C6.2799,1.2782 6.1518,1.4344 6.0761,1.6172C6.0004,1.7999 5.9806,2.001 6.0192,2.195C6.0578,2.389 6.1531,2.5671 6.293,2.707C6.4805,2.8944 6.7348,2.9998 7,2.9998C7.2652,2.9998 7.5195,2.8944 7.707,2.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15.707,4.707C15.8469,4.5671 15.9421,4.389 15.9808,4.195C16.0194,4.001 15.9996,3.7999 15.9239,3.6172C15.8482,3.4344 15.7201,3.2782 15.5556,3.1683C15.3911,3.0584 15.1978,2.9998 15,2.9998C14.8022,2.9998 14.6088,3.0584 14.4444,3.1683C14.2799,3.2782 14.1518,3.4344 14.0761,3.6172C14.0004,3.7999 13.9806,4.001 14.0192,4.195C14.0578,4.389 14.1531,4.5671 14.293,4.707C14.4805,4.8944 14.7348,4.9998 15,4.9998C15.2652,4.9998 15.5195,4.8944 15.707,4.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17.707,2.707C17.8469,2.5671 17.9421,2.389 17.9808,2.195C18.0194,2.001 17.9996,1.7999 17.9239,1.6172C17.8482,1.4344 17.7201,1.2782 17.5556,1.1683C17.3911,1.0584 17.1978,0.9998 17,0.9998C16.8022,0.9998 16.6088,1.0584 16.4444,1.1683C16.2799,1.2782 16.1518,1.4344 16.0761,1.6172C16.0004,1.7999 15.9806,2.001 16.0192,2.195C16.0578,2.389 16.1531,2.5671 16.293,2.707C16.4805,2.8944 16.7348,2.9998 17,2.9998C17.2652,2.9998 17.5195,2.8944 17.707,2.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,9.683V7C15,6.7348 14.8946,6.4804 14.7071,6.2929C14.5196,6.1054 14.2652,6 14,6H10C9.7348,6 9.4804,6.1054 9.2929,6.2929C9.1053,6.4804 9,6.7348 9,7V9.683C7.855,10.2245 6.8787,11.067 6.1756,12.1205C5.4725,13.174 5.0689,14.3988 5.0081,15.6639C4.9473,16.929 5.2315,18.1868 5.8304,19.3029C6.4292,20.4189 7.3202,21.3512 8.408,22H15.592C16.6798,21.3512 17.5707,20.4189 18.1696,19.3029C18.7685,18.1868 19.0527,16.929 18.9919,15.6639C18.9311,14.3988 18.5275,13.174 17.8244,12.1205C17.1212,11.067 16.145,10.2245 15,9.683ZM14.989,20H9.011C8.3852,19.5381 7.877,18.9352 7.5276,18.2402C7.1783,17.5453 6.9975,16.7778 7,16C7.0041,15.0553 7.2746,14.131 7.7803,13.3331C8.286,12.5351 9.0065,11.896 9.859,11.489L11,10.946V8H13V10.946L14.141,11.489C14.9935,11.896 15.714,12.5351 16.2197,13.3331C16.7254,14.131 16.9959,15.0553 17,16C17.0025,16.7778 16.8217,17.5453 16.4723,18.2402C16.123,18.9352 15.6148,19.5381 14.989,20Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_air_freshener_on.xml b/packages/SystemUI/res/drawable/ic_device_air_freshener_on.xml
new file mode 100644
index 0000000..4f3434d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_air_freshener_on.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,5C12.5523,5 13,4.5523 13,4C13,3.4477 12.5523,3 12,3C11.4477,3 11,3.4477 11,4C11,4.5523 11.4477,5 12,5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,2C12.5523,2 13,1.5523 13,1C13,0.4477 12.5523,0 12,0C11.4477,0 11,0.4477 11,1C11,1.5523 11.4477,2 12,2Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M9.707,4.707C9.8469,4.5671 9.9422,4.389 9.9808,4.195C10.0194,4.001 9.9996,3.7999 9.9239,3.6172C9.8482,3.4344 9.7201,3.2782 9.5556,3.1683C9.3912,3.0584 9.1978,2.9998 9,2.9998C8.8022,2.9998 8.6088,3.0584 8.4444,3.1683C8.2799,3.2782 8.1518,3.4344 8.0761,3.6172C8.0004,3.7999 7.9806,4.001 8.0192,4.195C8.0578,4.389 8.1531,4.5671 8.293,4.707C8.4805,4.8944 8.7348,4.9998 9,4.9998C9.2652,4.9998 9.5195,4.8944 9.707,4.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M7.707,2.707C7.8469,2.5671 7.9422,2.389 7.9808,2.195C8.0194,2.001 7.9996,1.7999 7.9239,1.6172C7.8482,1.4344 7.7201,1.2782 7.5556,1.1683C7.3911,1.0584 7.1978,0.9998 7,0.9998C6.8022,0.9998 6.6089,1.0584 6.4444,1.1683C6.2799,1.2782 6.1518,1.4344 6.0761,1.6172C6.0004,1.7999 5.9806,2.001 6.0192,2.195C6.0578,2.389 6.1531,2.5671 6.293,2.707C6.4805,2.8944 6.7348,2.9998 7,2.9998C7.2652,2.9998 7.5195,2.8944 7.707,2.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15.707,4.707C15.8469,4.5671 15.9422,4.389 15.9808,4.195C16.0194,4.001 15.9996,3.7999 15.9239,3.6172C15.8482,3.4344 15.7201,3.2782 15.5556,3.1683C15.3911,3.0584 15.1978,2.9998 15,2.9998C14.8022,2.9998 14.6089,3.0584 14.4444,3.1683C14.2799,3.2782 14.1518,3.4344 14.0761,3.6172C14.0004,3.7999 13.9806,4.001 14.0192,4.195C14.0578,4.389 14.1531,4.5671 14.293,4.707C14.4805,4.8944 14.7348,4.9998 15,4.9998C15.2652,4.9998 15.5195,4.8944 15.707,4.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17.707,2.707C17.8469,2.5671 17.9422,2.389 17.9808,2.195C18.0194,2.001 17.9996,1.7999 17.9239,1.6172C17.8482,1.4344 17.7201,1.2782 17.5556,1.1683C17.3911,1.0584 17.1978,0.9998 17,0.9998C16.8022,0.9998 16.6089,1.0584 16.4444,1.1683C16.2799,1.2782 16.1518,1.4344 16.0761,1.6172C16.0004,1.7999 15.9806,2.001 16.0192,2.195C16.0578,2.389 16.1531,2.5671 16.293,2.707C16.4805,2.8944 16.7348,2.9998 17,2.9998C17.2652,2.9998 17.5195,2.8944 17.707,2.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,9.683V7C15,6.7348 14.8946,6.4804 14.7071,6.2929C14.5196,6.1054 14.2652,6 14,6H10C9.7348,6 9.4804,6.1054 9.2929,6.2929C9.1053,6.4804 9,6.7348 9,7V9.683C7.855,10.2245 6.8787,11.067 6.1756,12.1205C5.4725,13.174 5.0689,14.3988 5.0081,15.6639C4.9473,16.929 5.2315,18.1868 5.8304,19.3029C6.4292,20.4189 7.3202,21.3512 8.408,22H15.592C16.6798,21.3512 17.5707,20.4189 18.1696,19.3029C18.7685,18.1868 19.0527,16.929 18.9919,15.6639C18.9311,14.3988 18.5275,13.174 17.8244,12.1205C17.1213,11.067 16.145,10.2245 15,9.683Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_air_purifier_off.xml b/packages/SystemUI/res/drawable/ic_device_air_purifier_off.xml
new file mode 100644
index 0000000..b18c3e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_air_purifier_off.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,19H5V7C5.0016,6.47 5.2128,5.9623 5.5875,5.5875C5.9623,5.2128 6.47,5.0016 7,5H14C14.5299,5.0016 15.0377,5.2128 15.4125,5.5875C15.7872,5.9623 15.9984,6.47 16,7V8H18V7C18,5.9391 17.5786,4.9217 16.8284,4.1716C16.0783,3.4214 15.0609,3 14,3H7C5.9391,3 4.9217,3.4214 4.1716,4.1716C3.4214,4.9217 3,5.9391 3,7V21H18V17H16V19Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M19,13C18.6049,13.378 18.1309,13.6638 17.6122,13.8367C17.0935,14.0096 16.5429,14.0653 16,14V16C16.5429,16.0653 17.0935,16.0096 17.6122,15.8367C18.1309,15.6638 18.6049,15.378 19,15C19.93,14.02 20,14 21,14V12C20,12 19.93,12.02 19,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M19,9C18.6049,9.378 18.1309,9.6638 17.6122,9.8367C17.0935,10.0096 16.5429,10.0653 16,10V12C16.5429,12.0653 17.0935,12.0096 17.6122,11.8367C18.1309,11.6638 18.6049,11.378 19,11C19.93,10.02 20,10 21,10V8C20,8 19.93,8.02 19,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M10.5,8C9.7089,8 8.9355,8.2346 8.2777,8.6741C7.6199,9.1137 7.1072,9.7383 6.8045,10.4692C6.5017,11.2001 6.4225,12.0044 6.5769,12.7803C6.7312,13.5563 7.1122,14.269 7.6716,14.8284C8.231,15.3878 8.9437,15.7688 9.7196,15.9232C10.4956,16.0775 11.2998,15.9982 12.0307,15.6955C12.7616,15.3927 13.3864,14.8801 13.8259,14.2223C14.2654,13.5645 14.5,12.7911 14.5,12C14.5,10.9391 14.0786,9.9217 13.3284,9.1716C12.5783,8.4214 11.5609,8 10.5,8ZM10.5,14C10.1044,14 9.7178,13.8827 9.3889,13.663C9.06,13.4432 8.8036,13.1308 8.6522,12.7654C8.5009,12.3999 8.4613,11.9978 8.5384,11.6098C8.6156,11.2218 8.8061,10.8655 9.0858,10.5858C9.3655,10.3061 9.7219,10.1156 10.1098,10.0385C10.4978,9.9613 10.8999,10.0008 11.2654,10.1522C11.6308,10.3036 11.9432,10.56 12.1629,10.8889C12.3827,11.2178 12.5,11.6044 12.5,12C12.5,12.5304 12.2893,13.0391 11.9142,13.4142C11.5391,13.7893 11.0304,14 10.5,14Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_air_purifier_on.xml b/packages/SystemUI/res/drawable/ic_device_air_purifier_on.xml
new file mode 100644
index 0000000..b18c3e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_air_purifier_on.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,19H5V7C5.0016,6.47 5.2128,5.9623 5.5875,5.5875C5.9623,5.2128 6.47,5.0016 7,5H14C14.5299,5.0016 15.0377,5.2128 15.4125,5.5875C15.7872,5.9623 15.9984,6.47 16,7V8H18V7C18,5.9391 17.5786,4.9217 16.8284,4.1716C16.0783,3.4214 15.0609,3 14,3H7C5.9391,3 4.9217,3.4214 4.1716,4.1716C3.4214,4.9217 3,5.9391 3,7V21H18V17H16V19Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M19,13C18.6049,13.378 18.1309,13.6638 17.6122,13.8367C17.0935,14.0096 16.5429,14.0653 16,14V16C16.5429,16.0653 17.0935,16.0096 17.6122,15.8367C18.1309,15.6638 18.6049,15.378 19,15C19.93,14.02 20,14 21,14V12C20,12 19.93,12.02 19,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M19,9C18.6049,9.378 18.1309,9.6638 17.6122,9.8367C17.0935,10.0096 16.5429,10.0653 16,10V12C16.5429,12.0653 17.0935,12.0096 17.6122,11.8367C18.1309,11.6638 18.6049,11.378 19,11C19.93,10.02 20,10 21,10V8C20,8 19.93,8.02 19,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M10.5,8C9.7089,8 8.9355,8.2346 8.2777,8.6741C7.6199,9.1137 7.1072,9.7383 6.8045,10.4692C6.5017,11.2001 6.4225,12.0044 6.5769,12.7803C6.7312,13.5563 7.1122,14.269 7.6716,14.8284C8.231,15.3878 8.9437,15.7688 9.7196,15.9232C10.4956,16.0775 11.2998,15.9982 12.0307,15.6955C12.7616,15.3927 13.3864,14.8801 13.8259,14.2223C14.2654,13.5645 14.5,12.7911 14.5,12C14.5,10.9391 14.0786,9.9217 13.3284,9.1716C12.5783,8.4214 11.5609,8 10.5,8ZM10.5,14C10.1044,14 9.7178,13.8827 9.3889,13.663C9.06,13.4432 8.8036,13.1308 8.6522,12.7654C8.5009,12.3999 8.4613,11.9978 8.5384,11.6098C8.6156,11.2218 8.8061,10.8655 9.0858,10.5858C9.3655,10.3061 9.7219,10.1156 10.1098,10.0385C10.4978,9.9613 10.8999,10.0008 11.2654,10.1522C11.6308,10.3036 11.9432,10.56 12.1629,10.8889C12.3827,11.2178 12.5,11.6044 12.5,12C12.5,12.5304 12.2893,13.0391 11.9142,13.4142C11.5391,13.7893 11.0304,14 10.5,14Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_blinds_off.xml b/packages/SystemUI/res/drawable/ic_device_blinds_off.xml
new file mode 100644
index 0000000..a511ad2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_blinds_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,18V4H4V18H2V20H22V18H20ZM18,6V9H6V6H18ZM6,18V11H11V13.2771C10.6187,13.4972 10.3207,13.8369 10.1522,14.2437C9.9838,14.6504 9.9542,15.1013 10.0681,15.5266C10.1821,15.9519 10.4332,16.3277 10.7825,16.5957C11.1318,16.8637 11.5597,17.009 12,17.009C12.4403,17.009 12.8682,16.8637 13.2175,16.5957C13.5668,16.3277 13.8179,15.9519 13.9319,15.5266C14.0458,15.1013 14.0162,14.6504 13.8478,14.2437C13.6793,13.8369 13.3813,13.4972 13,13.2771V11H18V18H6Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_blinds_on.xml b/packages/SystemUI/res/drawable/ic_device_blinds_on.xml
new file mode 100644
index 0000000..8166274
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_blinds_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,18V4H4V18H2V20H22V18H20ZM6,18V11H11V13.2771C10.6187,13.4972 10.3207,13.8369 10.1522,14.2437C9.9838,14.6504 9.9542,15.1013 10.0681,15.5266C10.1821,15.9519 10.4332,16.3277 10.7825,16.5957C11.1318,16.8637 11.5597,17.009 12,17.009C12.4403,17.009 12.8682,16.8637 13.2175,16.5957C13.5668,16.3277 13.8179,15.9519 13.9319,15.5266C14.0458,15.1013 14.0162,14.6504 13.8478,14.2437C13.6793,13.8369 13.3813,13.4972 13,13.2771V11H18V18H6Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_camera_off.xml b/packages/SystemUI/res/drawable/ic_device_camera_off.xml
new file mode 100644
index 0000000..32cad14
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_camera_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,10.48V6C17.9984,5.47 17.7872,4.9624 17.4125,4.5876C17.0377,4.2129 16.5299,4.0016 16,4H4C3.4701,4.0016 2.9623,4.2129 2.5875,4.5876C2.2128,4.9624 2.0016,5.47 2,6V18C2.0016,18.5299 2.2128,19.0376 2.5875,19.4124C2.9623,19.7871 3.4701,19.9984 4,20H16C16.5299,19.9984 17.0377,19.7871 17.4125,19.4124C17.7872,19.0376 17.9984,18.5299 18,18V13.52L22,17.5V6.5L18,10.48ZM16,9.6899V18H4V6H16V9.6899Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_camera_on.xml b/packages/SystemUI/res/drawable/ic_device_camera_on.xml
new file mode 100644
index 0000000..93c50f0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_camera_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,10.48V6C17.9984,5.47 17.7872,4.9624 17.4125,4.5876C17.0377,4.2129 16.5299,4.0016 16,4H4C3.4701,4.0016 2.9623,4.2129 2.5875,4.5876C2.2128,4.9624 2.0016,5.47 2,6V18C2.0016,18.5299 2.2128,19.0376 2.5875,19.4124C2.9623,19.7871 3.4701,19.9984 4,20H16C16.5299,19.9984 17.0377,19.7871 17.4125,19.4124C17.7872,19.0376 17.9984,18.5299 18,18V13.52L22,17.5V6.5L18,10.48Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_dishwasher_off.xml b/packages/SystemUI/res/drawable/ic_device_dishwasher_off.xml
new file mode 100644
index 0000000..16ad90b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_dishwasher_off.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,2.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2335,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9905 4.1504,3.2335C4.0502,3.4766 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5234 4.1504,20.7665C4.2505,21.0096 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2335,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0096 19.8496,20.7665C19.9498,20.5234 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.7728 19.4151,2.5878C19.2291,2.4027 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM18,20H6L5.993,4H18V20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M11,7C11.5523,7 12,6.5523 12,6C12,5.4477 11.5523,5 11,5C10.4477,5 10,5.4477 10,6C10,6.5523 10.4477,7 11,7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8,7C8.5523,7 9,6.5523 9,6C9,5.4477 8.5523,5 8,5C7.4477,5 7,5.4477 7,6C7,6.5523 7.4477,7 8,7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8.211,14.272C8.2337,15.2618 8.6429,16.2035 9.351,16.8955C10.0591,17.5875 11.0099,17.975 12,17.975C12.9901,17.975 13.9409,17.5875 14.649,16.8955C15.3571,16.2035 15.7663,15.2618 15.789,14.272C15.7891,13.7805 15.6908,13.2941 15.5,12.8412C15.3092,12.3883 15.0297,11.9782 14.678,11.635L12,9L9.322,11.635C8.9703,11.9782 8.6908,12.3883 8.5,12.8412C8.3092,13.2941 8.2109,13.7805 8.211,14.272ZM10.724,13.061L12,11.806L13.276,13.061C13.4381,13.2184 13.567,13.4065 13.6551,13.6145C13.7432,13.8225 13.7888,14.0461 13.789,14.272C13.7735,14.7361 13.5782,15.1761 13.2444,15.4989C12.9106,15.8217 12.4644,16.0022 12,16.0022C11.5356,16.0022 11.0894,15.8217 10.7556,15.4989C10.4218,15.1761 10.2265,14.7361 10.211,14.272C10.2111,14.0461 10.2566,13.8225 10.3447,13.6145C10.4328,13.4065 10.5618,13.2183 10.724,13.061Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_dishwasher_on.xml b/packages/SystemUI/res/drawable/ic_device_dishwasher_on.xml
new file mode 100644
index 0000000..63f99ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_dishwasher_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,2.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2335,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9905 4.1504,3.2335C4.0502,3.4766 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5234 4.1504,20.7665C4.2505,21.0096 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2335,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0096 19.8496,20.7665C19.9498,20.5234 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.7728 19.4151,2.5878C19.2291,2.4027 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM11,5C11.1978,5 11.3911,5.0587 11.5556,5.1686C11.72,5.2785 11.8482,5.4346 11.9239,5.6173C11.9996,5.8 12.0194,6.0011 11.9808,6.1951C11.9422,6.3891 11.847,6.5673 11.7071,6.7072C11.5673,6.847 11.3891,6.9423 11.1951,6.9809C11.0011,7.0194 10.8,6.9995 10.6173,6.9238C10.4346,6.8481 10.2784,6.72 10.1685,6.5556C10.0586,6.3911 10,6.1978 10,6C10,5.7348 10.1054,5.4804 10.2929,5.2929C10.4804,5.1053 10.7348,5 11,5ZM7,6C7,5.8022 7.0587,5.6089 7.1685,5.4445C7.2784,5.28 7.4346,5.1519 7.6173,5.0762C7.8,5.0005 8.0011,4.9806 8.1951,5.0192C8.3891,5.0578 8.5673,5.153 8.7071,5.2929C8.847,5.4327 8.9422,5.611 8.9808,5.8049C9.0194,5.9989 8.9996,6.2 8.9239,6.3827C8.8482,6.5654 8.72,6.7215 8.5556,6.8314C8.3911,6.9413 8.1978,7 8,7C7.7348,7 7.4804,6.8947 7.2929,6.7072C7.1054,6.5196 7,6.2652 7,6ZM12,18C11.0032,18.008 10.0441,17.6198 9.3335,16.9207C8.623,16.2216 8.2192,15.2688 8.211,14.272C8.2109,13.7806 8.3092,13.2941 8.5,12.8412C8.6908,12.3883 8.9703,11.9782 9.322,11.635L12,9L14.678,11.635C15.0297,11.9782 15.3092,12.3883 15.5,12.8412C15.6908,13.2941 15.7891,13.7806 15.789,14.272C15.7808,15.2688 15.377,16.2216 14.6665,16.9207C13.9559,17.6198 12.9968,18.008 12,18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_doorbell_off.xml b/packages/SystemUI/res/drawable/ic_device_doorbell_off.xml
new file mode 100644
index 0000000..6c03a4b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_doorbell_off.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M17,2H7C6.4696,2 5.9609,2.2106 5.5858,2.5857C5.2107,2.9608 5,3.4696 5,4V20C5,20.5304 5.2107,21.0392 5.5858,21.4143C5.9609,21.7894 6.4696,22 7,22H17C17.5304,22 18.0391,21.7894 18.4142,21.4143C18.7893,21.0392 19,20.5304 19,20V4C19,3.4696 18.7893,2.9608 18.4142,2.5857C18.0391,2.2106 17.5304,2 17,2ZM17,20H7V4H17V20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,15C11.6044,15 11.2177,15.1174 10.8889,15.3372C10.56,15.5569 10.3036,15.8692 10.1522,16.2346C10.0009,16.6001 9.9613,17.0022 10.0384,17.3901C10.1156,17.7781 10.3061,18.1346 10.5858,18.4143C10.8655,18.694 11.2219,18.8845 11.6098,18.9617C11.9978,19.0388 12.3999,18.999 12.7654,18.8477C13.1308,18.6963 13.4432,18.44 13.6629,18.1111C13.8827,17.7822 14,17.3956 14,17C14,16.4696 13.7893,15.9608 13.4142,15.5857C13.0391,15.2106 12.5304,15 12,15ZM12,18C11.8022,18 11.6089,17.9414 11.4444,17.8315C11.28,17.7217 11.1518,17.5653 11.0761,17.3826C11.0004,17.1998 10.9806,16.9989 11.0192,16.8049C11.0578,16.611 11.153,16.4328 11.2929,16.293C11.4327,16.1531 11.6109,16.0579 11.8049,16.0193C11.9989,15.9807 12.2,16.0005 12.3827,16.0762C12.5654,16.1519 12.7216,16.2799 12.8315,16.4443C12.9413,16.6088 13,16.8022 13,17C13,17.2652 12.8946,17.5195 12.7071,17.707C12.5196,17.8946 12.2652,18 12,18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M13,12.5H11C11,12.7652 11.1054,13.0195 11.2929,13.207C11.4804,13.3946 11.7348,13.5 12,13.5C12.2652,13.5 12.5196,13.3946 12.7071,13.207C12.8946,13.0195 13,12.7652 13,12.5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,11H15V8.6599C15.0532,7.9533 14.8572,7.2506 14.4462,6.6733C14.0352,6.0961 13.4351,5.6809 12.75,5.5V5.25C12.75,5.0511 12.671,4.8604 12.5303,4.7197C12.3897,4.5791 12.1989,4.5 12,4.5C11.8011,4.5 11.6103,4.5791 11.4697,4.7197C11.329,4.8604 11.25,5.0511 11.25,5.25V5.5C10.5659,5.6827 9.9669,6.0982 9.5562,6.675C9.1455,7.2519 8.9488,7.9537 9,8.6599V11H8V12H16V11Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_doorbell_on.xml b/packages/SystemUI/res/drawable/ic_device_doorbell_on.xml
new file mode 100644
index 0000000..d08393a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_doorbell_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,18C12.5523,18 13,17.5523 13,17C13,16.4477 12.5523,16 12,16C11.4477,16 11,16.4477 11,17C11,17.5523 11.4477,18 12,18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17,2H7C6.4696,2 5.9609,2.2106 5.5858,2.5857C5.2107,2.9608 5,3.4696 5,4V20C5,20.5304 5.2107,21.0392 5.5858,21.4143C5.9609,21.7894 6.4696,22 7,22H17C17.5304,22 18.0391,21.7894 18.4142,21.4143C18.7893,21.0392 19,20.5304 19,20V4C19,3.4696 18.7893,2.9608 18.4142,2.5857C18.0391,2.2106 17.5304,2 17,2ZM12,19C11.6044,19 11.2178,18.8826 10.8889,18.6628C10.56,18.4431 10.3036,18.1308 10.1522,17.7654C10.0009,17.3999 9.9613,16.9978 10.0384,16.6099C10.1156,16.2219 10.3061,15.8654 10.5858,15.5857C10.8655,15.306 11.2219,15.1155 11.6098,15.0383C11.9978,14.9612 12.3999,15.001 12.7654,15.1523C13.1308,15.3037 13.4432,15.56 13.6629,15.8889C13.8827,16.2178 14,16.6044 14,17C14,17.5304 13.7893,18.0392 13.4142,18.4143C13.0391,18.7894 12.5304,19 12,19ZM11,12.5H13C13,12.7652 12.8946,13.0195 12.7071,13.207C12.5196,13.3946 12.2652,13.5 12,13.5C11.7348,13.5 11.4804,13.3946 11.2929,13.207C11.1054,13.0195 11,12.7652 11,12.5ZM16,12H8V11H9V8.6599C8.9488,7.9537 9.1455,7.2519 9.5562,6.675C9.9669,6.0982 10.5659,5.6827 11.25,5.5V5.25C11.25,5.0511 11.329,4.8604 11.4697,4.7197C11.6103,4.5791 11.8011,4.5 12,4.5C12.1989,4.5 12.3897,4.5791 12.5303,4.7197C12.671,4.8604 12.75,5.0511 12.75,5.25V5.5C13.4351,5.6809 14.0352,6.0961 14.4462,6.6733C14.8572,7.2506 15.0532,7.9533 15,8.6599V11H16V12Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_drawer_off.xml b/packages/SystemUI/res/drawable/ic_device_drawer_off.xml
new file mode 100644
index 0000000..bcab534
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_drawer_off.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,3H6C5.4696,3 4.9609,3.2109 4.5858,3.5859C4.2107,3.961 4,4.4696 4,5V21H6V19H18V21H20V5C20,4.4696 19.7893,3.961 19.4142,3.5859C19.0391,3.2109 18.5304,3 18,3ZM18,11H13V9H18V11ZM18,7H13V5H18V7ZM11,5V11H6V5H11ZM6,17V13H18V17H6Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,14H10V16H14V14Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_drawer_on.xml b/packages/SystemUI/res/drawable/ic_device_drawer_on.xml
new file mode 100644
index 0000000..800e9f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_drawer_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,3H6C5.4696,3 4.9609,3.2109 4.5858,3.5859C4.2107,3.961 4,4.4696 4,5V21H6V19H18V21H20V5C20,4.4696 19.7893,3.961 19.4142,3.5859C19.0391,3.2109 18.5304,3 18,3ZM6,5H11V11H6V5ZM14,16H10V14H14V16ZM18,11H13V9H18V11ZM18,7H13V5H18V7Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_fan_off.xml b/packages/SystemUI/res/drawable/ic_device_fan_off.xml
new file mode 100644
index 0000000..c90d574
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_fan_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16.345,8.3611L14.055,9.1791C13.8731,9.0458 13.6785,8.9309 13.474,8.8361C13.6398,7.9956 14.1302,7.2543 14.839,6.7731C15.3079,6.465 15.6646,6.0136 15.8558,5.4861C16.047,4.9587 16.0625,4.3836 15.8999,3.8466C15.7374,3.3097 15.4055,2.8397 14.9538,2.5069C14.5022,2.1741 13.955,1.9963 13.394,2.0001C8.994,2.0001 7.157,5.0071 8.361,7.6551L9.179,9.9451C9.0458,10.1269 8.9309,10.3215 8.836,10.5261C7.9954,10.3606 7.254,9.8701 6.773,9.1611C6.465,8.6922 6.0135,8.3355 5.4861,8.1443C4.9587,7.9531 4.3835,7.9375 3.8466,8.1001C3.3096,8.2627 2.8396,8.5946 2.5068,9.0462C2.174,9.4979 1.9962,10.0451 2,10.6061C2,15.0061 5.007,16.843 7.655,15.639L9.945,14.821C10.1267,14.9541 10.3209,15.069 10.525,15.1641C10.3598,16.0048 9.8692,16.7463 9.16,17.227C8.691,17.5351 8.3343,17.9867 8.1431,18.5142C7.9519,19.0418 7.9365,19.617 8.0992,20.154C8.2619,20.691 8.5939,21.161 9.0457,21.4937C9.4976,21.8264 10.0449,22.004 10.606,22.0001C15.006,22.0001 16.843,18.993 15.639,16.345L14.821,14.0551C14.954,13.8734 15.0689,13.6791 15.164,13.475C16.0048,13.6402 16.7462,14.1309 17.227,14.8401C17.5351,15.3091 17.9866,15.6657 18.5141,15.8569C19.0417,16.0481 19.6169,16.0636 20.1539,15.9009C20.6909,15.7382 21.1609,15.4061 21.4936,14.9543C21.8264,14.5025 22.004,13.9551 22,13.394C22,9 18.993,7.1571 16.345,8.3611ZM12,13.5001C11.7033,13.5001 11.4133,13.4121 11.1666,13.2473C10.92,13.0824 10.7277,12.8482 10.6142,12.5741C10.5006,12.3 10.4709,11.9984 10.5288,11.7074C10.5867,11.4164 10.7296,11.1492 10.9393,10.9394C11.1491,10.7296 11.4164,10.5867 11.7074,10.5289C11.9983,10.471 12.2999,10.5007 12.574,10.6143C12.8481,10.7278 13.0824,10.92 13.2472,11.1667C13.412,11.4134 13.5,11.7034 13.5,12.0001C13.5,12.3979 13.342,12.7794 13.0607,13.0607C12.7793,13.342 12.3978,13.5001 12,13.5001ZM10.245,5.2161C10.6327,4.7742 11.1217,4.4328 11.6701,4.2211C12.2184,4.0093 12.8099,3.9335 13.394,4.0001C13.5259,3.9959 13.6555,4.0354 13.7627,4.1124C13.8699,4.1893 13.9487,4.2995 13.987,4.4258C14.0253,4.5521 14.0208,4.6875 13.9744,4.811C13.9279,4.9346 13.842,5.0393 13.73,5.1091C13.1418,5.5017 12.6392,6.0092 12.2521,6.601C11.8651,7.1929 11.6018,7.8568 11.478,8.553C11.2666,8.5847 11.0587,8.6362 10.857,8.707L10.181,6.8271C10.0515,6.576 9.9893,6.2955 10.0005,6.0131C10.0117,5.7308 10.0959,5.4561 10.245,5.2161ZM6.827,13.816C6.576,13.9458 6.2956,14.0083 6.0132,13.9973C5.7308,13.9862 5.4561,13.902 5.216,13.753C4.7745,13.3655 4.4332,12.8769 4.2215,12.3289C4.0098,11.7809 3.9338,11.1898 4,10.6061C3.9959,10.4742 4.0353,10.3446 4.1123,10.2374C4.1893,10.1302 4.2994,10.0513 4.4257,10.0131C4.552,9.9748 4.6874,9.9792 4.8109,10.0257C4.9345,10.0722 5.0392,10.1581 5.109,10.2701C5.5015,10.8581 6.0088,11.3607 6.6005,11.7477C7.1922,12.1347 7.8559,12.3981 8.552,12.522C8.5844,12.7334 8.6363,12.9413 8.707,13.1431L6.827,13.816ZM13.755,18.782C13.3675,19.2242 12.8786,19.566 12.3302,19.7781C11.7818,19.9902 11.1902,20.0664 10.606,20.0001C10.4741,20.0042 10.3445,19.9647 10.2373,19.8878C10.1301,19.8108 10.0512,19.7006 10.013,19.5743C9.9747,19.448 9.9791,19.3126 10.0256,19.1891C10.0721,19.0656 10.158,18.9608 10.27,18.8911C10.8581,18.4987 11.3606,17.9914 11.7475,17.3997C12.1343,16.808 12.3974,16.1441 12.521,15.4481C12.7327,15.4156 12.9409,15.3638 13.143,15.2931L13.818,17.173C13.9477,17.4241 14.0101,17.7045 13.999,17.9869C13.988,18.2692 13.9039,18.5439 13.755,18.7841V18.782ZM18.891,13.7281C18.4985,13.1399 17.991,12.6373 17.3992,12.2504C16.8073,11.8636 16.1432,11.6005 15.447,11.477C15.4154,11.2653 15.3639,11.057 15.293,10.855L17.173,10.1801C17.424,10.0503 17.7044,9.9879 17.9868,9.9989C18.2692,10.0099 18.5439,10.094 18.784,10.243C19.2261,10.631 19.5677,11.1202 19.7795,11.669C19.9912,12.2178 20.0669,12.8097 20,13.394C20.0041,13.5259 19.9647,13.6555 19.8877,13.7628C19.8107,13.87 19.7006,13.9488 19.5743,13.9871C19.448,14.0253 19.3126,14.0209 19.1891,13.9744C19.0655,13.928 18.9608,13.8421 18.891,13.73V13.7281Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_fan_on.xml b/packages/SystemUI/res/drawable/ic_device_fan_on.xml
new file mode 100644
index 0000000..79950ea
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_fan_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16.345,8.3611L14.055,9.1791C13.8731,9.0458 13.6785,8.9309 13.474,8.8361C13.6398,7.9956 14.1302,7.2543 14.839,6.7731C15.3079,6.465 15.6646,6.0136 15.8558,5.4861C16.047,4.9587 16.0625,4.3836 15.8999,3.8466C15.7374,3.3097 15.4055,2.8397 14.9538,2.5069C14.5022,2.1741 13.955,1.9963 13.394,2.0001C8.994,2.0001 7.157,5.0071 8.361,7.6551L9.179,9.9451C9.0457,10.1269 8.9309,10.3215 8.836,10.5261C7.9954,10.3606 7.254,9.8701 6.773,9.1611C6.465,8.6922 6.0135,8.3355 5.4861,8.1443C4.9587,7.9531 4.3835,7.9375 3.8466,8.1001C3.3096,8.2627 2.8396,8.5946 2.5068,9.0462C2.174,9.4979 1.9962,10.0451 2,10.6061C2,15.0061 5.007,16.843 7.655,15.639L9.945,14.821C10.1267,14.9541 10.3209,15.069 10.525,15.1641C10.3598,16.0048 9.8692,16.7463 9.16,17.227C8.691,17.5351 8.3343,17.9867 8.1431,18.5142C7.9519,19.0418 7.9365,19.617 8.0992,20.154C8.2619,20.691 8.5939,21.161 9.0457,21.4937C9.4976,21.8264 10.0449,22.004 10.606,22.0001C15.006,22.0001 16.843,18.993 15.639,16.345L14.821,14.0551C14.954,13.8734 15.0689,13.6791 15.164,13.475C16.0048,13.6402 16.7462,14.1309 17.227,14.8401C17.5351,15.3091 17.9866,15.6657 18.5141,15.8569C19.0417,16.0481 19.6169,16.0636 20.1539,15.9009C20.6909,15.7382 21.1609,15.4061 21.4936,14.9543C21.8264,14.5025 22.004,13.9551 22,13.394C22,9 18.993,7.1571 16.345,8.3611ZM12,13.5001C11.7033,13.5001 11.4133,13.4121 11.1666,13.2473C10.92,13.0824 10.7277,12.8482 10.6142,12.5741C10.5006,12.3 10.4709,11.9984 10.5288,11.7074C10.5867,11.4164 10.7296,11.1492 10.9393,10.9394C11.1491,10.7296 11.4164,10.5867 11.7074,10.5289C11.9983,10.471 12.2999,10.5007 12.574,10.6143C12.8481,10.7278 13.0824,10.92 13.2472,11.1667C13.412,11.4134 13.5,11.7034 13.5,12.0001C13.5,12.3979 13.342,12.7794 13.0607,13.0607C12.7794,13.342 12.3978,13.5001 12,13.5001Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_garage_off.xml b/packages/SystemUI/res/drawable/ic_device_garage_off.xml
new file mode 100644
index 0000000..8865983
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_garage_off.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,9L12,3L4,9V21H6V10L12,5.5L18,10V21H20V9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M7,11V21H17V11H7ZM15,13V15H9V13H15ZM9,19V17H15V19H9Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_garage_on.xml b/packages/SystemUI/res/drawable/ic_device_garage_on.xml
new file mode 100644
index 0000000..8865983
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_garage_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,9L12,3L4,9V21H6V10L12,5.5L18,10V21H20V9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M7,11V21H17V11H7ZM15,13V15H9V13H15ZM9,19V17H15V19H9Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_gate_off.xml b/packages/SystemUI/res/drawable/ic_device_gate_off.xml
new file mode 100644
index 0000000..9f7d9ed
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_gate_off.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M4,7H2V17H4V7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,5H9C7.9391,5 6.9217,5.4215 6.1716,6.1716C5.4214,6.9218 5,7.9391 5,9V19H19V9C19,7.9391 18.5786,6.9218 17.8284,6.1716C17.0783,5.4215 16.0609,5 15,5ZM7,9C7,8.4696 7.2107,7.9608 7.5858,7.5857C7.9609,7.2106 8.4696,7 9,7H11V11H9V13H11V17H7V9ZM17,17H13V13H15V11H13V7H15C15.5304,7 16.0391,7.2106 16.4142,7.5857C16.7893,7.9608 17,8.4696 17,9V17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M22,7H20V17H22V7Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_gate_on.xml b/packages/SystemUI/res/drawable/ic_device_gate_on.xml
new file mode 100644
index 0000000..1a005ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_gate_on.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M4,7H2V17H4V7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M22,7H20V17H22V7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M5,9V19H11V13H9V11H11V5H9C7.9391,5 6.9217,5.4215 6.1716,6.1716C5.4214,6.9218 5,7.9391 5,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,5H13V11H15V13H13V19H19V9C19,7.9391 18.5786,6.9218 17.8284,6.1716C17.0783,5.4215 16.0609,5 15,5Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_hood_off.xml b/packages/SystemUI/res/drawable/ic_device_hood_off.xml
new file mode 100644
index 0000000..71d5f24
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_hood_off.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M21.414,12.414L17,8V3H7V8L2.586,12.414C2.2109,12.789 2.0001,13.2976 2,13.828V18C2,18.5304 2.2107,19.0391 2.5858,19.4142C2.9609,19.7893 3.4696,20 4,20H20C20.5304,20 21.0391,19.7893 21.4142,19.4142C21.7893,19.0391 22,18.5304 22,18V13.828C21.9999,13.2976 21.7891,12.789 21.414,12.414ZM9,8.828V5H15V8.828L18.172,12H5.828L9,8.828ZM20,18H4V14H20V18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,15.25H10V16.75H14V15.25Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_hood_on.xml b/packages/SystemUI/res/drawable/ic_device_hood_on.xml
new file mode 100644
index 0000000..721e68b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_hood_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M21,12L17,8V3H7V8L3,12H21Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M2,14V18C2,18.5304 2.2107,19.0391 2.5858,19.4142C2.9609,19.7893 3.4696,20 4,20H20C20.5304,20 21.0391,19.7893 21.4142,19.4142C21.7893,19.0391 22,18.5304 22,18V14H2ZM14,16.75H10V15.25H14V16.75Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_kettle_off.xml b/packages/SystemUI/res/drawable/ic_device_kettle_off.xml
new file mode 100644
index 0000000..94ad254
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_kettle_off.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,5H18V2H3L6,6V19H18V14H20C20.5304,14 21.0391,13.7893 21.4142,13.4142C21.7893,13.0391 22,12.5304 22,12V7C22,6.4696 21.7893,5.9609 21.4142,5.5858C21.0391,5.2107 20.5304,5 20,5ZM16,17H8V5.333L7,4H16V17ZM20,12H18V7H20V12Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,5H12V16H15V5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M21,20H3V22H21V20Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_kettle_on.xml b/packages/SystemUI/res/drawable/ic_device_kettle_on.xml
new file mode 100644
index 0000000..11081e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_kettle_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,5H18V2H3L6,6V19H18V14H20C20.5304,14 21.0391,13.7893 21.4142,13.4142C21.7893,13.0391 22,12.5304 22,12V7C22,6.4696 21.7893,5.9609 21.4142,5.5858C21.0391,5.2107 20.5304,5 20,5ZM15,16H12V5H15V16ZM20,12H18V7H20V12Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M21,20H3V22H21V20Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_light_off.xml b/packages/SystemUI/res/drawable/ic_device_light_off.xml
new file mode 100644
index 0000000..62fa631
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_light_off.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,22C12.5304,22 13.0391,21.7894 13.4142,21.4143C13.7893,21.0392 14,20.5304 14,20H10C10,20.5304 10.2107,21.0392 10.5858,21.4143C10.9609,21.7894 11.4696,22 12,22Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,17H8V19H16V17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,2C10.3491,2.0023 8.7451,2.5493 7.4367,3.5561C6.1283,4.563 5.1887,5.9734 4.7636,7.5686C4.3385,9.1638 4.4516,10.8547 5.0854,12.3792C5.7191,13.9036 6.8382,15.1764 8.269,16H15.731C17.1618,15.1764 18.2809,13.9036 18.9147,12.3792C19.5485,10.8547 19.6616,9.1638 19.2364,7.5686C18.8113,5.9734 17.8717,4.563 16.5633,3.5561C15.2549,2.5493 13.6509,2.0023 12,2ZM15.148,14H8.848C8.1191,13.4982 7.5239,12.826 7.114,12.0417C6.7041,11.2575 6.4919,10.3849 6.496,9.5C6.496,8.0413 7.0755,6.6423 8.1069,5.6108C9.1384,4.5794 10.5373,4 11.996,4C13.4547,4 14.8536,4.5794 15.8851,5.6108C16.9165,6.6423 17.496,8.0413 17.496,9.5C17.5005,10.3846 17.289,11.2568 16.8798,12.041C16.4706,12.8252 15.8761,13.4977 15.148,14Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_light_on.xml b/packages/SystemUI/res/drawable/ic_device_light_on.xml
new file mode 100644
index 0000000..08f05fc
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_light_on.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,22C12.5304,22 13.0391,21.7894 13.4142,21.4143C13.7893,21.0392 14,20.5304 14,20H10C10,20.5304 10.2107,21.0392 10.5858,21.4143C10.9609,21.7894 11.4696,22 12,22Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,17H8V19H16V17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,2C10.3491,2.0023 8.7451,2.5493 7.4367,3.5561C6.1283,4.563 5.1887,5.9734 4.7636,7.5686C4.3385,9.1638 4.4516,10.8547 5.0854,12.3792C5.7191,13.9036 6.8382,15.1764 8.269,16H15.731C17.1618,15.1764 18.2809,13.9036 18.9147,12.3792C19.5485,10.8547 19.6616,9.1638 19.2364,7.5686C18.8113,5.9734 17.8717,4.563 16.5633,3.5561C15.2549,2.5493 13.6509,2.0023 12,2Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_lock_off.xml b/packages/SystemUI/res/drawable/ic_device_lock_off.xml
new file mode 100644
index 0000000..a2662ff
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_lock_off.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,8H17V6C17,4.6739 16.4732,3.402 15.5355,2.4644C14.5979,1.5267 13.3261,1 12,1C10.6739,1 9.4021,1.5267 8.4645,2.4644C7.5268,3.402 7,4.6739 7,6V8H6C5.47,8.0016 4.9623,8.2127 4.5875,8.5874C4.2128,8.9621 4.0016,9.47 4,10V20C4.0016,20.5299 4.2128,21.0379 4.5875,21.4126C4.9623,21.7873 5.47,21.9984 6,22H18C18.5299,21.9984 19.0377,21.7873 19.4125,21.4126C19.7872,21.0379 19.9984,20.5299 20,20V10C19.9984,9.47 19.7872,8.9621 19.4125,8.5874C19.0377,8.2127 18.5299,8.0016 18,8ZM9,6C9,5.2043 9.3161,4.4415 9.8787,3.8789C10.4413,3.3163 11.2044,3 12,3C12.7956,3 13.5587,3.3163 14.1213,3.8789C14.6839,4.4415 15,5.2043 15,6V8H9V6ZM18,20H6V10H18V20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,17C13.1046,17 14,16.1046 14,15C14,13.8954 13.1046,13 12,13C10.8954,13 10,13.8954 10,15C10,16.1046 10.8954,17 12,17Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_lock_on.xml b/packages/SystemUI/res/drawable/ic_device_lock_on.xml
new file mode 100644
index 0000000..5ae7090a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_lock_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,8H17V6C17,4.6739 16.4732,3.402 15.5355,2.4644C14.5979,1.5267 13.3261,1 12,1C10.6739,1 9.4022,1.5267 8.4645,2.4644C7.5268,3.402 7,4.6739 7,6V8H6C5.47,8.0016 4.9623,8.2127 4.5875,8.5874C4.2128,8.9621 4.0016,9.47 4,10V20C4.0016,20.5299 4.2128,21.0379 4.5875,21.4126C4.9623,21.7873 5.47,21.9984 6,22H18C18.5299,21.9984 19.0377,21.7873 19.4125,21.4126C19.7872,21.0379 19.9984,20.5299 20,20V10C19.9984,9.47 19.7872,8.9621 19.4125,8.5874C19.0377,8.2127 18.5299,8.0016 18,8ZM12,17C11.6044,17 11.2178,16.8828 10.8889,16.6631C10.56,16.4433 10.3036,16.1306 10.1522,15.7651C10.0009,15.3997 9.9613,14.9978 10.0384,14.6099C10.1156,14.2219 10.3061,13.8656 10.5858,13.5859C10.8655,13.3062 11.2219,13.1157 11.6098,13.0386C11.9978,12.9614 12.3999,13.001 12.7654,13.1523C13.1308,13.3037 13.4432,13.5598 13.6629,13.8887C13.8827,14.2176 14,14.6044 14,15C13.9984,15.5299 13.7872,16.0379 13.4125,16.4126C13.0377,16.7873 12.5299,16.9984 12,17ZM15,8H9V6C9,5.2043 9.3161,4.4415 9.8787,3.8789C10.4413,3.3163 11.2044,3 12,3C12.7956,3 13.5587,3.3163 14.1213,3.8789C14.6839,4.4415 15,5.2043 15,6V8Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_microwave_off.xml b/packages/SystemUI/res/drawable/ic_device_microwave_off.xml
new file mode 100644
index 0000000..771afbb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_microwave_off.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,4H4C3.4696,4 2.9609,4.2107 2.5858,4.5858C2.2107,4.9609 2,5.4696 2,6V18C2,18.5304 2.2107,19.0391 2.5858,19.4142C2.9609,19.7893 3.4696,20 4,20H20C20.5304,20 21.0391,19.7893 21.4142,19.4142C21.7893,19.0391 22,18.5304 22,18V6C22,5.4696 21.7893,4.9609 21.4142,4.5858C21.0391,4.2107 20.5304,4 20,4ZM20,18H4V6H20V18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18,9C18.5523,9 19,8.5523 19,8C19,7.4477 18.5523,7 18,7C17.4477,7 17,7.4477 17,8C17,8.5523 17.4477,9 18,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18,13C18.5523,13 19,12.5523 19,12C19,11.4477 18.5523,11 18,11C17.4477,11 17,11.4477 17,12C17,12.5523 17.4477,13 18,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18,17C18.5523,17 19,16.5523 19,16C19,15.4477 18.5523,15 18,15C17.4477,15 17,15.4477 17,16C17,16.5523 17.4477,17 18,17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,7H5V17H15V7ZM13,15H7V9H13V15Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_microwave_on.xml b/packages/SystemUI/res/drawable/ic_device_microwave_on.xml
new file mode 100644
index 0000000..b05f681
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_microwave_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,4H4C3.4696,4 2.9609,4.2107 2.5858,4.5858C2.2107,4.9609 2,5.4696 2,6V18C2,18.5304 2.2107,19.0391 2.5858,19.4142C2.9609,19.7893 3.4696,20 4,20H20C20.5304,20 21.0391,19.7893 21.4142,19.4142C21.7893,19.0391 22,18.5304 22,18V6C22,5.4696 21.7893,4.9609 21.4142,4.5858C21.0391,4.2107 20.5304,4 20,4ZM15,17H5V7H15V17ZM18,17C17.8022,17 17.6089,16.9413 17.4444,16.8314C17.28,16.7215 17.1518,16.5654 17.0761,16.3827C17.0004,16.2 16.9806,15.9989 17.0192,15.8049C17.0578,15.611 17.153,15.4327 17.2929,15.2928C17.4327,15.153 17.6109,15.0578 17.8049,15.0192C17.9989,14.9806 18.2,15.0005 18.3827,15.0762C18.5654,15.1519 18.7216,15.28 18.8315,15.4445C18.9414,15.6089 19,15.8022 19,16C19,16.2652 18.8946,16.5196 18.7071,16.7072C18.5196,16.8947 18.2652,17 18,17ZM18,13C17.8022,13 17.6089,12.9413 17.4444,12.8314C17.28,12.7215 17.1518,12.5654 17.0761,12.3827C17.0004,12.2 16.9806,11.9989 17.0192,11.8049C17.0578,11.611 17.153,11.4327 17.2929,11.2928C17.4327,11.153 17.6109,11.0578 17.8049,11.0192C17.9989,10.9806 18.2,11.0005 18.3827,11.0762C18.5654,11.1519 18.7216,11.28 18.8315,11.4445C18.9414,11.6089 19,11.8022 19,12C19,12.2652 18.8946,12.5196 18.7071,12.7072C18.5196,12.8947 18.2652,13 18,13ZM18,9C17.8022,9 17.6089,8.9413 17.4444,8.8314C17.28,8.7215 17.1518,8.5654 17.0761,8.3827C17.0004,8.2 16.9806,7.9989 17.0192,7.8049C17.0578,7.6109 17.153,7.4327 17.2929,7.2929C17.4327,7.153 17.6109,7.0578 17.8049,7.0192C17.9989,6.9806 18.2,7.0005 18.3827,7.0762C18.5654,7.1519 18.7216,7.28 18.8315,7.4445C18.9414,7.6089 19,7.8022 19,8C19,8.2652 18.8946,8.5196 18.7071,8.7072C18.5196,8.8947 18.2652,9 18,9Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_mop_off.xml b/packages/SystemUI/res/drawable/ic_device_mop_off.xml
new file mode 100644
index 0000000..7fdaaea
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_mop_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M22.379,20.515L21,15V13C21,12.4696 20.7893,11.9609 20.4142,11.5858C20.0391,11.2107 19.5304,11 19,11H15V4C15,3.2043 14.6839,2.4413 14.1213,1.8787C13.5587,1.3161 12.7956,1 12,1C11.2043,1 10.4413,1.3161 9.8786,1.8787C9.316,2.4413 9,3.2043 9,4V11H5C4.4695,11 3.9608,11.2107 3.5858,11.5858C3.2107,11.9609 3,12.4696 3,13V15L1.621,20.515C1.5473,20.8099 1.5417,21.1178 1.6048,21.4151C1.6679,21.7125 1.798,21.9916 1.9851,22.2311C2.1722,22.4707 2.4115,22.6645 2.6847,22.7977C2.958,22.9309 3.258,23.0001 3.562,23H20.438C20.742,23.0001 21.042,22.9309 21.3152,22.7977C21.5884,22.6645 21.8277,22.4707 22.0149,22.2311C22.202,21.9916 22.332,21.7125 22.3951,21.4151C22.4582,21.1178 22.4527,20.8099 22.379,20.515ZM11,4C11,3.7348 11.1053,3.4804 11.2929,3.2929C11.4804,3.1054 11.7348,3 12,3C12.2652,3 12.5195,3.1054 12.7071,3.2929C12.8946,3.4804 13,3.7348 13,4V11H11V4ZM5,13H19V15H5V13ZM18,21V19C18,18.7348 17.8946,18.4804 17.7071,18.2929C17.5195,18.1054 17.2652,18 17,18C16.7348,18 16.4804,18.1054 16.2929,18.2929C16.1053,18.4804 16,18.7348 16,19V21H13V19C13,18.7348 12.8946,18.4804 12.7071,18.2929C12.5195,18.1054 12.2652,18 12,18C11.7348,18 11.4804,18.1054 11.2929,18.2929C11.1053,18.4804 11,18.7348 11,19V21H8V19C8,18.7348 7.8946,18.4804 7.7071,18.2929C7.5195,18.1054 7.2652,18 7,18C6.7348,18 6.4804,18.1054 6.2929,18.2929C6.1053,18.4804 6,18.7348 6,19V21H3.562L4.562,17H19.438L20.438,21H18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_mop_on.xml b/packages/SystemUI/res/drawable/ic_device_mop_on.xml
new file mode 100644
index 0000000..8350ca1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_mop_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M22.379,20.515L21,15V13C21,12.4696 20.7893,11.9609 20.4142,11.5858C20.0391,11.2107 19.5304,11 19,11H15V4C15,3.2043 14.6839,2.4413 14.1213,1.8787C13.5587,1.3161 12.7956,1 12,1C11.2043,1 10.4413,1.3161 9.8787,1.8787C9.316,2.4413 9,3.2043 9,4V11H5C4.4695,11 3.9608,11.2107 3.5858,11.5858C3.2107,11.9609 3,12.4696 3,13V15L1.621,20.515C1.5473,20.8099 1.5417,21.1178 1.6048,21.4151C1.6679,21.7125 1.798,21.9916 1.9851,22.2311C2.1722,22.4707 2.4115,22.6645 2.6847,22.7977C2.958,22.9309 3.258,23.0001 3.562,23H20.438C20.742,23.0001 21.042,22.9309 21.3152,22.7977C21.5885,22.6645 21.8277,22.4707 22.0148,22.2311C22.202,21.9916 22.332,21.7125 22.3951,21.4151C22.4582,21.1178 22.4527,20.8099 22.379,20.515ZM18,21V19C18,18.7348 17.8946,18.4804 17.7071,18.2929C17.5195,18.1054 17.2652,18 17,18C16.7348,18 16.4804,18.1054 16.2929,18.2929C16.1053,18.4804 16,18.7348 16,19V21H13V19C13,18.7348 12.8946,18.4804 12.7071,18.2929C12.5195,18.1054 12.2652,18 12,18C11.7348,18 11.4804,18.1054 11.2929,18.2929C11.1053,18.4804 11,18.7348 11,19V21H8V19C8,18.7348 7.8946,18.4804 7.7071,18.2929C7.5195,18.1054 7.2652,18 7,18C6.7348,18 6.4804,18.1054 6.2929,18.2929C6.1053,18.4804 6,18.7348 6,19V21H3.562L4.562,17H19.438L20.438,21H18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_multicooker_off.xml b/packages/SystemUI/res/drawable/ic_device_multicooker_off.xml
new file mode 100644
index 0000000..8a79b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_multicooker_off.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19,5H16V4C16,3.4696 15.7893,2.9609 15.4142,2.5858C15.0391,2.2107 14.5304,2 14,2H10C9.4696,2 8.9609,2.2107 8.5858,2.5858C8.2107,2.9609 8,3.4696 8,4V5H5C4.4696,5 3.9609,5.2107 3.5858,5.5858C3.2107,5.9609 3,6.4696 3,7V19C3,19.5304 3.2107,20.0391 3.5858,20.4142C3.9609,20.7893 4.4696,21 5,21H19C19.5304,21 20.0391,20.7893 20.4142,20.4142C20.7893,20.0391 21,19.5304 21,19V7C21,6.4696 20.7893,5.9609 20.4142,5.5858C20.0391,5.2107 19.5304,5 19,5ZM10,4H14V5H10V4ZM19,19H5V10H7V12C7,12.5304 7.2107,13.0391 7.5858,13.4142C7.9609,13.7893 8.4696,14 9,14H15C15.5304,14 16.0391,13.7893 16.4142,13.4142C16.7893,13.0391 17,12.5304 17,12V10H19V19ZM9,12V10H15V12H9ZM5,8V7H19V8H5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,18C16.5523,18 17,17.5523 17,17C17,16.4477 16.5523,16 16,16C15.4477,16 15,16.4477 15,17C15,17.5523 15.4477,18 16,18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,18C12.5523,18 13,17.5523 13,17C13,16.4477 12.5523,16 12,16C11.4477,16 11,16.4477 11,17C11,17.5523 11.4477,18 12,18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8,18C8.5523,18 9,17.5523 9,17C9,16.4477 8.5523,16 8,16C7.4477,16 7,16.4477 7,17C7,17.5523 7.4477,18 8,18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_multicooker_on.xml b/packages/SystemUI/res/drawable/ic_device_multicooker_on.xml
new file mode 100644
index 0000000..90ede52
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_multicooker_on.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M17,12C17,12.5304 16.7893,13.0391 16.4142,13.4142C16.0391,13.7893 15.5304,14 15,14H9C8.4696,14 7.9609,13.7893 7.5858,13.4142C7.2107,13.0391 7,12.5304 7,12V10H3V19C3,19.5304 3.2107,20.0391 3.5858,20.4142C3.9609,20.7893 4.4696,21 5,21H19C19.5304,21 20.0391,20.7893 20.4142,20.4142C20.7893,20.0391 21,19.5304 21,19V10H17V12ZM8,18C7.8022,18 7.6089,17.9413 7.4444,17.8314C7.28,17.7215 7.1518,17.5654 7.0761,17.3827C7.0004,17.2 6.9806,16.9989 7.0192,16.8049C7.0578,16.611 7.153,16.4327 7.2929,16.2928C7.4328,16.153 7.6109,16.0578 7.8049,16.0192C7.9989,15.9806 8.2,16.0005 8.3827,16.0762C8.5654,16.1519 8.7216,16.28 8.8315,16.4445C8.9413,16.6089 9,16.8022 9,17C9,17.2652 8.8946,17.5196 8.7071,17.7072C8.5196,17.8947 8.2652,18 8,18ZM12,18C11.8022,18 11.6089,17.9413 11.4444,17.8314C11.28,17.7215 11.1518,17.5654 11.0761,17.3827C11.0004,17.2 10.9806,16.9989 11.0192,16.8049C11.0578,16.611 11.153,16.4327 11.2929,16.2928C11.4327,16.153 11.6109,16.0578 11.8049,16.0192C11.9989,15.9806 12.2,16.0005 12.3827,16.0762C12.5654,16.1519 12.7216,16.28 12.8315,16.4445C12.9414,16.6089 13,16.8022 13,17C13,17.2652 12.8946,17.5196 12.7071,17.7072C12.5196,17.8947 12.2652,18 12,18ZM16,18C15.8022,18 15.6089,17.9413 15.4444,17.8314C15.28,17.7215 15.1518,17.5654 15.0761,17.3827C15.0004,17.2 14.9806,16.9989 15.0192,16.8049C15.0578,16.611 15.153,16.4327 15.2929,16.2928C15.4327,16.153 15.6109,16.0578 15.8049,16.0192C15.9989,15.9806 16.2,16.0005 16.3827,16.0762C16.5654,16.1519 16.7216,16.28 16.8315,16.4445C16.9414,16.6089 17,16.8022 17,17C17,17.2652 16.8946,17.5196 16.7071,17.7072C16.5196,17.8947 16.2652,18 16,18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,10H9V12H15V10Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M21,8V7C21,6.4696 20.7893,5.9609 20.4142,5.5858C20.0391,5.2107 19.5304,5 19,5H16V4C16,3.4696 15.7893,2.9609 15.4142,2.5858C15.0391,2.2107 14.5304,2 14,2H10C9.4696,2 8.9609,2.2107 8.5858,2.5858C8.2107,2.9609 8,3.4696 8,4V5H5C4.4696,5 3.9609,5.2107 3.5858,5.5858C3.2107,5.9609 3,6.4696 3,7V8H21ZM10,4H14V5H10V4Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_outlet_off.xml b/packages/SystemUI/res/drawable/ic_device_outlet_off.xml
new file mode 100644
index 0000000..6fe7d12
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_outlet_off.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,2C10.0222,2 8.0888,2.5865 6.4443,3.6853C4.7998,4.7841 3.5181,6.346 2.7612,8.1732C2.0043,10.0005 1.8063,12.0111 2.1922,13.9509C2.578,15.8907 3.5304,17.6725 4.9289,19.071C6.3275,20.4696 8.1093,21.422 10.0491,21.8079C11.9889,22.1937 13.9996,21.9956 15.8268,21.2388C17.6541,20.4819 19.2159,19.2002 20.3147,17.5557C21.4135,15.9112 22,13.9778 22,12C22,9.3478 20.9464,6.8043 19.0711,4.929C17.1957,3.0536 14.6522,2 12,2ZM12,20C10.4178,20 8.871,19.5308 7.5554,18.6517C6.2399,17.7727 5.2145,16.5233 4.609,15.0615C4.0035,13.5997 3.845,11.9912 4.1537,10.4393C4.4624,8.8875 5.2243,7.462 6.3432,6.3431C7.462,5.2243 8.8874,4.4624 10.4393,4.1537C11.9911,3.845 13.5997,4.0035 15.0615,4.609C16.5233,5.2145 17.7727,6.2398 18.6518,7.5554C19.5308,8.871 20,10.4177 20,12C20,14.1217 19.1572,16.1566 17.6569,17.6569C16.1566,19.1572 14.1217,20 12,20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M9,9H7V13H9V9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,15C11.7348,15 11.4804,15.1053 11.2929,15.2928C11.1054,15.4804 11,15.7348 11,16V17H13V16C13,15.7348 12.8946,15.4804 12.7071,15.2928C12.5196,15.1053 12.2652,15 12,15Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17,9H15V13H17V9Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_outlet_on.xml b/packages/SystemUI/res/drawable/ic_device_outlet_on.xml
new file mode 100644
index 0000000..e9d80cf
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_outlet_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,2C10.0222,2 8.0888,2.5865 6.4443,3.6853C4.7998,4.7841 3.5181,6.346 2.7612,8.1732C2.0043,10.0005 1.8063,12.0111 2.1922,13.9509C2.578,15.8907 3.5304,17.6725 4.9289,19.071C6.3275,20.4696 8.1093,21.422 10.0491,21.8079C11.9889,22.1937 13.9996,21.9956 15.8268,21.2388C17.6541,20.4819 19.2159,19.2002 20.3147,17.5557C21.4135,15.9112 22,13.9778 22,12C22,9.3478 20.9464,6.8043 19.0711,4.929C17.1957,3.0536 14.6522,2 12,2ZM9,13H7V9H9V13ZM13,17H11V16C11,15.7348 11.1054,15.4804 11.2929,15.2928C11.4804,15.1053 11.7348,15 12,15C12.2652,15 12.5196,15.1053 12.7071,15.2928C12.8946,15.4804 13,15.7348 13,16V17ZM17,13H15V9H17V13Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_pergola_off.xml b/packages/SystemUI/res/drawable/ic_device_pergola_off.xml
new file mode 100644
index 0000000..b7113dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_pergola_off.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,2C19.7348,2 19.4804,2.1054 19.2929,2.293C19.1054,2.4805 19,2.7348 19,3V4H5V3C5,2.7348 4.8946,2.4805 4.7071,2.293C4.5196,2.1054 4.2652,2 4,2C3.7348,2 3.4804,2.1054 3.2929,2.293C3.1054,2.4805 3,2.7348 3,3V21H5V10H19V21H21V3C21,2.7348 20.8946,2.4805 20.7071,2.293C20.5196,2.1054 20.2652,2 20,2ZM5,8V6H19V8H5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8,18H11V21H13V18H16V16H8V18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_pergola_on.xml b/packages/SystemUI/res/drawable/ic_device_pergola_on.xml
new file mode 100644
index 0000000..b7113dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_pergola_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,2C19.7348,2 19.4804,2.1054 19.2929,2.293C19.1054,2.4805 19,2.7348 19,3V4H5V3C5,2.7348 4.8946,2.4805 4.7071,2.293C4.5196,2.1054 4.2652,2 4,2C3.7348,2 3.4804,2.1054 3.2929,2.293C3.1054,2.4805 3,2.7348 3,3V21H5V10H19V21H21V3C21,2.7348 20.8946,2.4805 20.7071,2.293C20.5196,2.1054 20.2652,2 20,2ZM5,8V6H19V8H5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8,18H11V21H13V18H16V16H8V18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_refrigerator_off.xml b/packages/SystemUI/res/drawable/ic_device_refrigerator_off.xml
new file mode 100644
index 0000000..33ad44c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_refrigerator_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,2.01L6,2C5.4696,2 4.9609,2.2107 4.5858,2.5858C4.2107,2.9609 4,3.4696 4,4V20C4.0016,20.5299 4.2128,21.0377 4.5875,21.4125C4.9623,21.7872 5.47,21.9984 6,22H18C18.5299,21.9984 19.0377,21.7872 19.4125,21.4125C19.7872,21.0377 19.9984,20.5299 20,20V4C19.9999,3.7379 19.948,3.4784 19.8473,3.2363C19.7466,2.9943 19.5991,2.7745 19.4133,2.5896C19.2275,2.4047 19.007,2.2583 18.7645,2.1588C18.5219,2.0594 18.2621,2.0088 18,2.01ZM18,20H6V10.98H18V20ZM18,9H6V4H18V9ZM8,5H10V8H8V5ZM8,12H10V17H8V12Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_refrigerator_on.xml b/packages/SystemUI/res/drawable/ic_device_refrigerator_on.xml
new file mode 100644
index 0000000..fe7a4b6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_refrigerator_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,9V4C20,3.4696 19.7893,2.9609 19.4142,2.5858C19.0391,2.2107 18.5304,2 18,2H6C5.4696,2 4.9609,2.2107 4.5858,2.5858C4.2107,2.9609 4,3.4696 4,4V9H20ZM8,5H10V8H8V5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M4,11V20C4,20.5304 4.2107,21.0391 4.5858,21.4142C4.9609,21.7893 5.4696,22 6,22H18C18.5304,22 19.0391,21.7893 19.4142,21.4142C19.7893,21.0391 20,20.5304 20,20V11H4ZM10,17H8V12H10V17Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_remote_control_off.xml b/packages/SystemUI/res/drawable/ic_device_remote_control_off.xml
new file mode 100644
index 0000000..761f6430
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_remote_control_off.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,1H8C7.4696,1 6.9609,1.2107 6.5858,1.5858C6.2107,1.9609 6,2.4696 6,3V21C6,21.5304 6.2107,22.0391 6.5858,22.4142C6.9609,22.7893 7.4696,23 8,23H16C16.5304,23 17.0391,22.7893 17.4142,22.4142C17.7893,22.0391 18,21.5304 18,21V3C18,2.4696 17.7893,1.9609 17.4142,1.5858C17.0391,1.2107 16.5304,1 16,1ZM16,21H8V3H16V21Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,10C12.5933,10 13.1734,9.824 13.6667,9.4944C14.1601,9.1648 14.5446,8.6963 14.7716,8.1481C14.9987,7.5999 15.0581,6.9966 14.9424,6.4147C14.8266,5.8327 14.5409,5.2982 14.1213,4.8787C13.7018,4.4591 13.1672,4.1734 12.5853,4.0576C12.0033,3.9419 11.4001,4.0013 10.8519,4.2284C10.3038,4.4555 9.8352,4.8399 9.5056,5.3333C9.1759,5.8266 9,6.4067 9,7C9,7.7957 9.3161,8.5587 9.8787,9.1214C10.4413,9.684 11.2044,10 12,10ZM12,6C12.1978,6 12.3911,6.0587 12.5556,6.1686C12.72,6.2785 12.8482,6.4346 12.9239,6.6173C12.9996,6.8 13.0194,7.0011 12.9808,7.1951C12.9422,7.3891 12.847,7.5673 12.7071,7.7072C12.5673,7.847 12.3891,7.9423 12.1951,7.9809C12.0011,8.0194 11.8,7.9995 11.6173,7.9238C11.4346,7.8481 11.2784,7.72 11.1685,7.5556C11.0587,7.3911 11,7.1978 11,7C11,6.7348 11.1054,6.4804 11.2929,6.2929C11.4804,6.1053 11.7348,6 12,6Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M10,14C10.5523,14 11,13.5523 11,13C11,12.4477 10.5523,12 10,12C9.4477,12 9,12.4477 9,13C9,13.5523 9.4477,14 10,14Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,14C14.5523,14 15,13.5523 15,13C15,12.4477 14.5523,12 14,12C13.4477,12 13,12.4477 13,13C13,13.5523 13.4477,14 14,14Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M10,17C10.5523,17 11,16.5523 11,16C11,15.4477 10.5523,15 10,15C9.4477,15 9,15.4477 9,16C9,16.5523 9.4477,17 10,17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,17C14.5523,17 15,16.5523 15,16C15,15.4477 14.5523,15 14,15C13.4477,15 13,15.4477 13,16C13,16.5523 13.4477,17 14,17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M10,20C10.5523,20 11,19.5523 11,19C11,18.4477 10.5523,18 10,18C9.4477,18 9,18.4477 9,19C9,19.5523 9.4477,20 10,20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,20C14.5523,20 15,19.5523 15,19C15,18.4477 14.5523,18 14,18C13.4477,18 13,18.4477 13,19C13,19.5523 13.4477,20 14,20Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_remote_control_on.xml b/packages/SystemUI/res/drawable/ic_device_remote_control_on.xml
new file mode 100644
index 0000000..b2c55a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_remote_control_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,8C12.5523,8 13,7.5523 13,7C13,6.4477 12.5523,6 12,6C11.4477,6 11,6.4477 11,7C11,7.5523 11.4477,8 12,8Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,1H8C7.4696,1 6.9609,1.2107 6.5858,1.5858C6.2107,1.9609 6,2.4696 6,3V21C6,21.5304 6.2107,22.0391 6.5858,22.4142C6.9609,22.7893 7.4696,23 8,23H16C16.5304,23 17.0391,22.7893 17.4142,22.4142C17.7893,22.0391 18,21.5304 18,21V3C18,2.4696 17.7893,1.9609 17.4142,1.5858C17.0391,1.2107 16.5304,1 16,1ZM10,20C9.8022,20 9.6089,19.9413 9.4444,19.8314C9.28,19.7215 9.1518,19.5654 9.0761,19.3827C9.0004,19.2 8.9806,18.9989 9.0192,18.8049C9.0578,18.611 9.153,18.4327 9.2929,18.2928C9.4327,18.153 9.6109,18.0578 9.8049,18.0192C9.9989,17.9806 10.2,18.0005 10.3827,18.0762C10.5654,18.1519 10.7216,18.28 10.8315,18.4445C10.9414,18.6089 11,18.8022 11,19C11,19.2652 10.8946,19.5196 10.7071,19.7072C10.5196,19.8947 10.2652,20 10,20ZM10,17C9.8022,17 9.6089,16.9413 9.4444,16.8314C9.28,16.7215 9.1518,16.5654 9.0761,16.3827C9.0004,16.2 8.9806,15.9989 9.0192,15.8049C9.0578,15.611 9.153,15.4327 9.2929,15.2928C9.4327,15.153 9.6109,15.0578 9.8049,15.0192C9.9989,14.9806 10.2,15.0005 10.3827,15.0762C10.5654,15.1519 10.7216,15.28 10.8315,15.4445C10.9414,15.6089 11,15.8022 11,16C11,16.2652 10.8946,16.5196 10.7071,16.7072C10.5196,16.8947 10.2652,17 10,17ZM10,14C9.8022,14 9.6089,13.9413 9.4444,13.8314C9.28,13.7215 9.1518,13.5654 9.0761,13.3827C9.0004,13.2 8.9806,12.9989 9.0192,12.8049C9.0578,12.611 9.153,12.4327 9.2929,12.2928C9.4327,12.153 9.6109,12.0578 9.8049,12.0192C9.9989,11.9806 10.2,12.0005 10.3827,12.0762C10.5654,12.1519 10.7216,12.28 10.8315,12.4445C10.9414,12.6089 11,12.8022 11,13C11,13.2652 10.8946,13.5196 10.7071,13.7072C10.5196,13.8947 10.2652,14 10,14ZM14,20C13.8022,20 13.6089,19.9413 13.4444,19.8314C13.28,19.7215 13.1518,19.5654 13.0761,19.3827C13.0004,19.2 12.9806,18.9989 13.0192,18.8049C13.0578,18.611 13.153,18.4327 13.2929,18.2928C13.4327,18.153 13.6109,18.0578 13.8049,18.0192C13.9989,17.9806 14.2,18.0005 14.3827,18.0762C14.5654,18.1519 14.7216,18.28 14.8315,18.4445C14.9414,18.6089 15,18.8022 15,19C15,19.2652 14.8946,19.5196 14.7071,19.7072C14.5196,19.8947 14.2652,20 14,20ZM14,17C13.8022,17 13.6089,16.9413 13.4444,16.8314C13.28,16.7215 13.1518,16.5654 13.0761,16.3827C13.0004,16.2 12.9806,15.9989 13.0192,15.8049C13.0578,15.611 13.153,15.4327 13.2929,15.2928C13.4327,15.153 13.6109,15.0578 13.8049,15.0192C13.9989,14.9806 14.2,15.0005 14.3827,15.0762C14.5654,15.1519 14.7216,15.28 14.8315,15.4445C14.9414,15.6089 15,15.8022 15,16C15,16.2652 14.8946,16.5196 14.7071,16.7072C14.5196,16.8947 14.2652,17 14,17ZM14,14C13.8022,14 13.6089,13.9413 13.4444,13.8314C13.28,13.7215 13.1518,13.5654 13.0761,13.3827C13.0004,13.2 12.9806,12.9989 13.0192,12.8049C13.0578,12.611 13.153,12.4327 13.2929,12.2928C13.4327,12.153 13.6109,12.0578 13.8049,12.0192C13.9989,11.9806 14.2,12.0005 14.3827,12.0762C14.5654,12.1519 14.7216,12.28 14.8315,12.4445C14.9414,12.6089 15,12.8022 15,13C15,13.2652 14.8946,13.5196 14.7071,13.7072C14.5196,13.8947 14.2652,14 14,14ZM12,10C11.4067,10 10.8266,9.824 10.3333,9.4944C9.8399,9.1647 9.4554,8.6962 9.2284,8.1481C9.0013,7.5999 8.9419,6.9966 9.0576,6.4147C9.1734,5.8327 9.4591,5.2982 9.8787,4.8787C10.2982,4.4591 10.8328,4.1734 11.4147,4.0576C11.9967,3.9419 12.5999,4.0013 13.1481,4.2284C13.6962,4.4555 14.1648,4.8399 14.4944,5.3333C14.8241,5.8266 15,6.4067 15,7C15,7.7957 14.6839,8.5587 14.1213,9.1213C13.5587,9.684 12.7956,10 12,10Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_security_system_off.xml b/packages/SystemUI/res/drawable/ic_device_security_system_off.xml
new file mode 100644
index 0000000..7a987b2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_security_system_off.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,2L4,5V11.0911C4,16.1361 7.413,20.854 12,22C16.587,20.854 20,16.1361 20,11.0911V5L12,2ZM18,11.0911C18.0051,12.9956 17.4351,14.8572 16.3645,16.4324C15.294,18.0075 13.7727,19.2227 12,19.9189C10.2273,19.2227 8.706,18.0075 7.6355,16.4324C6.5649,14.8572 5.9949,12.9956 6,11.0911V6.386L12,4.136L18,6.386V11.0911Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8.464,10.939L7.05,12.353L10.586,15.8879L16.949,9.5249L15.535,8.1111L10.586,13.0601L8.464,10.939Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_security_system_on.xml b/packages/SystemUI/res/drawable/ic_device_security_system_on.xml
new file mode 100644
index 0000000..f231068
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_security_system_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,2L4,5V11.0911C4,16.1361 7.413,20.854 12,22C16.587,20.854 20,16.1361 20,11.0911V5L12,2ZM10.586,15.8889L7.05,12.354L8.464,10.9399L10.586,13.061L15.536,8.1111L16.95,9.5249L10.586,15.8889Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_set_top_off.xml b/packages/SystemUI/res/drawable/ic_device_set_top_off.xml
new file mode 100644
index 0000000..7c9d9ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_set_top_off.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M2,7V17H22V7H2ZM20,15H4V9H20V15Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M11,11H5V13H11V11Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,13C14.5523,13 15,12.5523 15,12C15,11.4477 14.5523,11 14,11C13.4477,11 13,11.4477 13,12C13,12.5523 13.4477,13 14,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17,13C17.5523,13 18,12.5523 18,12C18,11.4477 17.5523,11 17,11C16.4477,11 16,11.4477 16,12C16,12.5523 16.4477,13 17,13Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_set_top_on.xml b/packages/SystemUI/res/drawable/ic_device_set_top_on.xml
new file mode 100644
index 0000000..c872794
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_set_top_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M2,7V17H22V7H2ZM11,13H5V11H11V13ZM14,13C13.8022,13 13.6089,12.9414 13.4444,12.8315C13.28,12.7217 13.1518,12.5653 13.0761,12.3826C13.0004,12.1998 12.9806,11.9989 13.0192,11.8049C13.0578,11.611 13.153,11.4328 13.2929,11.293C13.4327,11.1531 13.6109,11.0579 13.8049,11.0193C13.9989,10.9807 14.2,11.0005 14.3827,11.0762C14.5654,11.1519 14.7216,11.2799 14.8315,11.4443C14.9414,11.6088 15,11.8022 15,12C15,12.2652 14.8946,12.5195 14.7071,12.707C14.5196,12.8946 14.2652,13 14,13ZM17,13C16.8022,13 16.6089,12.9414 16.4444,12.8315C16.28,12.7217 16.1518,12.5653 16.0761,12.3826C16.0004,12.1998 15.9806,11.9989 16.0192,11.8049C16.0578,11.611 16.153,11.4328 16.2929,11.293C16.4327,11.1531 16.6109,11.0579 16.8049,11.0193C16.9989,10.9807 17.2,11.0005 17.3827,11.0762C17.5654,11.1519 17.7216,11.2799 17.8315,11.4443C17.9414,11.6088 18,11.8022 18,12C18,12.2652 17.8946,12.5195 17.7071,12.707C17.5196,12.8946 17.2652,13 17,13Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_sprinkler_off.xml b/packages/SystemUI/res/drawable/ic_device_sprinkler_off.xml
new file mode 100644
index 0000000..fb6e34e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_sprinkler_off.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M7.5,18H11V21H13V18H16.5V16H7.5V18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,13C12.5523,13 13,12.5523 13,12C13,11.4477 12.5523,11 12,11C11.4477,11 11,11.4477 11,12C11,12.5523 11.4477,13 12,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,9C12.5523,9 13,8.5523 13,8C13,7.4477 12.5523,7 12,7C11.4477,7 11,7.4477 11,8C11,8.5523 11.4477,9 12,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,5C12.5523,5 13,4.5523 13,4C13,3.4477 12.5523,3 12,3C11.4477,3 11,3.4477 11,4C11,4.5523 11.4477,5 12,5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15.707,14.707C15.8469,14.5672 15.9421,14.3891 15.9808,14.1951C16.0194,14.0011 15.9996,13.7999 15.9239,13.6172C15.8482,13.4344 15.7201,13.2784 15.5556,13.1685C15.3911,13.0586 15.1978,12.9998 15,12.9998C14.8022,12.9998 14.6088,13.0586 14.4444,13.1685C14.2799,13.2784 14.1518,13.4344 14.0761,13.6172C14.0004,13.7999 13.9806,14.0011 14.0192,14.1951C14.0578,14.3891 14.1531,14.5672 14.293,14.707C14.4805,14.8945 14.7348,14.9998 15,14.9998C15.2652,14.9998 15.5195,14.8945 15.707,14.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17.121,10.4641C16.9812,10.604 16.8861,10.7821 16.8476,10.9761C16.8091,11.17 16.829,11.371 16.9047,11.5537C16.9804,11.7364 17.1086,11.8924 17.273,12.0022C17.4375,12.112 17.6308,12.1707 17.8285,12.1707C18.0262,12.1707 18.2195,12.112 18.3839,12.0022C18.5484,11.8924 18.6765,11.7364 18.7523,11.5537C18.828,11.371 18.8479,11.17 18.8094,10.9761C18.7709,10.7821 18.6757,10.604 18.536,10.4641C18.4431,10.3711 18.3328,10.2972 18.2114,10.2468C18.09,10.1965 17.9599,10.1707 17.8285,10.1707C17.6971,10.1707 17.5669,10.1965 17.4455,10.2468C17.3241,10.2972 17.2139,10.3711 17.121,10.4641Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M21.364,7.6359C21.2242,7.496 21.046,7.4009 20.852,7.3622C20.658,7.3236 20.4569,7.3435 20.2742,7.4191C20.0914,7.4948 19.9352,7.6228 19.8253,7.7873C19.7155,7.9517 19.6568,8.1452 19.6568,8.343C19.6568,8.5407 19.7155,8.7342 19.8253,8.8986C19.9352,9.0631 20.0914,9.1911 20.2742,9.2668C20.4569,9.3425 20.658,9.3623 20.852,9.3237C21.046,9.2851 21.2242,9.1899 21.364,9.05C21.5515,8.8625 21.6568,8.6081 21.6568,8.343C21.6568,8.0778 21.5515,7.8235 21.364,7.6359Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M9.707,14.707C9.8469,14.5672 9.9421,14.3891 9.9808,14.1951C10.0194,14.0011 9.9996,13.7999 9.9239,13.6172C9.8482,13.4344 9.72,13.2784 9.5556,13.1685C9.3911,13.0586 9.1978,12.9998 9,12.9998C8.8022,12.9998 8.6088,13.0586 8.4444,13.1685C8.2799,13.2784 8.1518,13.4344 8.0761,13.6172C8.0004,13.7999 7.9806,14.0011 8.0192,14.1951C8.0578,14.3891 8.1531,14.5672 8.293,14.707C8.4805,14.8945 8.7348,14.9998 9,14.9998C9.2652,14.9998 9.5195,14.8945 9.707,14.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M5.464,10.4641C5.3243,10.604 5.2291,10.7821 5.1906,10.9761C5.1522,11.17 5.172,11.371 5.2477,11.5537C5.3235,11.7364 5.4516,11.8924 5.616,12.0022C5.7805,12.112 5.9738,12.1707 6.1715,12.1707C6.3692,12.1707 6.5625,12.112 6.727,12.0022C6.8914,11.8924 7.0196,11.7364 7.0953,11.5537C7.171,11.371 7.1909,11.17 7.1524,10.9761C7.1139,10.7821 7.0188,10.604 6.879,10.4641C6.7861,10.3711 6.6758,10.2972 6.5545,10.2468C6.4331,10.1965 6.3029,10.1707 6.1715,10.1707C6.0401,10.1707 5.91,10.1965 5.7886,10.2468C5.6672,10.2972 5.5569,10.3711 5.464,10.4641Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M2.636,7.636C2.4961,7.7758 2.4009,7.954 2.3623,8.148C2.3236,8.3419 2.3434,8.5431 2.4191,8.7258C2.4948,8.9086 2.623,9.0647 2.7874,9.1746C2.9519,9.2845 3.1452,9.3433 3.343,9.3433C3.5408,9.3433 3.7342,9.2845 3.8986,9.1746C4.0631,9.0647 4.1912,8.9086 4.2669,8.7258C4.3426,8.5431 4.3624,8.3419 4.3238,8.148C4.2852,7.954 4.1899,7.7758 4.05,7.636C3.8625,7.4485 3.6082,7.3433 3.343,7.3433C3.0779,7.3433 2.8235,7.4485 2.636,7.636Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_sprinkler_on.xml b/packages/SystemUI/res/drawable/ic_device_sprinkler_on.xml
new file mode 100644
index 0000000..a5bdf1c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_sprinkler_on.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20.657,9.343C21.2093,9.343 21.657,8.8953 21.657,8.343C21.657,7.7907 21.2093,7.343 20.657,7.343C20.1047,7.343 19.657,7.7907 19.657,8.343C19.657,8.8953 20.1047,9.343 20.657,9.343Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M7.5,18H11V21H13V18H16.5V16H7.5V18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,13C12.5523,13 13,12.5523 13,12C13,11.4477 12.5523,11 12,11C11.4477,11 11,11.4477 11,12C11,12.5523 11.4477,13 12,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,9C12.5523,9 13,8.5523 13,8C13,7.4477 12.5523,7 12,7C11.4477,7 11,7.4477 11,8C11,8.5523 11.4477,9 12,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,5C12.5523,5 13,4.5523 13,4C13,3.4477 12.5523,3 12,3C11.4477,3 11,3.4477 11,4C11,4.5523 11.4477,5 12,5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15.707,14.707C15.8469,14.5672 15.9422,14.3891 15.9808,14.1951C16.0194,14.0011 15.9996,13.7999 15.9239,13.6172C15.8483,13.4344 15.7201,13.2784 15.5556,13.1685C15.3912,13.0586 15.1978,12.9998 15,12.9998C14.8022,12.9998 14.6089,13.0586 14.4444,13.1685C14.28,13.2784 14.1518,13.4344 14.0761,13.6172C14.0004,13.7999 13.9807,14.0011 14.0193,14.1951C14.0579,14.3891 14.1531,14.5672 14.293,14.707C14.4806,14.8945 14.7349,14.9998 15,14.9998C15.2652,14.9998 15.5195,14.8945 15.707,14.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18.536,10.4642C18.3961,10.3245 18.2179,10.2293 18.024,10.1908C17.83,10.1523 17.629,10.1722 17.4464,10.2479C17.2637,10.3236 17.1076,10.4516 16.9978,10.616C16.8879,10.7805 16.8293,10.9737 16.8293,11.1715C16.8293,11.3692 16.8879,11.5627 16.9978,11.7271C17.1076,11.8916 17.2637,12.0196 17.4464,12.0953C17.629,12.171 17.83,12.1909 18.024,12.1524C18.2179,12.1139 18.3961,12.0187 18.536,11.879C18.629,11.7861 18.7028,11.6759 18.7531,11.5545C18.8034,11.4331 18.8293,11.3029 18.8293,11.1715C18.8293,11.0401 18.8034,10.9101 18.7531,10.7887C18.7028,10.6673 18.629,10.5571 18.536,10.4642Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M9.707,14.707C9.8469,14.5672 9.9422,14.3891 9.9808,14.1951C10.0194,14.0011 9.9996,13.7999 9.9239,13.6172C9.8483,13.4344 9.7201,13.2784 9.5556,13.1685C9.3912,13.0586 9.1978,12.9998 9,12.9998C8.8022,12.9998 8.6089,13.0586 8.4444,13.1685C8.28,13.2784 8.1518,13.4344 8.0761,13.6172C8.0004,13.7999 7.9807,14.0011 8.0193,14.1951C8.0579,14.3891 8.1531,14.5672 8.293,14.707C8.4806,14.8945 8.7349,14.9998 9,14.9998C9.2652,14.9998 9.5195,14.8945 9.707,14.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M5.464,10.4641C5.3243,10.604 5.2291,10.7821 5.1906,10.9761C5.1522,11.17 5.172,11.371 5.2477,11.5537C5.3235,11.7364 5.4516,11.8924 5.616,12.0022C5.7805,12.112 5.9738,12.1707 6.1715,12.1707C6.3692,12.1707 6.5625,12.112 6.727,12.0022C6.8914,11.8924 7.0196,11.7364 7.0953,11.5537C7.171,11.371 7.1909,11.17 7.1524,10.9761C7.1139,10.7821 7.0188,10.604 6.879,10.4641C6.7861,10.3711 6.6758,10.2972 6.5545,10.2468C6.4331,10.1965 6.3029,10.1707 6.1715,10.1707C6.0401,10.1707 5.91,10.1965 5.7886,10.2468C5.6672,10.2972 5.5569,10.3711 5.464,10.4641Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M2.636,7.636C2.4961,7.7758 2.4009,7.954 2.3623,8.148C2.3236,8.3419 2.3434,8.5431 2.4191,8.7258C2.4948,8.9086 2.623,9.0647 2.7874,9.1746C2.9519,9.2845 3.1452,9.3433 3.343,9.3433C3.5408,9.3433 3.7342,9.2845 3.8986,9.1746C4.0631,9.0647 4.1912,8.9086 4.2669,8.7258C4.3426,8.5431 4.3624,8.3419 4.3238,8.148C4.2852,7.954 4.1899,7.7758 4.05,7.636C3.8625,7.4485 3.6082,7.3433 3.343,7.3433C3.0779,7.3433 2.8235,7.4485 2.636,7.636Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_styler_off.xml b/packages/SystemUI/res/drawable/ic_device_styler_off.xml
new file mode 100644
index 0000000..4d5e3f3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_styler_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19.56,11.361L13,8.4408V6.9999C13,6.7347 12.8946,6.4804 12.7071,6.2929C12.5196,6.1054 12.2652,5.9999 12,5.9999C11.8022,5.9999 11.6089,5.9413 11.4444,5.8315C11.28,5.7216 11.1518,5.5652 11.0761,5.3825C11.0004,5.1998 10.9806,4.9988 11.0192,4.8049C11.0578,4.6109 11.153,4.4327 11.2929,4.2929C11.4327,4.153 11.6109,4.0578 11.8049,4.0192C11.9989,3.9806 12.2,4.0004 12.3827,4.0761C12.5654,4.1518 12.7216,4.2798 12.8315,4.4443C12.9414,4.6087 13,4.8021 13,4.9999H15C15.0015,4.4496 14.8517,3.9095 14.5668,3.4386C14.2819,2.9678 13.8729,2.5843 13.3847,2.3303C12.8965,2.0762 12.3478,1.9613 11.7987,1.9982C11.2496,2.0351 10.7212,2.2224 10.2714,2.5395C9.8216,2.8566 9.4677,3.2915 9.2484,3.7963C9.0291,4.3011 8.9529,4.8563 9.0282,5.4015C9.1034,5.9467 9.3272,6.4608 9.6749,6.8874C10.0227,7.3139 10.4811,7.6365 11,7.82V8.4499L4.44,11.37C4.0115,11.5562 3.6468,11.8636 3.3909,12.2546C3.1351,12.6455 2.9992,13.1028 3,13.57V13.58C2.9995,13.8979 3.0617,14.2129 3.1831,14.5068C3.3046,14.8006 3.4828,15.0676 3.7076,15.2924C3.9325,15.5172 4.1994,15.6954 4.4933,15.8168C4.7871,15.9382 5.1021,16.0004 5.42,15.9999H7V21.9999H17V15.9999H18.58C18.898,16.0004 19.2129,15.9382 19.5067,15.8168C19.8006,15.6954 20.0676,15.5172 20.2924,15.2924C20.5172,15.0676 20.6954,14.8006 20.8169,14.5068C20.9383,14.2129 21.0005,13.8979 21,13.58V13.57C20.9994,13.1019 20.8631,12.644 20.6075,12.2519C20.3519,11.8598 19.988,11.5504 19.56,11.361ZM15,19.9999H9V14.9999H15V19.9999ZM18.58,13.9999H17V12.9999H7V13.9999H5.42C5.3642,13.9993 5.3091,13.9877 5.2577,13.9657C5.2064,13.9438 5.1599,13.9119 5.1209,13.872C5.0819,13.8321 5.0512,13.7846 5.0304,13.7328C5.0097,13.681 4.9993,13.6258 5,13.57C4.999,13.4889 5.0222,13.4094 5.0668,13.3417C5.1114,13.274 5.1752,13.221 5.25,13.1899L12,10.1899L18.75,13.1899C18.8245,13.2243 18.8876,13.2795 18.9319,13.3486C18.9761,13.4176 18.9998,13.4979 19,13.58C18.9995,13.6912 18.9551,13.7977 18.8764,13.8764C18.7978,13.955 18.6912,13.9994 18.58,13.9999Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_styler_on.xml b/packages/SystemUI/res/drawable/ic_device_styler_on.xml
new file mode 100644
index 0000000..58e04e0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_styler_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19.56,11.361L13,8.4408V6.9999C13,6.7347 12.8946,6.4804 12.7071,6.2929C12.5196,6.1054 12.2652,5.9999 12,5.9999C11.8022,5.9999 11.6089,5.9413 11.4444,5.8315C11.28,5.7216 11.1518,5.5652 11.0761,5.3825C11.0004,5.1998 10.9806,4.9988 11.0192,4.8049C11.0578,4.6109 11.153,4.4327 11.2929,4.2929C11.4327,4.153 11.6109,4.0578 11.8049,4.0192C11.9989,3.9806 12.2,4.0004 12.3827,4.0761C12.5654,4.1518 12.7216,4.2798 12.8315,4.4443C12.9414,4.6087 13,4.8021 13,4.9999H15C15.0015,4.4496 14.8517,3.9095 14.5668,3.4386C14.2819,2.9678 13.8729,2.5843 13.3847,2.3303C12.8965,2.0762 12.3478,1.9613 11.7987,1.9982C11.2496,2.0351 10.7212,2.2224 10.2714,2.5395C9.8216,2.8566 9.4677,3.2915 9.2484,3.7963C9.0291,4.3011 8.9529,4.8563 9.0282,5.4015C9.1034,5.9467 9.3272,6.4608 9.6749,6.8874C10.0227,7.3139 10.4811,7.6365 11,7.82V8.4499L4.44,11.37C4.0115,11.5562 3.6468,11.8636 3.3909,12.2546C3.1351,12.6455 2.9992,13.1028 3,13.57V13.58C2.9995,13.8979 3.0617,14.2129 3.1831,14.5068C3.3046,14.8006 3.4828,15.0676 3.7076,15.2924C3.9325,15.5172 4.1994,15.6954 4.4933,15.8168C4.7871,15.9382 5.1021,16.0004 5.42,15.9999H7V21.9999H17V15.9999H18.58C18.898,16.0004 19.2129,15.9382 19.5067,15.8168C19.8006,15.6954 20.0676,15.5172 20.2924,15.2924C20.5172,15.0676 20.6954,14.8006 20.8169,14.5068C20.9383,14.2129 21.0005,13.8979 21,13.58V13.57C20.9994,13.1019 20.8631,12.644 20.6075,12.2519C20.3519,11.8598 19.988,11.5504 19.56,11.361ZM18.58,14.0009H17V13.0009H7V14.0009H5.42C5.3642,14.0002 5.3091,13.9887 5.2577,13.9667C5.2064,13.9448 5.1599,13.9129 5.1209,13.873C5.0819,13.833 5.0512,13.7859 5.0304,13.7341C5.0097,13.6822 4.9993,13.6268 5,13.571C4.999,13.4899 5.0222,13.4104 5.0668,13.3427C5.1114,13.275 5.1752,13.222 5.25,13.1908L12,10.1908L18.75,13.1908C18.8245,13.2253 18.8876,13.2804 18.9319,13.3495C18.9761,13.4186 18.9998,13.4989 19,13.581C18.9992,13.692 18.9547,13.7982 18.8761,13.8766C18.7974,13.9551 18.6911,13.9994 18.58,13.9999V14.0009Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_switch_off.xml b/packages/SystemUI/res/drawable/ic_device_switch_off.xml
new file mode 100644
index 0000000..12dcd81
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_switch_off.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19,3H5C4.4696,3 3.9609,3.2107 3.5858,3.5858C3.2107,3.9609 3,4.4696 3,5V19C3,19.5304 3.2107,20.0391 3.5858,20.4142C3.9609,20.7893 4.4696,21 5,21H19C19.5304,21 20.0391,20.7893 20.4142,20.4142C20.7893,20.0391 21,19.5304 21,19V5C21,4.4696 20.7893,3.9609 20.4142,3.5858C20.0391,3.2107 19.5304,3 19,3ZM19,19H5V5H19V19Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,7H8V17H16V7ZM14,15H10V9H14V15Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M13,10H11V12H13V10Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_switch_on.xml b/packages/SystemUI/res/drawable/ic_device_switch_on.xml
new file mode 100644
index 0000000..68678a39
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_switch_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M14,9H10V15H14V9ZM13,12H11V10H13V12Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M19,3H5C4.4696,3 3.9609,3.2107 3.5858,3.5858C3.2107,3.9609 3,4.4696 3,5V19C3,19.5304 3.2107,20.0391 3.5858,20.4142C3.9609,20.7893 4.4696,21 5,21H19C19.5304,21 20.0391,20.7893 20.4142,20.4142C20.7893,20.0391 21,19.5304 21,19V5C21,4.4696 20.7893,3.9609 20.4142,3.5858C20.0391,3.2107 19.5304,3 19,3ZM16,17H8V7H16V17Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml
deleted file mode 100644
index 45a658f..0000000
--- a/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,9h-5v2h5m3,-6h-8v2h8m-9,11.97c0.62,-0.83 1,-1.85 1,-2.97 0,-1.63 -0.79,-3.09 -2,-4V6c0,-1.66 -1.34,-3 -3,-3S5,4.34 5,6v6c-1.21,0.91 -2,2.37 -2,4 0,1.12 0.38,2.14 1,2.97V19h0.02c0.91,1.21 2.35,2 3.98,2s3.06,-0.79 3.98,-2H12v-0.03zM6.2,13.6L7,13V6c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v7l0.8,0.6c0.75,0.57 1.2,1.46 1.2,2.4H5c0,-0.94 0.45,-1.84 1.2,-2.4z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_off.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_off.xml
new file mode 100644
index 0000000..1ba8741
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_thermostat_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,18.97C16.6469,18.1148 16.9979,17.0723 17,16C16.9993,15.2239 16.8183,14.4586 16.4712,13.7644C16.1241,13.0702 15.6205,12.4662 15,12V6C15,5.2043 14.6839,4.4413 14.1213,3.8787C13.5587,3.3161 12.7956,3 12,3C11.2044,3 10.4413,3.3161 9.8787,3.8787C9.3161,4.4413 9,5.2043 9,6V12C8.3795,12.4662 7.8759,13.0702 7.5288,13.7644C7.1817,14.4586 7.0007,15.2239 7,16C7.0021,17.0723 7.3531,18.1148 8,18.97V19H8.02C8.4815,19.6206 9.0818,20.1246 9.7729,20.4719C10.4639,20.8192 11.2266,21.0001 12,21.0001C12.7734,21.0001 13.5361,20.8192 14.2271,20.4719C14.9182,20.1246 15.5185,19.6206 15.98,19H16V18.97ZM10.2,13.6L11,13V6C11,5.7348 11.1054,5.4804 11.2929,5.2929C11.4804,5.1054 11.7348,5 12,5C12.2652,5 12.5196,5.1054 12.7071,5.2929C12.8946,5.4804 13,5.7348 13,6V13L13.8,13.6C14.1711,13.8809 14.4723,14.2435 14.6805,14.6598C14.8886,15.076 14.9979,15.5346 15,16H9C9.0009,15.5344 9.1098,15.0754 9.318,14.659C9.5262,14.2426 9.8281,13.8801 10.2,13.6Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_on.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_on.xml
new file mode 100644
index 0000000..1ba8741
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_thermostat_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,18.97C16.6469,18.1148 16.9979,17.0723 17,16C16.9993,15.2239 16.8183,14.4586 16.4712,13.7644C16.1241,13.0702 15.6205,12.4662 15,12V6C15,5.2043 14.6839,4.4413 14.1213,3.8787C13.5587,3.3161 12.7956,3 12,3C11.2044,3 10.4413,3.3161 9.8787,3.8787C9.3161,4.4413 9,5.2043 9,6V12C8.3795,12.4662 7.8759,13.0702 7.5288,13.7644C7.1817,14.4586 7.0007,15.2239 7,16C7.0021,17.0723 7.3531,18.1148 8,18.97V19H8.02C8.4815,19.6206 9.0818,20.1246 9.7729,20.4719C10.4639,20.8192 11.2266,21.0001 12,21.0001C12.7734,21.0001 13.5361,20.8192 14.2271,20.4719C14.9182,20.1246 15.5185,19.6206 15.98,19H16V18.97ZM10.2,13.6L11,13V6C11,5.7348 11.1054,5.4804 11.2929,5.2929C11.4804,5.1054 11.7348,5 12,5C12.2652,5 12.5196,5.1054 12.7071,5.2929C12.8946,5.4804 13,5.7348 13,6V13L13.8,13.6C14.1711,13.8809 14.4723,14.2435 14.6805,14.6598C14.8886,15.076 14.9979,15.5346 15,16H9C9.0009,15.5344 9.1098,15.0754 9.318,14.659C9.5262,14.2426 9.8281,13.8801 10.2,13.6Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_tv_off.xml b/packages/SystemUI/res/drawable/ic_device_tv_off.xml
new file mode 100644
index 0000000..dd91ed8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_tv_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,4H4C3.4701,4.0016 2.9623,4.2129 2.5875,4.5876C2.2128,4.9624 2.0016,5.47 2,6V17C2.0016,17.5299 2.2128,18.0376 2.5875,18.4124C2.9623,18.7871 3.4701,18.9984 4,19V21H5L5.667,19H18.333L19,21H20V19C20.5299,18.9984 21.0377,18.7871 21.4125,18.4124C21.7872,18.0376 21.9984,17.5299 22,17V6C21.9984,5.47 21.7872,4.9624 21.4125,4.5876C21.0377,4.2129 20.5299,4.0016 20,4ZM20,17H4V6H20V17Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_tv_on.xml b/packages/SystemUI/res/drawable/ic_device_tv_on.xml
new file mode 100644
index 0000000..dd91ed8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_tv_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,4H4C3.4701,4.0016 2.9623,4.2129 2.5875,4.5876C2.2128,4.9624 2.0016,5.47 2,6V17C2.0016,17.5299 2.2128,18.0376 2.5875,18.4124C2.9623,18.7871 3.4701,18.9984 4,19V21H5L5.667,19H18.333L19,21H20V19C20.5299,18.9984 21.0377,18.7871 21.4125,18.4124C21.7872,18.0376 21.9984,17.5299 22,17V6C21.9984,5.47 21.7872,4.9624 21.4125,4.5876C21.0377,4.2129 20.5299,4.0016 20,4ZM20,17H4V6H20V17Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_vacuum_off.xml b/packages/SystemUI/res/drawable/ic_device_vacuum_off.xml
new file mode 100644
index 0000000..e0fadc8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_vacuum_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M4,16.0001C3.4067,16.0001 2.8266,16.176 2.3333,16.5057C1.8399,16.8353 1.4554,17.3039 1.2284,17.8521C1.0013,18.4002 0.9419,19.0034 1.0576,19.5854C1.1734,20.1673 1.4591,20.7019 1.8787,21.1214C2.2982,21.541 2.8328,21.8267 3.4147,21.9425C3.9967,22.0582 4.5999,21.9988 5.148,21.7717C5.6962,21.5447 6.1648,21.1602 6.4944,20.6668C6.824,20.1735 7,19.5934 7,19.0001C7,18.2045 6.6839,17.4414 6.1213,16.8788C5.5587,16.3162 4.7957,16.0001 4,16.0001ZM4,20.0001C3.8022,20.0001 3.6089,19.9415 3.4444,19.8316C3.28,19.7217 3.1518,19.5655 3.0761,19.3828C3.0004,19.2001 2.9806,18.999 3.0192,18.805C3.0578,18.611 3.153,18.4329 3.2929,18.293C3.4327,18.1532 3.6109,18.0579 3.8049,18.0193C3.9989,17.9807 4.2,18.0005 4.3827,18.0762C4.5654,18.1519 4.7216,18.2801 4.8315,18.4445C4.9413,18.609 5,18.8023 5,19.0001C5,19.2653 4.8946,19.5197 4.7071,19.7072C4.5196,19.8947 4.2652,20.0001 4,20.0001ZM23,20.0001V22.0001H16V20.0001H18.49L12.01,4.5901C11.7747,4.0366 11.3553,3.5814 10.823,3.3016C10.2906,3.0217 9.6779,2.9344 9.0885,3.0544C8.4991,3.1744 7.9693,3.4943 7.5888,3.96C7.2082,4.4257 7.0002,5.0086 7,5.6101V9.0001H9C10.0609,9.0001 11.0783,9.4215 11.8284,10.1717C12.5786,10.9218 13,11.9392 13,13.0001V22.0001H7.99C8.4398,21.4103 8.7508,20.7267 8.9,20.0001H11V13.0001C10.9984,12.4702 10.7872,11.9624 10.4125,11.5876C10.0377,11.2129 9.5299,11.0017 9,11.0001H4V14.0001C3.3113,13.9992 2.6301,14.1422 2,14.4201V9.0001H5V5.6101C5.0002,4.5458 5.3685,3.5144 6.0426,2.6908C6.7165,1.8672 7.6547,1.3021 8.6979,1.0913C9.741,0.8806 10.825,1.0372 11.7659,1.5345C12.7068,2.0319 13.4466,2.8394 13.86,3.8201L20.66,20.0001H23Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_vacuum_on.xml b/packages/SystemUI/res/drawable/ic_device_vacuum_on.xml
new file mode 100644
index 0000000..d3b0a7d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_vacuum_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M4,16.0001C3.4067,16.0001 2.8266,16.176 2.3333,16.5057C1.8399,16.8353 1.4554,17.3039 1.2284,17.8521C1.0013,18.4002 0.9419,19.0034 1.0576,19.5854C1.1734,20.1673 1.4591,20.7018 1.8787,21.1214C2.2982,21.541 2.8328,21.8267 3.4147,21.9424C3.9967,22.0582 4.5999,21.9988 5.148,21.7717C5.6962,21.5447 6.1648,21.1602 6.4944,20.6668C6.824,20.1735 7,19.5934 7,19.0001C7,18.2044 6.6839,17.4414 6.1213,16.8788C5.5587,16.3162 4.7957,16.0001 4,16.0001ZM4,20.0001C3.8022,20.0001 3.6089,19.9415 3.4444,19.8316C3.28,19.7217 3.1518,19.5655 3.0761,19.3828C3.0004,19.2001 2.9806,18.999 3.0192,18.805C3.0578,18.611 3.153,18.4329 3.2929,18.293C3.4327,18.1531 3.6109,18.0579 3.8049,18.0193C3.9989,17.9807 4.2,18.0005 4.3827,18.0762C4.5654,18.1519 4.7216,18.2801 4.8315,18.4445C4.9413,18.609 5,18.8023 5,19.0001C5,19.2653 4.8946,19.5196 4.7071,19.7072C4.5196,19.8947 4.2652,20.0001 4,20.0001Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M20.66,20.0001L13.86,3.8201C13.4466,2.8394 12.7068,2.0319 11.7659,1.5345C10.825,1.0372 9.7411,0.8806 8.6979,1.0913C7.6547,1.3021 6.7165,1.8672 6.0426,2.6908C5.3685,3.5144 5.0002,4.5458 5,5.6101V9.0001H2V14.4261C2.76,14.0908 3.5918,13.9506 4.4197,14.0184C5.2476,14.0861 6.0455,14.3596 6.7409,14.814C7.4363,15.2684 8.0072,15.8893 8.4017,16.6203C8.7962,17.3514 9.0019,18.1694 9,19.0001C8.9968,20.0853 8.637,21.1394 7.976,22.0001H13V13.0001C13,11.9392 12.5786,10.9218 11.8284,10.1717C11.0783,9.4215 10.0609,9.0001 9,9.0001H7V5.6101C7.0002,5.0086 7.2082,4.4257 7.5888,3.96C7.9693,3.4943 8.4991,3.1744 9.0885,3.0544C9.6779,2.9344 10.2906,3.0217 10.823,3.3016C11.3553,3.5814 11.7747,4.0366 12.01,4.5901L18.49,20.0001H16V22.0001H23V20.0001H20.66Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_valve_off.xml b/packages/SystemUI/res/drawable/ic_device_valve_off.xml
new file mode 100644
index 0000000..5bfb46f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_valve_off.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M11,8H13V5H17V3H7V5H11V8Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18,13V14H15V11H16V9H8V11H9V14H6V13H4V21H6V20H18V21H20V13H18ZM6,18V16H11V11H13V16H18V18H6Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_valve_on.xml b/packages/SystemUI/res/drawable/ic_device_valve_on.xml
new file mode 100644
index 0000000..66b8829
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_valve_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M11,8H13V5H17V3H7V5H11V8Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18,13V14H15V11H16V9H8V11H9V14H6V13H4V21H6V20H18V21H20V13H18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_washer_off.xml b/packages/SystemUI/res/drawable/ic_device_washer_off.xml
new file mode 100644
index 0000000..f759bcc
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_washer_off.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,2.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2336,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9906 4.1504,3.2336C4.0502,3.4767 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5233 4.1504,20.7664C4.2505,21.0094 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2336,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0094 19.8497,20.7664C19.9498,20.5233 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.773 19.4151,2.5879C19.2291,2.4028 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM18,20H6L5.993,4H18V20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M11,7C11.5523,7 12,6.5523 12,6C12,5.4477 11.5523,5 11,5C10.4477,5 10,5.4477 10,6C10,6.5523 10.4477,7 11,7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8,7C8.5523,7 9,6.5523 9,6C9,5.4477 8.5523,5 8,5C7.4477,5 7,5.4477 7,6C7,6.5523 7.4477,7 8,7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,18.9999C12.9889,18.9999 13.9556,18.7065 14.7778,18.1571C15.6001,17.6077 16.241,16.8269 16.6194,15.9132C16.9978,14.9996 17.0969,13.9945 16.9039,13.0246C16.711,12.0547 16.2348,11.1635 15.5355,10.4643C14.8363,9.765 13.9454,9.289 12.9754,9.0961C12.0055,8.9032 11.0002,9.0021 10.0866,9.3805C9.1729,9.759 8.3921,10.3998 7.8426,11.2221C7.2932,12.0443 7,13.011 7,13.9999C7,15.326 7.5268,16.5979 8.4645,17.5356C9.4021,18.4732 10.6739,18.9999 12,18.9999ZM14.36,11.6398C14.9689,12.2692 15.3061,13.1127 15.2989,13.9884C15.2916,14.8641 14.9405,15.702 14.3213,16.3212C13.7021,16.9404 12.8643,17.2915 11.9886,17.2987C11.1129,17.306 10.2694,16.9689 9.64,16.36L14.36,11.6398Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_washer_on.xml b/packages/SystemUI/res/drawable/ic_device_washer_on.xml
new file mode 100644
index 0000000..b624fb6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_washer_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M9.64,16.3601C10.2694,16.969 11.1129,17.3061 11.9886,17.2988C12.8643,17.2916 13.7021,16.9405 14.3213,16.3213C14.9406,15.7021 15.2916,14.8642 15.2989,13.9885C15.3061,13.1128 14.9689,12.2693 14.36,11.6399L9.64,16.3601ZM18,2.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2336,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9906 4.1504,3.2336C4.0502,3.4767 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5233 4.1504,20.7664C4.2505,21.0094 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2336,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0094 19.8497,20.7664C19.9498,20.5233 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.773 19.4151,2.5879C19.2291,2.4028 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM11,5C11.1978,5 11.3911,5.0586 11.5556,5.1685C11.72,5.2783 11.8482,5.4347 11.9239,5.6174C11.9996,5.8002 12.0194,6.0011 11.9808,6.1951C11.9422,6.3891 11.847,6.5672 11.7071,6.707C11.5673,6.8469 11.3891,6.9421 11.1951,6.9807C11.0011,7.0193 10.8001,6.9995 10.6173,6.9238C10.4346,6.8481 10.2784,6.7201 10.1685,6.5557C10.0587,6.3912 10,6.1978 10,6C10,5.7348 10.1054,5.4805 10.2929,5.293C10.4804,5.1054 10.7348,5 11,5ZM8,5C8.1978,5 8.3911,5.0586 8.5556,5.1685C8.72,5.2783 8.8482,5.4347 8.9239,5.6174C8.9996,5.8002 9.0194,6.0011 8.9808,6.1951C8.9422,6.3891 8.847,6.5672 8.7071,6.707C8.5673,6.8469 8.3891,6.9421 8.1951,6.9807C8.0011,7.0193 7.8001,6.9995 7.6173,6.9238C7.4346,6.8481 7.2784,6.7201 7.1685,6.5557C7.0587,6.3912 7,6.1978 7,6C7,5.7348 7.1054,5.4805 7.2929,5.293C7.4804,5.1054 7.7348,5 8,5ZM12,19C11.0111,19 10.0444,18.7066 9.2222,18.1572C8.3999,17.6078 7.759,16.827 7.3806,15.9133C7.0022,14.9997 6.9032,13.9946 7.0961,13.0247C7.289,12.0548 7.7652,11.1636 8.4645,10.4644C9.1637,9.7651 10.0547,9.2891 11.0246,9.0962C11.9945,8.9033 12.9998,9.0022 13.9134,9.3806C14.8271,9.7591 15.608,10.3999 16.1574,11.2222C16.7068,12.0444 17,13.0111 17,14C17,15.3261 16.4732,16.598 15.5355,17.5357C14.5979,18.4733 13.3261,19 12,19Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_water_heater_off.xml b/packages/SystemUI/res/drawable/ic_device_water_heater_off.xml
new file mode 100644
index 0000000..1791958
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_water_heater_off.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,2H8C6.9391,2 5.9217,2.4212 5.1716,3.1714C4.4214,3.9215 4,4.9391 4,6V20C4,20.5304 4.2107,21.039 4.5858,21.4141C4.9609,21.7891 5.4696,22 6,22H18C18.5304,22 19.0391,21.7891 19.4142,21.4141C19.7893,21.039 20,20.5304 20,20V6C20,4.9391 19.5786,3.9215 18.8284,3.1714C18.0783,2.4212 17.0609,2 16,2ZM18,20H6V18C7.05,18 7.18,19 9,19C10.82,19 10.952,18 12,18C13.048,18 13.189,19 15,19C16.811,19 16.953,18 18,18V20ZM18,16C16.18,16 16.046,17 15,17C13.954,17 13.81,16 12,16C10.19,16 10.047,17 9,17C7.953,17 7.821,16 6,16V6C6,5.4696 6.2107,4.961 6.5858,4.5859C6.9609,4.2109 7.4696,4 8,4H16C16.5304,4 17.0391,4.2109 17.4142,4.5859C17.7893,4.961 18,5.4696 18,6V16Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M13.553,8.0161C13.1979,7.6625 12.9486,7.2166 12.8333,6.729C12.7179,6.2413 12.741,5.7311 12.9,5.2558C12.9134,5.2214 12.9162,5.1839 12.9082,5.1479C12.9003,5.1119 12.8818,5.0792 12.8552,5.0537C12.8286,5.0281 12.795,5.0109 12.7586,5.0044C12.7223,4.9979 12.6849,5.0023 12.6511,5.0171C8.8941,6.6581 10.4031,10.6938 10.4031,10.7568C10.4028,10.8187 10.3848,10.8792 10.3511,10.9311C10.3174,10.9831 10.2695,11.0243 10.2131,11.0498C10.2031,11.0498 9.974,11.1708 9.769,10.8838C9.5395,10.5707 9.3759,10.2145 9.2879,9.8364C9.1999,9.4583 9.1894,9.0663 9.2571,8.6841C9.2647,8.6434 9.2587,8.6012 9.2398,8.5644C9.2209,8.5276 9.1902,8.4984 9.1527,8.4809C9.1152,8.4635 9.0729,8.459 9.0326,8.4682C8.9923,8.4775 8.9562,8.5001 8.93,8.5322C8.503,9.08 8.2253,9.7288 8.1241,10.416C8.023,11.1032 8.1018,11.805 8.3528,12.4526C8.6039,13.1003 9.0187,13.6719 9.5567,14.1113C10.0946,14.5507 10.7373,14.8431 11.4221,14.9599C15.6071,15.4939 17.1871,11.2899 14.7041,8.9599C14.3381,8.6159 13.909,8.3721 13.553,8.0161ZM13.3241,12.8691C13.0354,13.1235 12.6634,13.2626 12.2787,13.2607C11.8939,13.2589 11.5233,13.116 11.2371,12.8589C11.225,12.8488 11.2159,12.836 11.2107,12.8213C11.2054,12.8065 11.2042,12.7903 11.2072,12.7749C11.2101,12.7595 11.2172,12.7452 11.2275,12.7334C11.2379,12.7216 11.2512,12.7129 11.2661,12.708C11.5164,12.6335 11.7426,12.4939 11.9216,12.3037C12.1005,12.1135 12.226,11.8794 12.2851,11.625C12.3198,11.2109 12.2684,10.7941 12.1341,10.4009C12.067,10.0764 12.087,9.74 12.1921,9.4258C12.196,9.4132 12.2035,9.4023 12.2138,9.394C12.2241,9.3858 12.2366,9.3809 12.2497,9.3799C12.2628,9.3788 12.2759,9.3817 12.2874,9.3882C12.2989,9.3946 12.3081,9.4042 12.3141,9.416C12.6801,10.236 13.8361,10.6222 13.8361,11.6162C13.843,11.8492 13.801,12.081 13.7128,12.2969C13.6246,12.5127 13.4922,12.7076 13.3241,12.8691Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_water_heater_on.xml b/packages/SystemUI/res/drawable/ic_device_water_heater_on.xml
new file mode 100644
index 0000000..ee1ca91
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_water_heater_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M13.324,12.8694C13.4916,12.7083 13.6238,12.5136 13.7119,12.2986C13.8001,12.0835 13.8424,11.8527 13.836,11.6203C13.836,10.6203 12.68,10.2361 12.314,9.4201C12.3081,9.4084 12.2988,9.3988 12.2874,9.3923C12.2759,9.3859 12.2628,9.3829 12.2496,9.384C12.2365,9.3851 12.224,9.3899 12.2138,9.3982C12.2035,9.4064 12.1959,9.4178 12.192,9.4304C12.087,9.7446 12.067,10.0806 12.134,10.405C12.2683,10.7982 12.3197,11.2151 12.285,11.6291C12.2259,11.8835 12.1005,12.1181 11.9215,12.3083C11.7425,12.4985 11.5164,12.6377 11.266,12.7121C11.2511,12.717 11.2378,12.7257 11.2275,12.7375C11.2171,12.7493 11.2101,12.7636 11.2071,12.779C11.2042,12.7944 11.2054,12.8106 11.2106,12.8254C11.2159,12.8402 11.225,12.8529 11.237,12.863C11.5237,13.1195 11.8947,13.2623 12.2794,13.2634C12.6641,13.2645 13.0358,13.1242 13.324,12.8694Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,2H8C6.9391,2 5.9217,2.4212 5.1716,3.1714C4.4214,3.9215 4,4.9391 4,6V20C4,20.5304 4.2107,21.039 4.5858,21.4141C4.9609,21.7891 5.4696,22 6,22H18C18.5304,22 19.0391,21.7891 19.4142,21.4141C19.7893,21.039 20,20.5304 20,20V6C20,4.9391 19.5786,3.9215 18.8284,3.1714C18.0783,2.4212 17.0609,2 16,2ZM8.93,8.5278C8.9561,8.4957 8.9922,8.4736 9.0325,8.4644C9.0729,8.4551 9.1151,8.4591 9.1526,8.4766C9.1902,8.494 9.2208,8.5237 9.2397,8.5605C9.2586,8.5974 9.2647,8.6395 9.257,8.6802C9.1893,9.0625 9.1998,9.4544 9.2878,9.8325C9.3758,10.2106 9.5395,10.5668 9.769,10.8799C9.969,11.1669 10.203,11.0499 10.213,11.0459C10.2694,11.0204 10.3173,10.9792 10.351,10.9272C10.3847,10.8753 10.4027,10.8148 10.403,10.7529C10.403,10.6899 8.894,6.6532 12.651,5.0132C12.6848,4.9985 12.7223,4.994 12.7586,5.0005C12.7949,5.007 12.8285,5.0238 12.8551,5.0493C12.8817,5.0749 12.9002,5.108 12.9082,5.144C12.9162,5.1801 12.9133,5.2175 12.9,5.2519C12.741,5.7272 12.7178,6.2374 12.8332,6.7251C12.9486,7.2127 13.1979,7.6586 13.553,8.0122C13.909,8.3682 14.338,8.6121 14.704,8.9541C17.187,11.2821 15.604,15.4861 11.422,14.9541C10.7376,14.8371 10.0952,14.5448 9.5576,14.1055C9.0199,13.6662 8.6053,13.0946 8.3543,12.4473C8.1033,11.7999 8.0244,11.0986 8.1252,10.4116C8.2261,9.7247 8.5034,9.0756 8.93,8.5278ZM18,20H6V16C6.7396,15.9897 7.4619,16.2246 8.054,16.668C8.3188,16.8888 8.6527,17.0098 8.9975,17.0098C9.3423,17.0098 9.6762,16.8888 9.941,16.668C10.5357,16.2281 11.2558,15.9907 11.9955,15.9907C12.7352,15.9907 13.4553,16.2281 14.05,16.668C14.3161,16.889 14.6511,17.0103 14.997,17.0103C15.3429,17.0103 15.6779,16.889 15.944,16.668C16.5368,16.2244 17.2597,15.9896 18,16V20Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_window_off.xml b/packages/SystemUI/res/drawable/ic_device_window_off.xml
new file mode 100644
index 0000000..ea4af98
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_window_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,2H4C3.4701,2.0016 2.9623,2.2129 2.5875,2.5877C2.2128,2.9624 2.0016,3.4701 2,4V20C2.0016,20.5299 2.2128,21.0376 2.5875,21.4124C2.9623,21.7871 3.4701,21.9984 4,22H20C20.5299,21.9984 21.0377,21.7871 21.4125,21.4124C21.7872,21.0376 21.9984,20.5299 22,20V4C21.9984,3.4701 21.7872,2.9624 21.4125,2.5877C21.0377,2.2129 20.5299,2.0016 20,2ZM20,11H13V4H20V11ZM11,4V11H4V4H11ZM4,13H11V20H4V13ZM13,20V13H20V20H13Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_window_on.xml b/packages/SystemUI/res/drawable/ic_device_window_on.xml
new file mode 100644
index 0000000..ea4af98
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_window_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,2H4C3.4701,2.0016 2.9623,2.2129 2.5875,2.5877C2.2128,2.9624 2.0016,3.4701 2,4V20C2.0016,20.5299 2.2128,21.0376 2.5875,21.4124C2.9623,21.7871 3.4701,21.9984 4,22H20C20.5299,21.9984 21.0377,21.7871 21.4125,21.4124C21.7872,21.0376 21.9984,20.5299 22,20V4C21.9984,3.4701 21.7872,2.9624 21.4125,2.5877C21.0377,2.2129 20.5299,2.0016 20,2ZM20,11H13V4H20V11ZM11,4V11H4V4H11ZM4,13H11V20H4V13ZM13,20V13H20V20H13Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml
deleted file mode 100644
index 78c3cc5..0000000
--- a/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M9,21v-1h6v1c0,0.55 -0.45,1 -1,1h-4c-0.55,0 -1,-0.45 -1,-1z"/>
- <group>
- <clip-path android:pathData="M0,0h24v24H0z M 0,0"/>
- </group>
- <path
- android:fillColor="#FF000000"
- android:pathData="M12,2c-1.89,0 -3.6,0.75 -4.86,1.97l1.41,1.41C9.45,4.53 10.67,4 12,4c2.76,0 5,2.24 5,5 0,1.28 -0.5,2.5 -1.36,3.42l-0.02,0.02 1.41,1.41C18.25,12.6 19,10.89 19,9c0,-3.86 -3.14,-7 -7,-7z"
- android:fillType="evenOdd"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M2.92,2.29L1.65,3.57l3.59,3.59C5.09,7.75 5,8.36 5,9c0,2.38 1.19,4.47 3,5.74V17c0,0.55 0.45,1 1,1h6c0.3,0 0.57,-0.13 0.75,-0.34L20.09,22l1.27,-1.27L2.92,2.29zM10,16v-2.3l-0.85,-0.6C7.8,12.16 7,10.63 7,9v-0.08L14.09,16H10z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lightbulb_outline_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lightbulb_outline_gm2_24px.xml
deleted file mode 100644
index 87684a3..0000000
--- a/packages/SystemUI/res/drawable/ic_lightbulb_outline_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M9,21c0,0.55 0.45,1 1,1h4c0.55,0 1,-0.45 1,-1v-1L9,20v1zM12,2C8.14,2 5,5.14 5,9c0,2.38 1.19,4.47 3,5.74L8,17c0,0.55 0.45,1 1,1h6c0.55,0 1,-0.45 1,-1v-2.26c1.81,-1.27 3,-3.36 3,-5.74 0,-3.86 -3.14,-7 -7,-7zM14.85,13.1l-0.85,0.6L14,16h-4v-2.3l-0.85,-0.6C7.8,12.16 7,10.63 7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,1.63 -0.8,3.16 -2.15,4.1z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml
deleted file mode 100644
index f4299e6..0000000
--- a/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM9,6c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2L9,8L9,6zM18,20L6,20L6,10h12v10zM12,17c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml
deleted file mode 100644
index 59fe0a9..0000000
--- a/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6h2c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM18,20L6,20L6,10h12v10z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml
deleted file mode 100644
index cd95719..0000000
--- a/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M16,9v4.66l-3.5,3.51V19h-1v-1.83L8,13.65V9h8m0,-6h-2v4h-4V3H8v4h-0.01C6.9,6.99 6,7.89 6,8.98v5.52L9.5,18v3h5v-3l3.5,-3.51V9c0,-1.1 -0.9,-2 -2,-2V3z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml
deleted file mode 100644
index 3eb7dd6..0000000
--- a/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M21.19,21.19L2.81,2.81 1.39,4.22l4.63,4.63L6,14.5 9.5,18v3h5v-3l0.34,-0.34 4.94,4.94 1.41,-1.41zM12.5,17.17L12.5,19h-1v-1.83L8,13.65v-2.83l5.42,5.42 -0.92,0.93zM11.83,9L8,5.17L8,3h2v4h4L14,3h2v4c1.1,0 2,0.9 2,2v5.49l-0.34,0.34L16,13.17L16,9h-4.17z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml
deleted file mode 100644
index bb535ce..0000000
--- a/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M19,9h-8.02C10.06,7.79 8.63,7 7,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5c1.63,0 3.06,-0.79 3.98,-2H19c1.66,0 3,-1.34 3,-3S20.66,9 19,9zM19,13h-7.1c0.07,-0.32 0.1,-0.66 0.1,-1s-0.04,-0.68 -0.1,-1H19c0.55,0 1,0.45 1,1S19.55,13 19,13z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml
deleted file mode 100644
index 86b9591..0000000
--- a/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M4,16c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3zM4,20c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM23,20v2h-7v-2h2.49L12.01,4.59C11.6,3.63 10.66,3 9.61,3 8.17,3 7,4.17 7,5.61L7,9h2c2.21,0 4,1.79 4,4v9L7.99,22c0.44,-0.58 0.76,-1.26 0.91,-2L11,20v-7c0,-1.1 -0.9,-2 -2,-2L4,11v3c-0.71,0 -1.39,0.15 -2,0.42L2,9h3L5,5.61C5,3.07 7.07,1 9.61,1c1.86,0 3.53,1.11 4.25,2.82L20.66,20L23,20z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml
deleted file mode 100644
index 687c9c4..0000000
--- a/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,10.48L18,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-4.48l4,3.98v-11l-4,3.98zM16,9.69L16,18L4,18L4,6h12v3.69z"/>
-</vector>
diff --git a/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
index e791c8a..19a85fe 100644
--- a/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
+++ b/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
@@ -48,11 +48,7 @@
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:layout_marginTop="8dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Subtitle"/>
<TextView
android:id="@+id/description"
@@ -69,10 +65,7 @@
android:id="@+id/error"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/colorError"/>
+ style="@style/TextAppearance.AuthCredential.Error"/>
<Space
android:layout_width="0dp"
diff --git a/packages/SystemUI/res/layout/auth_biometric_contents.xml b/packages/SystemUI/res/layout/auth_biometric_contents.xml
index a1006a8..6b61046 100644
--- a/packages/SystemUI/res/layout/auth_biometric_contents.xml
+++ b/packages/SystemUI/res/layout/auth_biometric_contents.xml
@@ -18,34 +18,24 @@
<TextView
android:id="@+id/title"
- android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingHorizontal="24dp"
- android:paddingTop="24dp"
android:gravity="@integer/biometric_dialog_text_gravity"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Title"/>
<TextView
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingTop="8dp"
- android:paddingHorizontal="24dp"
android:gravity="@integer/biometric_dialog_text_gravity"
- android:textSize="16sp"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Subtitle"/>
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingHorizontal="24dp"
- android:paddingTop="8dp"
android:gravity="@integer/biometric_dialog_text_gravity"
- android:textSize="16sp"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Description"/>
<ImageView
android:id="@+id/biometric_icon"
diff --git a/packages/SystemUI/res/layout/auth_credential_password_view.xml b/packages/SystemUI/res/layout/auth_credential_password_view.xml
index b14bc7d..45638ce 100644
--- a/packages/SystemUI/res/layout/auth_credential_password_view.xml
+++ b/packages/SystemUI/res/layout/auth_credential_password_view.xml
@@ -42,11 +42,7 @@
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:layout_marginTop="8dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Subtitle"/>
<TextView
android:id="@+id/description"
@@ -59,15 +55,6 @@
android:layout_height="0dp"
android:layout_weight="1"/>
- <TextView
- android:id="@+id/error"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/colorError"/>
-
<EditText
android:id="@+id/lockPassword"
android:layout_width="208dp"
@@ -80,6 +67,12 @@
android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii"
style="@style/TextAppearance.AuthCredential.PasswordEntry"/>
+ <TextView
+ android:id="@+id/error"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/TextAppearance.AuthCredential.Error"/>
+
<Space
android:layout_width="0dp"
android:layout_height="0dp"
diff --git a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
index eda5ecb..4939ea2 100644
--- a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
+++ b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
@@ -42,11 +42,7 @@
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:layout_marginTop="8dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Subtitle"/>
<TextView
android:id="@+id/description"
@@ -89,10 +85,7 @@
android:id="@+id/error"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/colorError"/>
+ style="@style/TextAppearance.AuthCredential.Error"/>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml
index 6e1fd20..b83e500 100644
--- a/packages/SystemUI/res/layout/controls_base_item.xml
+++ b/packages/SystemUI/res/layout/controls_base_item.xml
@@ -50,6 +50,7 @@
app:layout_constraintBottom_toBottomOf="@+id/icon"
app:layout_constraintStart_toEndOf="@+id/icon" />
+
<TextView
android:id="@+id/status_extra"
android:layout_width="wrap_content"
@@ -64,7 +65,7 @@
<TextView
android:id="@+id/title"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Control.Title"
android:paddingLeft="@dimen/control_padding_adjustment"
@@ -73,12 +74,20 @@
android:focusable="false"
android:maxLines="1"
android:ellipsize="end"
- app:layout_constraintBottom_toTopOf="@+id/subtitle"
- app:layout_constraintStart_toStartOf="parent" />
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/barrier"/>
+
+ <androidx.constraintlayout.widget.Barrier
+ android:id="@+id/barrier"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:barrierDirection="top"
+ app:constraint_referenced_ids="subtitle,favorite" />
<TextView
android:id="@+id/subtitle"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Control.Subtitle"
android:paddingLeft="@dimen/control_padding_adjustment"
@@ -88,24 +97,22 @@
android:focusable="false"
android:maxLines="1"
android:ellipsize="end"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/favorite"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"/>
+ />
- <FrameLayout
- android:id="@+id/favorite_container"
+ <CheckBox
+ android:id="@+id/favorite"
android:visibility="gone"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|end"
+ android:button="@drawable/controls_btn_star"
+ android:layout_marginTop="4dp"
+ android:layout_marginStart="4dp"
+ app:layout_constraintStart_toEndOf="@id/subtitle"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toBottomOf="parent">
-
- <CheckBox
- android:id="@+id/favorite"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom|end"
- android:button="@drawable/controls_btn_star"/>
- </FrameLayout>
-
+ app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
index 1d6c751..91beeb8 100644
--- a/packages/SystemUI/res/layout/controls_with_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -14,26 +14,29 @@
~ limitations under the License.
-->
<merge
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+ xmlns:android="http://schemas.android.com/apk/res/android">
- <androidx.constraintlayout.widget.ConstraintLayout
+ <LinearLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/controls_top_margin">
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:layout_marginTop="@dimen/controls_top_margin"
+ android:layout_marginEnd="@dimen/controls_header_side_margin"
+ android:layout_marginStart="@dimen/controls_header_side_margin">
+
+ <!-- make sure the header stays centered in the layout by adding a spacer -->
+ <Space
+ android:layout_width="@dimen/controls_header_menu_size"
+ android:layout_height="1dp" />
<LinearLayout
android:id="@+id/controls_header"
android:orientation="horizontal"
- android:layout_width="match_parent"
+ android:layout_width="0dp"
+ android:layout_weight="1"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/controls_header_side_margin"
- android:layout_marginEnd="@dimen/controls_header_side_margin"
- android:gravity="center"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent" >
+ android:layout_gravity="center"
+ android:gravity="center">
<ImageView
android:id="@+id/app_icon"
@@ -54,16 +57,14 @@
<ImageView
android:id="@+id/controls_more"
android:src="@drawable/ic_more_vert"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="@dimen/controls_header_menu_size"
+ android:layout_height="@dimen/controls_header_menu_size"
android:padding="12dp"
- android:layout_marginEnd="@dimen/controls_list_side_margin"
android:tint="@color/control_more_vert"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintRight_toRightOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
-
- </androidx.constraintlayout.widget.ConstraintLayout>
+ android:layout_gravity="center"
+ android:contentDescription="@string/accessibility_menu"
+ android:background="?android:attr/selectableItemBackgroundBorderless" />
+ </LinearLayout>
<LinearLayout
android:id="@+id/global_actions_controls_list"
diff --git a/packages/SystemUI/res/values-television/dimens.xml b/packages/SystemUI/res/values-television/dimens.xml
new file mode 100644
index 0000000..6da0c69
--- /dev/null
+++ b/packages/SystemUI/res/values-television/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+ <!-- Opacity at which the background for the shutdown UI will be drawn. -->
+ <item name="shutdown_scrim_behind_alpha" format="float" type="dimen">1.0</item>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-television/styles.xml b/packages/SystemUI/res/values-television/styles.xml
index b59f007..b01c5d8 100644
--- a/packages/SystemUI/res/values-television/styles.xml
+++ b/packages/SystemUI/res/values-television/styles.xml
@@ -17,4 +17,9 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Dialog" />
<style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Dialog.Alert" />
+
+ <style name="Animation.ShutdownUi">
+ <item name="android:windowEnterAnimation">@null</item>
+ <item name="android:windowExitAnimation">@null</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ee7f523..23be78b 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1219,7 +1219,8 @@
<dimen name="magnifier_up_down_controls_height">40dp</dimen>
<!-- Home Controls -->
- <dimen name="controls_header_side_margin">32dp</dimen>
+ <dimen name="controls_header_side_margin">4dp</dimen>
+ <dimen name="controls_header_menu_size">48dp</dimen>
<dimen name="controls_header_app_icon_size">40dp</dimen>
<dimen name="controls_list_side_margin">16dp</dimen>
<dimen name="controls_top_margin">44dp</dimen>
@@ -1266,4 +1267,7 @@
<dimen name="screenrecord_status_icon_radius">5dp</dimen>
<dimen name="kg_user_switcher_text_size">16sp</dimen>
+
+ <!-- Opacity at which the background for the shutdown UI will be drawn. -->
+ <item name="shutdown_scrim_behind_alpha" format="float" type="dimen">0.95</item>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8a3a16e..d17b81d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1151,15 +1151,6 @@
<!-- Name for a freshly added user [CHAR LIMIT=30] -->
<string name="user_new_user_name">New user</string>
- <!-- Name for the guest user [CHAR LIMIT=35] -->
- <string name="guest_nickname">Guest</string>
-
- <!-- Label for adding a new guest in the user switcher [CHAR LIMIT=35] -->
- <string name="guest_new_guest">Add guest</string>
-
- <!-- Label for exiting and removing the guest session in the user switcher [CHAR LIMIT=35] -->
- <string name="guest_exit_guest">Remove guest</string>
-
<!-- Title of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
<string name="guest_exit_guest_dialog_title">Remove guest?</string>
@@ -2687,9 +2678,9 @@
<!-- Controls management controls screen header for Other zone [CHAR LIMIT=60] -->
<string name="controls_favorite_other_zone_header">Other</string>
- <!-- Controls dialog title [CHAR LIMIT=30] -->
+ <!-- Controls dialog title [CHAR LIMIT=40] -->
<string name="controls_dialog_title">Add to quick controls</string>
- <!-- Controls dialog add to favorites [CHAR LIMIT=30] -->
+ <!-- Controls dialog add to favorites [CHAR LIMIT=40] -->
<string name="controls_dialog_ok">Add to favorites</string>
<!-- Controls dialog message [CHAR LIMIT=NONE] -->
<string name="controls_dialog_message"><xliff:g id="app" example="System UI">%s</xliff:g> suggested this control to add to your favorites.</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 1233d4d..1598465 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -250,28 +250,39 @@
<style name="TextAppearance.AuthCredential">
<item name="android:gravity">center_horizontal</item>
- <item name="android:fontFamily">google-sans</item>
<item name="android:textAlignment">gravity</item>
<item name="android:layout_gravity">top</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="TextAppearance.AuthCredential.Title">
- <item name="android:layout_marginBottom">2dp</item>
- <item name="android:layout_marginLeft">24dp</item>
- <item name="android:layout_marginRight">24dp</item>
- <item name="android:layout_marginTop">16dp</item>
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:paddingTop">16dp</item>
+ <item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">24sp</item>
</style>
- <style name="TextAppearance.AuthCredential.Description">
- <item name="android:layout_marginBottom">12dp</item>
- <item name="android:layout_marginStart">40dp</item>
- <item name="android:layout_marginEnd">40dp</item>
- <item name="android:layout_marginTop">3dp</item>
+ <style name="TextAppearance.AuthCredential.Subtitle">
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:paddingTop">8dp</item>
+ <item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">16sp</item>
</style>
+ <style name="TextAppearance.AuthCredential.Description">
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:paddingTop">8dp</item>
+ <item name="android:paddingHorizontal">24dp</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+
+ <style name="TextAppearance.AuthCredential.Error">
+ <item name="android:paddingTop">12dp</item>
+ <item name="android:paddingHorizontal">24dp</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textColor">?android:attr/colorError</item>
+ </style>
+
<style name="TextAppearance.AuthCredential.PasswordEntry" parent="@android:style/TextAppearance.DeviceDefault">
<item name="android:gravity">center</item>
<item name="android:singleLine">true</item>
@@ -305,6 +316,9 @@
<item name="android:windowExitAnimation">@null</item>
</style>
+ <style name="Animation.ShutdownUi" parent="@android:style/Animation.Toast">
+ </style>
+
<!-- Standard animations for hiding and showing the status bar. -->
<style name="Animation.StatusBar">
</style>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java
index 360244c..34a0268 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java
@@ -74,16 +74,9 @@
}
@Override
- public void onSaveReentryBounds(ComponentName componentName, Rect bounds) {
+ public void onActivityHidden(ComponentName componentName) {
for (PinnedStackListener listener : mListeners) {
- listener.onSaveReentryBounds(componentName, bounds);
- }
- }
-
- @Override
- public void onResetReentryBounds(ComponentName componentName) {
- for (PinnedStackListener listener : mListeners) {
- listener.onResetReentryBounds(componentName);
+ listener.onActivityHidden(componentName);
}
}
@@ -121,9 +114,7 @@
public void onActionsChanged(ParceledListSlice actions) {}
- public void onSaveReentryBounds(ComponentName componentName, Rect bounds) {}
-
- public void onResetReentryBounds(ComponentName componentName) {}
+ public void onActivityHidden(ComponentName componentName) {}
public void onDisplayInfoChanged(DisplayInfo displayInfo) {}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 0018d33..b736b4d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricConstants;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -207,6 +208,7 @@
animateAway(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED);
break;
case AuthBiometricView.Callback.ACTION_USER_CANCELED:
+ sendEarlyUserCanceled();
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
break;
case AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE:
@@ -286,11 +288,13 @@
addView(mFrameLayout);
+ // TODO: De-dupe the logic with AuthCredentialPasswordView
setOnKeyListener((v, keyCode, event) -> {
if (keyCode != KeyEvent.KEYCODE_BACK) {
return false;
}
if (event.getAction() == KeyEvent.ACTION_UP) {
+ sendEarlyUserCanceled();
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
}
return true;
@@ -300,6 +304,11 @@
requestFocus();
}
+ void sendEarlyUserCanceled() {
+ mConfig.mCallback.onSystemEvent(
+ BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL);
+ }
+
@Override
public boolean isAllowDeviceCredentials() {
return Utils.isDeviceCredentialAllowed(mConfig.mBiometricPromptBundle);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index c30477c..0c6794c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -165,6 +165,19 @@
}
@Override
+ public void onSystemEvent(int event) {
+ if (mReceiver == null) {
+ Log.e(TAG, "onSystemEvent(" + event + "): Receiver is null");
+ return;
+ }
+ try {
+ mReceiver.onSystemEvent(event);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException when sending system event", e);
+ }
+ }
+
+ @Override
public void onDismissed(@DismissedReason int reason, @Nullable byte[] credentialAttestation) {
switch (reason) {
case AuthDialogCallback.DISMISSED_USER_CANCELED:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
index b986f6c..d8a11d3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
@@ -51,11 +51,13 @@
super.onFinishInflate();
mPasswordField = findViewById(R.id.lockPassword);
mPasswordField.setOnEditorActionListener(this);
+ // TODO: De-dupe the logic with AuthContainerView
mPasswordField.setOnKeyListener((v, keyCode, event) -> {
if (keyCode != KeyEvent.KEYCODE_BACK) {
return false;
}
if (event.getAction() == KeyEvent.ACTION_UP) {
+ mContainerView.sendEarlyUserCanceled();
mContainerView.animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
}
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
index a47621d..d3bd4fb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
@@ -58,4 +58,11 @@
* Invoked when the "use password" button is clicked
*/
void onDeviceCredentialPressed();
+
+ /**
+ * See {@link android.hardware.biometrics.BiometricPrompt.Builder
+ * #setReceiveSystemEvents(boolean)}
+ * @param event
+ */
+ void onSystemEvent(int event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
index a1cb7f6..55be77c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
@@ -28,6 +28,8 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import java.util.EnumSet;
+
/**
* View that displays an adaptive icon with an app-badge and a dot.
*
@@ -42,12 +44,27 @@
/** Same as value in Launcher3 IconShape */
public static final int DEFAULT_PATH_SIZE = 100;
- static final int DOT_STATE_DEFAULT = 0;
- static final int DOT_STATE_SUPPRESSED_FOR_FLYOUT = 1;
- static final int DOT_STATE_ANIMATING = 2;
+ /**
+ * Flags that suppress the visibility of the 'new' dot, for one reason or another. If any of
+ * these flags are set, the dot will not be shown even if {@link Bubble#showDot()} returns true.
+ */
+ enum SuppressionFlag {
+ // Suppressed because the flyout is visible - it will morph into the dot via animation.
+ FLYOUT_VISIBLE,
+ // Suppressed because this bubble is behind others in the collapsed stack.
+ BEHIND_STACK,
+ }
- // Flyout gets shown before the dot
- private int mCurrentDotState = DOT_STATE_SUPPRESSED_FOR_FLYOUT;
+ /**
+ * Start by suppressing the dot because the flyout is visible - most bubbles are added with a
+ * flyout, so this is a reasonable default.
+ */
+ private final EnumSet<SuppressionFlag> mDotSuppressionFlags =
+ EnumSet.of(SuppressionFlag.FLYOUT_VISIBLE);
+
+ private float mDotScale = 0f;
+ private float mAnimatingToDotScale = 0f;
+ private boolean mDotIsAnimating = false;
private BubbleViewProvider mBubble;
@@ -57,8 +74,6 @@
private boolean mOnLeft;
private int mDotColor;
- private float mDotScale = 0f;
- private boolean mDotDrawn;
private Rect mTempBounds = new Rect();
@@ -83,28 +98,28 @@
Path iconPath = PathParser.createPathFromPathData(
getResources().getString(com.android.internal.R.string.config_icon_mask));
mDotRenderer = new DotRenderer(mBubbleBitmapSize, iconPath, DEFAULT_PATH_SIZE);
+
+ setFocusable(true);
}
/**
* Updates the view with provided info.
*/
- public void update(BubbleViewProvider bubble) {
+ public void setRenderedBubble(BubbleViewProvider bubble) {
mBubble = bubble;
setImageBitmap(bubble.getBadgedImage());
- setDotState(DOT_STATE_SUPPRESSED_FOR_FLYOUT);
mDotColor = bubble.getDotColor();
drawDot(bubble.getDotPath());
- animateDot();
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
- if (isDotHidden()) {
- mDotDrawn = false;
+
+ if (!shouldDrawDot()) {
return;
}
- mDotDrawn = mDotScale > 0.1f;
+
getDrawingRect(mTempBounds);
mDrawParams.color = mDotColor;
@@ -115,23 +130,33 @@
mDotRenderer.draw(canvas, mDrawParams);
}
- /**
- * Sets the dot state, does not animate changes.
- */
- void setDotState(int state) {
- mCurrentDotState = state;
- if (state == DOT_STATE_SUPPRESSED_FOR_FLYOUT || state == DOT_STATE_DEFAULT) {
- mDotScale = mBubble.showDot() ? 1f : 0f;
- invalidate();
+ /** Adds a dot suppression flag, updating dot visibility if needed. */
+ void addDotSuppressionFlag(SuppressionFlag flag) {
+ if (mDotSuppressionFlags.add(flag)) {
+ // Update dot visibility, and animate out if we're now behind the stack.
+ updateDotVisibility(flag == SuppressionFlag.BEHIND_STACK /* animate */);
}
}
- /**
- * Whether the dot should be hidden based on current dot state.
- */
- private boolean isDotHidden() {
- return (mCurrentDotState == DOT_STATE_DEFAULT && !mBubble.showDot())
- || mCurrentDotState == DOT_STATE_SUPPRESSED_FOR_FLYOUT;
+ /** Removes a dot suppression flag, updating dot visibility if needed. */
+ void removeDotSuppressionFlag(SuppressionFlag flag) {
+ if (mDotSuppressionFlags.remove(flag)) {
+ // Update dot visibility, animating if we're no longer behind the stack.
+ updateDotVisibility(flag == SuppressionFlag.BEHIND_STACK);
+ }
+ }
+
+ /** Updates the visibility of the dot, animating if requested. */
+ void updateDotVisibility(boolean animate) {
+ final float targetScale = shouldDrawDot() ? 1f : 0f;
+
+ if (animate) {
+ animateDotScale(targetScale, null /* after */);
+ } else {
+ mDotScale = targetScale;
+ mAnimatingToDotScale = targetScale;
+ invalidate();
+ }
}
/**
@@ -194,11 +219,11 @@
}
/** Sets the position of the 'new' dot, animating it out and back in if requested. */
- void setDotPosition(boolean onLeft, boolean animate) {
- if (animate && onLeft != getDotOnLeft() && !isDotHidden()) {
- animateDot(false /* showDot */, () -> {
+ void setDotPositionOnLeft(boolean onLeft, boolean animate) {
+ if (animate && onLeft != getDotOnLeft() && shouldDrawDot()) {
+ animateDotScale(0f /* showDot */, () -> {
setDotOnLeft(onLeft);
- animateDot(true /* showDot */, null);
+ animateDotScale(1.0f, null /* after */);
});
} else {
setDotOnLeft(onLeft);
@@ -209,28 +234,34 @@
return getDotOnLeft();
}
- /** Changes the dot's visibility to match the bubble view's state. */
- void animateDot() {
- if (mCurrentDotState == DOT_STATE_DEFAULT) {
- animateDot(mBubble.showDot(), null);
- }
+ /** Whether to draw the dot in onDraw(). */
+ private boolean shouldDrawDot() {
+ // Always render the dot if it's animating, since it could be animating out. Otherwise, show
+ // it if the bubble wants to show it, and we aren't suppressing it.
+ return mDotIsAnimating || (mBubble.showDot() && mDotSuppressionFlags.isEmpty());
}
/**
- * Animates the dot to show or hide.
+ * Animates the dot to the given scale, running the optional callback when the animation ends.
*/
- private void animateDot(boolean showDot, Runnable after) {
- if (mDotDrawn == showDot) {
- // State is consistent, do nothing.
+ private void animateDotScale(float toScale, @Nullable Runnable after) {
+ mDotIsAnimating = true;
+
+ // Don't restart the animation if we're already animating to the given value.
+ if (mAnimatingToDotScale == toScale || !shouldDrawDot()) {
+ mDotIsAnimating = false;
return;
}
- setDotState(DOT_STATE_ANIMATING);
+ mAnimatingToDotScale = toScale;
+
+ final boolean showDot = toScale > 0f;
// Do NOT wait until after animation ends to setShowDot
// to avoid overriding more recent showDot states.
clearAnimation();
- animate().setDuration(200)
+ animate()
+ .setDuration(200)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.setUpdateListener((valueAnimator) -> {
float fraction = valueAnimator.getAnimatedFraction();
@@ -238,7 +269,7 @@
setDotScale(fraction);
}).withEndAction(() -> {
setDotScale(showDot ? 1f : 0f);
- setDotState(DOT_STATE_DEFAULT);
+ mDotIsAnimating = false;
if (after != null) {
after.run();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 726a7dd..71f2bc0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -76,7 +76,6 @@
private BadgedImageView mIconView;
private BubbleExpandedView mExpandedView;
- private boolean mInflated;
private BubbleViewInfoTask mInflationTask;
private boolean mInflateSynchronously;
@@ -166,10 +165,16 @@
return mExpandedView;
}
- void cleanupExpandedState() {
+ /**
+ * Call when the views should be removed, ensure this is called to clean up ActivityView
+ * content.
+ */
+ void cleanupViews() {
if (mExpandedView != null) {
mExpandedView.cleanUpExpandedState();
+ mExpandedView = null;
}
+ mIconView = null;
}
/**
@@ -213,17 +218,15 @@
}
boolean isInflated() {
- return mInflated;
+ return mIconView != null && mExpandedView != null;
}
void stopInflation() {
if (mInflationTask == null) {
return;
}
- mInflationTask.cancel(/* mayInterruptIfRunning */ true);
- mIconView = null;
- mExpandedView = null;
- mInflated = false;
+ mInflationTask.cancel(true /* mayInterruptIfRunning */);
+ cleanupViews();
}
void setViewInfo(BubbleViewInfoTask.BubbleViewInfo info) {
@@ -240,21 +243,14 @@
mDotColor = info.dotColor;
mDotPath = info.dotPath;
- if (mExpandedView != null && mIconView != null) {
- mInflated = true;
- }
if (mExpandedView != null) {
mExpandedView.update(/* bubble */ this);
}
if (mIconView != null) {
- mIconView.update(/* bubble */ this);
+ mIconView.setRenderedBubble(/* bubble */ this);
}
}
- void setInflated(boolean inflated) {
- mInflated = inflated;
- }
-
/**
* Set visibility of bubble in the expanded state.
*
@@ -306,7 +302,7 @@
void markAsAccessedAt(long lastAccessedMillis) {
mLastAccessed = lastAccessedMillis;
setSuppressNotification(true);
- setShowDot(false /* show */, true /* animate */);
+ setShowDot(false /* show */);
}
/**
@@ -346,12 +342,11 @@
/**
* Sets whether the bubble for this notification should show a dot indicating updated content.
*/
- void setShowDot(boolean showDot, boolean animate) {
+ void setShowDot(boolean showDot) {
mShowBubbleUpdateDot = showDot;
- if (animate && mIconView != null) {
- mIconView.animateDot();
- } else if (mIconView != null) {
- mIconView.invalidate();
+
+ if (mIconView != null) {
+ mIconView.updateDotVisibility(true /* animate */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 01c2faa..9d885fd 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -331,14 +331,14 @@
@Override
public void onZenChanged(int zen) {
for (Bubble b : mBubbleData.getBubbles()) {
- b.setShowDot(b.showInShade(), true /* animate */);
+ b.setShowDot(b.showInShade());
}
}
@Override
public void onConfigChanged(ZenModeConfig config) {
for (Bubble b : mBubbleData.getBubbles()) {
- b.setShowDot(b.showInShade(), true /* animate */);
+ b.setShowDot(b.showInShade());
}
}
});
@@ -1101,7 +1101,7 @@
} else if (interceptBubbleDismissal) {
Bubble bubble = mBubbleData.getBubbleWithKey(entry.getKey());
bubble.setSuppressNotification(true);
- bubble.setShowDot(false /* show */, true /* animate */);
+ bubble.setShowDot(false /* show */);
} else {
return false;
}
@@ -1141,7 +1141,7 @@
Bubble bubbleChild = mBubbleData.getBubbleWithKey(child.getKey());
mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry());
bubbleChild.setSuppressNotification(true);
- bubbleChild.setShowDot(false /* show */, true /* animate */);
+ bubbleChild.setShowDot(false /* show */);
} else {
// non-bubbled children can be removed
for (NotifCallback cb : mCallbacks) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 2bd1518..1c69594 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -288,7 +288,7 @@
boolean isBubbleExpandedAndSelected = mExpanded && mSelectedBubble == bubble;
boolean suppress = isBubbleExpandedAndSelected || !showInShade || !bubble.showInShade();
bubble.setSuppressNotification(suppress);
- bubble.setShowDot(!isBubbleExpandedAndSelected /* show */, true /* animate */);
+ bubble.setShowDot(!isBubbleExpandedAndSelected /* show */);
dispatchPendingChanges();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
index 4fb2d08..13669a6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
@@ -112,7 +112,7 @@
mPath.transform(matrix);
mOverflowBtn.setVisibility(GONE);
- mOverflowBtn.update(this);
+ mOverflowBtn.setRenderedBubble(this);
}
ImageView getBtn() {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index b651985..2231d11 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -183,7 +183,7 @@
public void onBindViewHolder(ViewHolder vh, int index) {
Bubble b = mBubbles.get(index);
- vh.iconView.update(b);
+ vh.iconView.setRenderedBubble(b);
vh.iconView.setOnClickListener(view -> {
mBubbles.remove(b);
notifyDataSetChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 7191a20..6fd6b8d 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -22,8 +22,6 @@
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.systemui.Prefs.Key.HAS_SEEN_BUBBLES_EDUCATION;
import static com.android.systemui.Prefs.Key.HAS_SEEN_BUBBLES_MANAGE_EDUCATION;
-import static com.android.systemui.bubbles.BadgedImageView.DOT_STATE_DEFAULT;
-import static com.android.systemui.bubbles.BadgedImageView.DOT_STATE_SUPPRESSED_FOR_FLYOUT;
import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_STACK_VIEW;
import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_USER_EDUCATION;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
@@ -226,7 +224,7 @@
private boolean mIsExpanded;
/** Whether the stack is currently on the left side of the screen, or animating there. */
- private boolean mStackOnLeftOrWillBe = false;
+ private boolean mStackOnLeftOrWillBe = true;
/** Whether a touch gesture, such as a stack/bubble drag or flyout drag, is in progress. */
private boolean mIsGestureInProgress = false;
@@ -936,9 +934,13 @@
mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
}
+ if (bubble.getIconView() == null) {
+ return;
+ }
+
// Set the dot position to the opposite of the side the stack is resting on, since the stack
// resting slightly off-screen would result in the dot also being off-screen.
- bubble.getIconView().setDotPosition(
+ bubble.getIconView().setDotPositionOnLeft(
!mStackOnLeftOrWillBe /* onLeft */, false /* animate */);
mBubbleContainer.addView(bubble.getIconView(), 0,
@@ -961,8 +963,7 @@
if (v instanceof BadgedImageView
&& ((BadgedImageView) v).getKey().equals(bubble.getKey())) {
mBubbleContainer.removeViewAt(i);
- bubble.cleanupExpandedState();
- bubble.setInflated(false);
+ bubble.cleanupViews();
logBubbleEvent(bubble, SysUiStatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
return;
}
@@ -1698,7 +1699,7 @@
|| mBubbleToExpandAfterFlyoutCollapse != null
|| bubbleView == null) {
if (bubbleView != null) {
- bubbleView.setDotState(DOT_STATE_DEFAULT);
+ bubbleView.removeDotSuppressionFlag(BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
}
// Skip the message if none exists, we're expanded or animating expansion, or we're
// about to expand a bubble from the previous tapped flyout, or if bubble view is null.
@@ -1717,12 +1718,16 @@
mBubbleData.setExpanded(true);
mBubbleToExpandAfterFlyoutCollapse = null;
}
- bubbleView.setDotState(DOT_STATE_DEFAULT);
+
+ // Stop suppressing the dot now that the flyout has morphed into the dot.
+ bubbleView.removeDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
};
mFlyout.setVisibility(INVISIBLE);
- // Don't show the dot when we're animating the flyout
- bubbleView.setDotState(DOT_STATE_SUPPRESSED_FOR_FLYOUT);
+ // Suppress the dot when we are animating the flyout.
+ bubbleView.addDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
// Start flyout expansion. Post in case layout isn't complete and getWidth returns 0.
post(() -> {
@@ -1743,6 +1748,11 @@
};
mFlyout.postDelayed(mAnimateInFlyout, 200);
};
+
+ if (bubble.getIconView() == null) {
+ return;
+ }
+
mFlyout.setupFlyoutStartingAsDot(flyoutMessage,
mStackAnimationController.getStackPosition(), getWidth(),
mStackAnimationController.isStackOnLeftSide(),
@@ -1877,9 +1887,19 @@
for (int i = 0; i < bubbleCount; i++) {
BadgedImageView bv = (BadgedImageView) mBubbleContainer.getChildAt(i);
bv.setZ((mMaxBubbles * mBubbleElevation) - i);
+
// If the dot is on the left, and so is the stack, we need to change the dot position.
if (bv.getDotPositionOnLeft() == mStackOnLeftOrWillBe) {
- bv.setDotPosition(!mStackOnLeftOrWillBe, animate);
+ bv.setDotPositionOnLeft(!mStackOnLeftOrWillBe, animate);
+ }
+
+ if (!mIsExpanded && i > 0) {
+ // If we're collapsed and this bubble is behind other bubbles, suppress its dot.
+ bv.addDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.BEHIND_STACK);
+ } else {
+ bv.removeDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.BEHIND_STACK);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 7ee162e..00de8b4 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -287,7 +287,7 @@
/** Whether the stack is on the left side of the screen. */
public boolean isStackOnLeftSide() {
if (mLayout == null || !isStackPositionSet()) {
- return false;
+ return true; // Default to left, which is where it starts by default.
}
float stackCenter = mStackPosition.x + mBubbleBitmapSize / 2;
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 118fcbb..fdb0e4c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -65,7 +65,7 @@
companion object {
private const val TAG = "ControlsControllerImpl"
- internal const val CONTROLS_AVAILABLE = "systemui.controls_available"
+ internal const val CONTROLS_AVAILABLE = Settings.Secure.CONTROLS_ENABLED
internal val URI = Settings.Secure.getUriFor(CONTROLS_AVAILABLE)
private const val USER_CHANGE_RETRY_DELAY = 500L // ms
private const val DEFAULT_ENABLED = 1
@@ -439,13 +439,14 @@
Log.d(TAG, "Controls not available")
return
}
- executor.execute {
- val changed = Favorites.updateControls(
- componentName,
- listOf(control)
- )
- if (changed) {
- persistenceWrapper.storeFavorites(Favorites.getAllStructures())
+
+ // Assume that non STATUS_OK responses may contain incomplete or invalid information about
+ // the control, and do not attempt to update it
+ if (control.getStatus() == Control.STATUS_OK) {
+ executor.execute {
+ if (Favorites.updateControls(componentName, listOf(control))) {
+ persistenceWrapper.storeFavorites(Favorites.getAllStructures())
+ }
}
}
uiController.onRefreshState(componentName, listOf(control))
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
index 563c2f6..764fda0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
@@ -68,6 +68,8 @@
width = ViewGroup.LayoutParams.MATCH_PARENT
}
elevation = this@ControlAdapter.elevation
+ background = parent.context.getDrawable(
+ R.drawable.control_background_ripple)
}
) { id, favorite ->
model?.changeFavoriteStatus(id, favorite)
@@ -137,10 +139,7 @@
private val title: TextView = itemView.requireViewById(R.id.title)
private val subtitle: TextView = itemView.requireViewById(R.id.subtitle)
private val removed: TextView = itemView.requireViewById(R.id.status)
- private val favorite: CheckBox = itemView.requireViewById<CheckBox>(R.id.favorite)
- private val favoriteFrame: ViewGroup = itemView
- .requireViewById<ViewGroup>(R.id.favorite_container)
- .apply {
+ private val favorite: CheckBox = itemView.requireViewById<CheckBox>(R.id.favorite).apply {
visibility = View.VISIBLE
}
@@ -155,7 +154,7 @@
favorite.setOnClickListener {
favoriteCallback(data.control.controlId, favorite.isChecked)
}
- favoriteFrame.setOnClickListener { favorite.performClick() }
+ itemView.setOnClickListener { favorite.performClick() }
applyRenderInfo(renderInfo)
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
index 810ea65..d33cd94 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
@@ -110,60 +110,160 @@
private val deviceIconMap = mapOf<Int, IconState>(
THERMOSTAT_RANGE to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
(THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_OFF) to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
(THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT) to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
(THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_COOL) to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
(THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT_COOL) to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
(THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_ECO) to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
DeviceTypes.TYPE_THERMOSTAT to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
DeviceTypes.TYPE_LIGHT to IconState(
- R.drawable.ic_light_off_gm2_24px,
- R.drawable.ic_lightbulb_outline_gm2_24px
+ R.drawable.ic_device_light_off,
+ R.drawable.ic_device_light_on
),
DeviceTypes.TYPE_CAMERA to IconState(
- R.drawable.ic_videocam_gm2_24px,
- R.drawable.ic_videocam_gm2_24px
+ R.drawable.ic_device_camera_off,
+ R.drawable.ic_device_camera_on
),
DeviceTypes.TYPE_LOCK to IconState(
- R.drawable.ic_lock_open_gm2_24px,
- R.drawable.ic_lock_gm2_24px
+ R.drawable.ic_device_lock_off,
+ R.drawable.ic_device_lock_on
),
DeviceTypes.TYPE_SWITCH to IconState(
- R.drawable.ic_switches_gm2_24px,
- R.drawable.ic_switches_gm2_24px
+ R.drawable.ic_device_switch_off,
+ R.drawable.ic_device_switch_on
),
DeviceTypes.TYPE_OUTLET to IconState(
- R.drawable.ic_power_off_gm2_24px,
- R.drawable.ic_power_gm2_24px
+ R.drawable.ic_device_outlet_off,
+ R.drawable.ic_device_outlet_on
),
DeviceTypes.TYPE_VACUUM to IconState(
- R.drawable.ic_vacuum_gm2_24px,
- R.drawable.ic_vacuum_gm2_24px
+ R.drawable.ic_device_vacuum_off,
+ R.drawable.ic_device_vacuum_on
),
DeviceTypes.TYPE_MOP to IconState(
- R.drawable.ic_vacuum_gm2_24px,
- R.drawable.ic_vacuum_gm2_24px
+ R.drawable.ic_device_mop_off,
+ R.drawable.ic_device_mop_on
+ ),
+ DeviceTypes.TYPE_AIR_FRESHENER to IconState(
+ R.drawable.ic_device_air_freshener_off,
+ R.drawable.ic_device_air_freshener_on
+ ),
+ DeviceTypes.TYPE_AIR_PURIFIER to IconState(
+ R.drawable.ic_device_air_purifier_off,
+ R.drawable.ic_device_air_purifier_on
+ ),
+ DeviceTypes.TYPE_FAN to IconState(
+ R.drawable.ic_device_fan_off,
+ R.drawable.ic_device_fan_on
+ ),
+ DeviceTypes.TYPE_HOOD to IconState(
+ R.drawable.ic_device_hood_off,
+ R.drawable.ic_device_hood_on
+ ),
+ DeviceTypes.TYPE_KETTLE to IconState(
+ R.drawable.ic_device_kettle_off,
+ R.drawable.ic_device_kettle_on
+ ),
+ DeviceTypes.TYPE_MICROWAVE to IconState(
+ R.drawable.ic_device_microwave_off,
+ R.drawable.ic_device_microwave_on
+ ),
+ DeviceTypes.TYPE_REMOTE_CONTROL to IconState(
+ R.drawable.ic_device_remote_control_off,
+ R.drawable.ic_device_remote_control_on
+ ),
+ DeviceTypes.TYPE_SET_TOP to IconState(
+ R.drawable.ic_device_set_top_off,
+ R.drawable.ic_device_set_top_on
+ ),
+ DeviceTypes.TYPE_STYLER to IconState(
+ R.drawable.ic_device_styler_off,
+ R.drawable.ic_device_styler_on
+ ),
+ DeviceTypes.TYPE_TV to IconState(
+ R.drawable.ic_device_tv_off,
+ R.drawable.ic_device_tv_on
+ ),
+ DeviceTypes.TYPE_WATER_HEATER to IconState(
+ R.drawable.ic_device_water_heater_off,
+ R.drawable.ic_device_water_heater_on
+ ),
+ DeviceTypes.TYPE_DISHWASHER to IconState(
+ R.drawable.ic_device_dishwasher_off,
+ R.drawable.ic_device_dishwasher_on
+ ),
+ DeviceTypes.TYPE_MULTICOOKER to IconState(
+ R.drawable.ic_device_multicooker_off,
+ R.drawable.ic_device_multicooker_on
+ ),
+ DeviceTypes.TYPE_SPRINKLER to IconState(
+ R.drawable.ic_device_sprinkler_off,
+ R.drawable.ic_device_sprinkler_on
+ ),
+ DeviceTypes.TYPE_WASHER to IconState(
+ R.drawable.ic_device_washer_off,
+ R.drawable.ic_device_washer_on
+ ),
+ DeviceTypes.TYPE_BLINDS to IconState(
+ R.drawable.ic_device_blinds_off,
+ R.drawable.ic_device_blinds_on
+ ),
+ DeviceTypes.TYPE_DRAWER to IconState(
+ R.drawable.ic_device_drawer_off,
+ R.drawable.ic_device_drawer_on
+ ),
+ DeviceTypes.TYPE_GARAGE to IconState(
+ R.drawable.ic_device_garage_off,
+ R.drawable.ic_device_garage_on
+ ),
+ DeviceTypes.TYPE_GATE to IconState(
+ R.drawable.ic_device_gate_off,
+ R.drawable.ic_device_gate_on
+ ),
+ DeviceTypes.TYPE_PERGOLA to IconState(
+ R.drawable.ic_device_pergola_off,
+ R.drawable.ic_device_pergola_on
+ ),
+ DeviceTypes.TYPE_WINDOW to IconState(
+ R.drawable.ic_device_window_off,
+ R.drawable.ic_device_window_on
+ ),
+ DeviceTypes.TYPE_VALVE to IconState(
+ R.drawable.ic_device_valve_off,
+ R.drawable.ic_device_valve_on
+ ),
+ DeviceTypes.TYPE_SECURITY_SYSTEM to IconState(
+ R.drawable.ic_device_security_system_off,
+ R.drawable.ic_device_security_system_on
+ ),
+ DeviceTypes.TYPE_REFRIGERATOR to IconState(
+ R.drawable.ic_device_refrigerator_off,
+ R.drawable.ic_device_refrigerator_on
+ ),
+ DeviceTypes.TYPE_DOORBELL to IconState(
+ R.drawable.ic_device_doorbell_off,
+ R.drawable.ic_device_doorbell_on
),
DeviceTypes.TYPE_ROUTINE to IconState(
RenderInfo.APP_ICON_ID,
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 12955a1..ce29859 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -49,8 +49,6 @@
public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks {
- private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
-
private final Context mContext;
private final Lazy<GlobalActionsDialog> mGlobalActionsDialogLazy;
private final KeyguardStateController mKeyguardStateController;
@@ -124,7 +122,7 @@
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
window.setBackgroundDrawable(background);
- window.setWindowAnimations(R.style.Animation_Toast);
+ window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi);
d.setContentView(R.layout.shutdown_dialog);
d.setCancelable(false);
@@ -153,7 +151,9 @@
mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
mBlurUtils.blurRadiusOfRatio(1));
} else {
- background.setAlpha((int) (SHUTDOWN_SCRIM_ALPHA * 255));
+ float backgroundAlpha = mContext.getResources().getFloat(
+ com.android.systemui.R.dimen.shutdown_scrim_behind_alpha);
+ background.setAlpha((int) (backgroundAlpha * 255));
}
d.show();
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index e208ee2..9873d24 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -37,6 +37,7 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
@@ -53,6 +54,8 @@
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationMediaManager.MediaListener;
+import com.android.systemui.util.Assert;
import java.util.List;
import java.util.concurrent.Executor;
@@ -60,7 +63,7 @@
/**
* Base media control panel for System UI
*/
-public class MediaControlPanel implements NotificationMediaManager.MediaListener {
+public class MediaControlPanel {
private static final String TAG = "MediaControlPanel";
private final NotificationMediaManager mMediaManager;
private final Executor mForegroundExecutor;
@@ -74,6 +77,7 @@
private int mForegroundColor;
private int mBackgroundColor;
protected ComponentName mRecvComponent;
+ private boolean mIsRegistered = false;
private final int[] mActionIds;
@@ -86,12 +90,34 @@
com.android.internal.R.id.action4
};
- private MediaController.Callback mSessionCallback = new MediaController.Callback() {
+ private final MediaController.Callback mSessionCallback = new MediaController.Callback() {
@Override
public void onSessionDestroyed() {
Log.d(TAG, "session destroyed");
mController.unregisterCallback(mSessionCallback);
clearControls();
+ makeInactive();
+ }
+ };
+
+ private final MediaListener mMediaListener = new MediaListener() {
+ @Override
+ public void onMetadataOrStateChanged(MediaMetadata metadata, int state) {
+ if (state == PlaybackState.STATE_NONE) {
+ clearControls();
+ makeInactive();
+ }
+ }
+ };
+
+ private final OnAttachStateChangeListener mStateListener = new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View unused) {
+ makeActive();
+ }
+ @Override
+ public void onViewDetachedFromWindow(View unused) {
+ makeInactive();
}
};
@@ -111,6 +137,12 @@
mContext = context;
LayoutInflater inflater = LayoutInflater.from(mContext);
mMediaNotifView = (LinearLayout) inflater.inflate(layoutId, parent, false);
+ // TODO(b/150854549): removeOnAttachStateChangeListener when this doesn't inflate views
+ // mStateListener shouldn't need to be unregistered since this object shares the same
+ // lifecycle with the inflated view. It would be better, however, if this controller used an
+ // attach/detach of views instead of inflating them in the constructor, which would allow
+ // mStateListener to be unregistered in detach.
+ mMediaNotifView.addOnAttachStateChangeListener(mStateListener);
mMediaManager = manager;
mActionIds = actionIds;
mForegroundExecutor = foregroundExecutor;
@@ -236,9 +268,7 @@
});
}
- // Ensure is only added once
- mMediaManager.removeCallback(this);
- mMediaManager.addCallback(this);
+ makeActive();
}
/**
@@ -422,11 +452,20 @@
btn.setVisibility(View.VISIBLE);
}
- @Override
- public void onMetadataOrStateChanged(MediaMetadata metadata, int state) {
- if (state == PlaybackState.STATE_NONE) {
- clearControls();
- mMediaManager.removeCallback(this);
+ private void makeActive() {
+ Assert.isMainThread();
+ if (!mIsRegistered) {
+ mMediaManager.addCallback(mMediaListener);
+ mIsRegistered = true;
}
}
+
+ private void makeInactive() {
+ Assert.isMainThread();
+ if (mIsRegistered) {
+ mMediaManager.removeCallback(mMediaListener);
+ mIsRegistered = false;
+ }
+ }
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
index 232c23d..1533592 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
@@ -49,10 +49,10 @@
@Retention(RetentionPolicy.SOURCE)
public @interface AnimationType {}
- static final int TRANSITION_DIRECTION_NONE = 0;
- static final int TRANSITION_DIRECTION_SAME = 1;
- static final int TRANSITION_DIRECTION_TO_PIP = 2;
- static final int TRANSITION_DIRECTION_TO_FULLSCREEN = 3;
+ public static final int TRANSITION_DIRECTION_NONE = 0;
+ public static final int TRANSITION_DIRECTION_SAME = 1;
+ public static final int TRANSITION_DIRECTION_TO_PIP = 2;
+ public static final int TRANSITION_DIRECTION_TO_FULLSCREEN = 3;
@IntDef(prefix = { "TRANSITION_DIRECTION_" }, value = {
TRANSITION_DIRECTION_NONE,
@@ -61,7 +61,7 @@
TRANSITION_DIRECTION_TO_FULLSCREEN
})
@Retention(RetentionPolicy.SOURCE)
- @interface TransitionDirection {}
+ public @interface TransitionDirection {}
private final Interpolator mFastOutSlowInInterpolator;
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 6ce5e7c..da171b2 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -16,6 +16,9 @@
package com.android.systemui.pip;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_NONE;
@@ -26,9 +29,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
-import android.window.ITaskOrganizerController;
import android.app.PictureInPictureParams;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
@@ -38,9 +40,9 @@
import android.os.RemoteException;
import android.util.Log;
import android.util.Size;
+import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.IWindowContainer;
-import android.view.SurfaceControl;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
@@ -93,7 +95,8 @@
mMainHandler.post(() -> {
for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
- callback.onPipTransitionStarted();
+ callback.onPipTransitionStarted(mTaskInfo.baseActivity,
+ animator.getTransitionDirection());
}
});
}
@@ -104,7 +107,8 @@
mMainHandler.post(() -> {
for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
- callback.onPipTransitionFinished();
+ callback.onPipTransitionFinished(mTaskInfo.baseActivity,
+ animator.getTransitionDirection());
}
});
finishResize(tx, animator.getDestinationBounds(), animator.getTransitionDirection());
@@ -115,7 +119,8 @@
mMainHandler.post(() -> {
for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
- callback.onPipTransitionCanceled();
+ callback.onPipTransitionCanceled(mTaskInfo.baseActivity,
+ animator.getTransitionDirection());
}
});
}
@@ -200,6 +205,10 @@
return mUpdateHandler;
}
+ public Rect getLastReportedBounds() {
+ return new Rect(mLastReportedBounds);
+ }
+
/**
* Registers {@link PipTransitionCallback} to receive transition callbacks.
*/
@@ -216,6 +225,29 @@
mOneShotAnimationType = animationType;
}
+ /**
+ * Dismiss PiP, this is done in two phases using {@link WindowContainerTransaction}
+ * - setActivityWindowingMode to fullscreen at beginning of the transaction. without changing
+ * the windowing mode of the Task itself. This makes sure the activity render it's fullscreen
+ * configuration while the Task is still in PiP.
+ * - setWindowingMode to fullscreen at the end of transition
+ * @param animationDurationMs duration in millisecond for the exiting PiP transition
+ */
+ public void dismissPip(int animationDurationMs) {
+ try {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN);
+ WindowOrganizer.applyTransaction(wct);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to apply container transaction", e);
+ }
+ final Rect destinationBounds = mBoundsToRestore.remove(mToken.asBinder());
+ scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
+ TRANSITION_DIRECTION_TO_FULLSCREEN, animationDurationMs,
+ null /* updateBoundsCallback */);
+ mInPip = false;
+ }
+
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo info) {
Objects.requireNonNull(info, "Requires RunningTaskInfo");
@@ -235,7 +267,8 @@
mBoundsToRestore.put(mToken.asBinder(), currentBounds);
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
scheduleAnimateResizePip(currentBounds, destinationBounds,
- TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, null);
+ TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
+ null /* updateBoundsCallback */);
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
mUpdateHandler.post(() -> mPipAnimationController
.getAnimator(mLeash, destinationBounds, 0f, 1f)
@@ -249,6 +282,12 @@
}
}
+ /**
+ * Note that dismissing PiP is now originated from SystemUI, see {@link #dismissPip(int)}.
+ * Meanwhile this callback is invoked whenever the task is removed. For instance:
+ * - as a result of removeStacksInWindowingModes from WM
+ * - activity itself is died
+ */
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
IWindowContainer token = info.token;
@@ -259,7 +298,8 @@
}
final Rect boundsToRestore = mBoundsToRestore.remove(token.asBinder());
scheduleAnimateResizePip(mLastReportedBounds, boundsToRestore,
- TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration, null);
+ TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration,
+ null /* updateBoundsCallback */);
mInPip = false;
}
@@ -274,7 +314,8 @@
getAspectRatioOrDefault(newParams),
null /* bounds */, getMinimalSize(info.topActivityInfo));
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
- scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration, null);
+ scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration,
+ null /* updateBoundsCallback */);
}
/**
@@ -434,12 +475,19 @@
}
mLastReportedBounds.set(destinationBounds);
try {
- // If we are animating to fullscreen, then we need to reset the override bounds on the
- // task to ensure that the task "matches" the parent's bounds
- Rect taskBounds = direction == TRANSITION_DIRECTION_TO_FULLSCREEN
- ? null
- : destinationBounds;
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ final Rect taskBounds;
+ if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) {
+ // If we are animating to fullscreen, then we need to reset the override bounds
+ // on the task to ensure that the task "matches" the parent's bounds, this applies
+ // also to the final windowing mode, which should be reset to undefined rather than
+ // fullscreen.
+ taskBounds = null;
+ wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED)
+ .setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+ } else {
+ taskBounds = destinationBounds;
+ }
if (direction == TRANSITION_DIRECTION_TO_PIP) {
wct.scheduleFinishEnterPip(mToken, taskBounds);
} else {
@@ -492,16 +540,16 @@
/**
* Callback when the pip transition is started.
*/
- void onPipTransitionStarted();
+ void onPipTransitionStarted(ComponentName activity, int direction);
/**
* Callback when the pip transition is finished.
*/
- void onPipTransitionFinished();
+ void onPipTransitionFinished(ComponentName activity, int direction);
/**
* Callback when the pip transition is cancelled.
*/
- void onPipTransitionCanceled();
+ void onPipTransitionCanceled(ComponentName activity, int direction);
}
}
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 e89ce2e..ea19532 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -20,6 +20,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.window.WindowOrganizer.TaskOrganizer;
+import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
+
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.IActivityManager;
@@ -36,7 +38,6 @@
import android.view.DisplayInfo;
import android.view.IPinnedStackController;
import android.window.WindowContainerTransaction;
-import android.window.WindowOrganizer;
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
@@ -171,24 +172,7 @@
}
@Override
- public void onSaveReentryBounds(ComponentName componentName, Rect bounds) {
- mHandler.post(() -> {
- // On phones, the expansion animation that happens on pip tap before restoring
- // to fullscreen makes it so that the bounds received here are the expanded
- // bounds. We want to restore to the unexpanded bounds when re-entering pip,
- // so we save the bounds before expansion (normal) instead of the current
- // bounds.
- mReentryBounds.set(mTouchHandler.getNormalBounds());
- // Apply the snap fraction of the current bounds to the normal bounds.
- float snapFraction = mPipBoundsHandler.getSnapFraction(bounds);
- mPipBoundsHandler.applySnapFraction(mReentryBounds, snapFraction);
- // Save reentry bounds (normal non-expand bounds with current position applied).
- mPipBoundsHandler.onSaveReentryBounds(componentName, mReentryBounds);
- });
- }
-
- @Override
- public void onResetReentryBounds(ComponentName componentName) {
+ public void onActivityHidden(ComponentName componentName) {
mHandler.post(() -> mPipBoundsHandler.onResetReentryBounds(componentName));
}
@@ -258,7 +242,7 @@
// register the pip input consumer to ensure touch can send to it.
mInputConsumerController.registerInputConsumer();
}
- } catch (RemoteException e) {
+ } catch (RemoteException | UnsupportedOperationException e) {
e.printStackTrace();
}
}
@@ -326,7 +310,21 @@
}
@Override
- public void onPipTransitionStarted() {
+ public void onPipTransitionStarted(ComponentName activity, int direction) {
+ if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) {
+ // On phones, the expansion animation that happens on pip tap before restoring
+ // to fullscreen makes it so that the bounds received here are the expanded
+ // bounds. We want to restore to the unexpanded bounds when re-entering pip,
+ // so we save the bounds before expansion (normal) instead of the current
+ // bounds.
+ mReentryBounds.set(mTouchHandler.getNormalBounds());
+ // Apply the snap fraction of the current bounds to the normal bounds.
+ final Rect bounds = mPipTaskOrganizer.getLastReportedBounds();
+ float snapFraction = mPipBoundsHandler.getSnapFraction(bounds);
+ mPipBoundsHandler.applySnapFraction(mReentryBounds, snapFraction);
+ // Save reentry bounds (normal non-expand bounds with current position applied).
+ mPipBoundsHandler.onSaveReentryBounds(activity, mReentryBounds);
+ }
// Disable touches while the animation is running
mTouchHandler.setTouchEnabled(false);
if (mPinnedStackAnimationRecentsListener != null) {
@@ -339,12 +337,12 @@
}
@Override
- public void onPipTransitionFinished() {
+ public void onPipTransitionFinished(ComponentName activity, int direction) {
onPipTransitionFinishedOrCanceled();
}
@Override
- public void onPipTransitionCanceled() {
+ public void onPipTransitionCanceled(ComponentName activity, int direction) {
onPipTransitionFinishedOrCanceled();
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 449a2bc..7974281 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -219,11 +219,7 @@
cancelAnimations();
mMenuController.hideMenuWithoutResize();
mPipTaskOrganizer.getUpdateHandler().post(() -> {
- try {
- mActivityTaskManager.dismissPip(!skipAnimation, EXPAND_STACK_TO_FULLSCREEN_DURATION);
- } catch (RemoteException e) {
- Log.e(TAG, "Error expanding PiP activity", e);
- }
+ mPipTaskOrganizer.dismissPip(skipAnimation ? 0 : EXPAND_STACK_TO_FULLSCREEN_DURATION);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 2dcf1f8..c6e6da1 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -45,7 +45,6 @@
import android.util.Log;
import android.util.Pair;
import android.view.DisplayInfo;
-import android.window.WindowOrganizer;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -296,7 +295,7 @@
try {
WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener);
TaskOrganizer.registerOrganizer(mPipTaskOrganizer, WINDOWING_MODE_PINNED);
- } catch (RemoteException e) {
+ } catch (RemoteException | UnsupportedOperationException e) {
Log.e(TAG, "Failed to register pinned stack listener", e);
}
@@ -700,15 +699,15 @@
};
@Override
- public void onPipTransitionStarted() { }
+ public void onPipTransitionStarted(ComponentName activity, int direction) { }
@Override
- public void onPipTransitionFinished() {
+ public void onPipTransitionFinished(ComponentName activity, int direction) {
onPipTransitionFinishedOrCanceled();
}
@Override
- public void onPipTransitionCanceled() {
+ public void onPipTransitionCanceled(ComponentName activity, int direction) {
onPipTransitionFinishedOrCanceled();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 0403a05..cd73721 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -142,6 +142,9 @@
@Override
public void computeScroll() {
if (!mScroller.isFinished() && mScroller.computeScrollOffset()) {
+ if (!isFakeDragging()) {
+ beginFakeDrag();
+ }
fakeDragBy(getScrollX() - mScroller.getCurrX());
// Keep on drawing until the animation has finished.
postInvalidateOnAnimation();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index 2571521..c828c4c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -130,7 +130,7 @@
try {
CompletableFuture<List<Notification.Action>> smartActionsFuture =
ScreenshotSmartActions.getSmartActionsFuture(
- mScreenshotId, image, mSmartActionsProvider,
+ mScreenshotId, mImageFileName, image, mSmartActionsProvider,
mSmartActionsEnabled, isManagedProfile(mContext));
// Save the screenshot to the MediaStore
@@ -202,7 +202,7 @@
1000);
smartActions.addAll(buildSmartActions(
ScreenshotSmartActions.getSmartActions(
- mScreenshotId, smartActionsFuture, timeoutMs,
+ mScreenshotId, mImageFileName, smartActionsFuture, timeoutMs,
mSmartActionsProvider),
mContext));
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
index b6f5447..09a0644 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
@@ -56,16 +56,18 @@
* Default implementation that returns an empty list.
* This method is overridden in vendor-specific Sys UI implementation.
*
- * @param screenshotId A generated random unique id for the screenshot.
- * @param bitmap The bitmap of the screenshot. The bitmap config must be {@link
- * HARDWARE}.
- * @param componentName Contains package and activity class names where the screenshot was
- * taken. This is used as an additional signal to generate and rank more
- * relevant actions.
- * @param isManagedProfile The screenshot was taken for a work profile app.
+ * @param screenshotId A generated random unique id for the screenshot.
+ * @param screenshotFileName name of the file where the screenshot will be written.
+ * @param bitmap The bitmap of the screenshot. The bitmap config must be {@link
+ * HARDWARE}.
+ * @param componentName Contains package and activity class names where the screenshot was
+ * taken. This is used as an additional signal to generate and rank
+ * more relevant actions.
+ * @param isManagedProfile The screenshot was taken for a work profile app.
*/
public CompletableFuture<List<Notification.Action>> getActions(
String screenshotId,
+ String screenshotFileName,
Bitmap bitmap,
ComponentName componentName,
boolean isManagedProfile) {
@@ -77,7 +79,7 @@
* Notify exceptions and latency encountered during generating smart actions.
* This method is overridden in vendor-specific Sys UI implementation.
*
- * @param screenshotId Unique id of the screenshot.
+ * @param screenshotId unique id of the screenshot.
* @param op screenshot execution phase defined in {@link ScreenshotOp}
* @param status {@link ScreenshotOpStatus} to report success or failure.
* @param durationMs latency experienced in different phases of screenshots.
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
index e76e37e..d313444 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
@@ -44,8 +44,9 @@
private static final String TAG = "ScreenshotSmartActions";
@VisibleForTesting
- static CompletableFuture<List<Notification.Action>> getSmartActionsFuture(String screenshotId,
- Bitmap image, ScreenshotNotificationSmartActionsProvider smartActionsProvider,
+ static CompletableFuture<List<Notification.Action>> getSmartActionsFuture(
+ String screenshotId, String screenshotFileName, Bitmap image,
+ ScreenshotNotificationSmartActionsProvider smartActionsProvider,
boolean smartActionsEnabled, boolean isManagedProfile) {
if (!smartActionsEnabled) {
Slog.i(TAG, "Screenshot Intelligence not enabled, returning empty list.");
@@ -68,9 +69,8 @@
(runningTask != null && runningTask.topActivity != null)
? runningTask.topActivity
: new ComponentName("", "");
- smartActionsFuture = smartActionsProvider.getActions(screenshotId, image,
- componentName,
- isManagedProfile);
+ smartActionsFuture = smartActionsProvider.getActions(
+ screenshotId, screenshotFileName, image, componentName, isManagedProfile);
} catch (Throwable e) {
long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList());
@@ -84,7 +84,7 @@
}
@VisibleForTesting
- static List<Notification.Action> getSmartActions(String screenshotId,
+ static List<Notification.Action> getSmartActions(String screenshotId, String screenshotFileName,
CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs,
ScreenshotNotificationSmartActionsProvider smartActionsProvider) {
long startTimeMs = SystemClock.uptimeMillis();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 01498f9..66e3211 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -25,6 +25,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -32,11 +33,11 @@
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Slog;
-import android.window.IWindowContainer;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
+import android.window.IWindowContainer;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
@@ -112,6 +113,9 @@
private DisplayChangeController.OnDisplayChangingListener mRotationController =
(display, fromRotation, toRotation, t) -> {
+ if (!mSplits.isSplitScreenSupported()) {
+ return;
+ }
DisplayLayout displayLayout =
new DisplayLayout(mDisplayController.getDisplayLayout(display));
SplitDisplayLayout sdl = new SplitDisplayLayout(mContext, displayLayout, mSplits);
@@ -472,6 +476,10 @@
mDisplayController.getDisplayLayout(displayId), mSplits);
mImeController.addPositionProcessor(mImePositionProcessor);
mDisplayController.addDisplayChangingController(mRotationController);
+ if (!ActivityTaskManager.supportsSplitScreenMultiWindow(mContext)) {
+ removeDivider();
+ return;
+ }
try {
mSplits.init(mSurfaceSession);
// Set starting tile bounds based on middle target
@@ -481,13 +489,15 @@
WindowOrganizer.applyTransaction(tct);
} catch (Exception e) {
Slog.e(TAG, "Failed to register docked stack listener", e);
+ removeDivider();
+ return;
}
update(mDisplayController.getDisplayContext(displayId).getResources().getConfiguration());
}
@Override
public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
- if (displayId != DEFAULT_DISPLAY) {
+ if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) {
return;
}
mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 1aa7831..1e4c8e4 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -25,7 +25,6 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
-import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -130,7 +129,6 @@
private int mDividerInsets;
private final Display mDefaultDisplay;
- private boolean mSupportSplitScreenMultiWindow;
private int mDividerSize;
private int mTouchElevation;
@@ -284,8 +282,6 @@
final DisplayManager displayManager =
(DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
- mSupportSplitScreenMultiWindow =
- ActivityTaskManager.supportsSplitScreenMultiWindow(mContext);
}
@Override
@@ -358,11 +354,6 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (!mSupportSplitScreenMultiWindow) {
- super.onLayout(changed, left, top, right, bottom);
- return;
- }
-
if (mFirstLayout) {
// Wait for first layout so that the ViewRootImpl surface has been created.
initializeSurfaceState();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
index 6cb7f4f..0a528a6 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -49,6 +49,7 @@
ArrayList<SurfaceControl> mHomeAndRecentsSurfaces = new ArrayList<>();
Rect mHomeBounds = new Rect();
final Divider mDivider;
+ private boolean mSplitScreenSupported = false;
SplitScreenTaskOrganizer(Divider divider) {
mDivider = divider;
@@ -57,12 +58,19 @@
void init(SurfaceSession session) throws RemoteException {
TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
- WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
- WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- mPrimarySurface = mPrimary.token.getLeash();
- mSecondarySurface = mSecondary.token.getLeash();
+ try {
+ mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
+ WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
+ WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ mPrimarySurface = mPrimary.token.getLeash();
+ mSecondarySurface = mSecondary.token.getLeash();
+ } catch (RemoteException e) {
+ // teardown to prevent callbacks
+ TaskOrganizer.unregisterOrganizer(this);
+ throw e;
+ }
+ mSplitScreenSupported = true;
// Initialize dim surfaces:
mPrimaryDim = new SurfaceControl.Builder(session).setParent(mPrimarySurface)
@@ -78,6 +86,10 @@
releaseTransaction(t);
}
+ boolean isSplitScreenSupported() {
+ return mSplitScreenSupported;
+ }
+
SurfaceControl.Transaction getTransaction() {
return mDivider.mTransactionPool.acquire();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index bb0fa2d..5475812 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -93,7 +93,7 @@
private String mRestingIndication;
private String mAlignmentIndication;
private CharSequence mTransientIndication;
- private ColorStateList mTransientTextColorState;
+ private boolean mTransientTextIsError;
private ColorStateList mInitialTextColorState;
private boolean mVisible;
private boolean mHideTransientMessageOnScreenOff;
@@ -260,7 +260,7 @@
* Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
*/
public void showTransientIndication(CharSequence transientIndication) {
- showTransientIndication(transientIndication, mInitialTextColorState,
+ showTransientIndication(transientIndication, false /* isError */,
false /* hideOnScreenOff */);
}
@@ -268,10 +268,10 @@
* Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
*/
private void showTransientIndication(CharSequence transientIndication,
- ColorStateList textColorState, boolean hideOnScreenOff) {
+ boolean isError, boolean hideOnScreenOff) {
mTransientIndication = transientIndication;
mHideTransientMessageOnScreenOff = hideOnScreenOff && transientIndication != null;
- mTransientTextColorState = textColorState;
+ mTransientTextIsError = isError;
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
mHandler.removeMessages(MSG_SWIPE_UP_TO_UNLOCK);
if (mDozing && !TextUtils.isEmpty(mTransientIndication)) {
@@ -311,7 +311,6 @@
mTextView.switchIndication(mTransientIndication);
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
mTextView.switchIndication(mAlignmentIndication);
- mTextView.setTextColor(Utils.getColorError(mContext));
} else if (mPowerPluggedIn) {
String indication = computePowerIndication();
if (animate) {
@@ -336,9 +335,9 @@
powerIndication = computePowerIndication();
}
+ boolean isError = false;
if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)) {
mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
- mTextView.setTextColor(mInitialTextColorState);
} else if (!TextUtils.isEmpty(mTransientIndication)) {
if (powerIndication != null && !mTransientIndication.equals(powerIndication)) {
String indication = mContext.getResources().getString(
@@ -348,7 +347,7 @@
} else {
mTextView.switchIndication(mTransientIndication);
}
- mTextView.setTextColor(mTransientTextColorState);
+ isError = mTransientTextIsError;
} else if (!TextUtils.isEmpty(trustGrantedIndication)
&& mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
if (powerIndication != null) {
@@ -359,15 +358,13 @@
} else {
mTextView.switchIndication(trustGrantedIndication);
}
- mTextView.setTextColor(mInitialTextColorState);
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
mTextView.switchIndication(mAlignmentIndication);
- mTextView.setTextColor(Utils.getColorError(mContext));
+ isError = true;
} else if (mPowerPluggedIn) {
if (DEBUG_CHARGING_SPEED) {
powerIndication += ", " + (mChargingWattage / 1000) + " mW";
}
- mTextView.setTextColor(mInitialTextColorState);
if (animate) {
animateText(mTextView, powerIndication);
} else {
@@ -377,11 +374,11 @@
&& mKeyguardUpdateMonitor.getUserTrustIsManaged(userId)
&& !mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
mTextView.switchIndication(trustManagedIndication);
- mTextView.setTextColor(mInitialTextColorState);
} else {
mTextView.switchIndication(mRestingIndication);
- mTextView.setTextColor(mInitialTextColorState);
}
+ mTextView.setTextColor(isError ? Utils.getColorError(mContext)
+ : mInitialTextColorState);
}
}
@@ -532,7 +529,7 @@
mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState);
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
showTransientIndication(mContext.getString(R.string.keyguard_unlock),
- mInitialTextColorState, true /* hideOnScreenOff */);
+ false /* isError */, true /* hideOnScreenOff */);
hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
}
}
@@ -551,7 +548,7 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("KeyguardIndicationController:");
- pw.println(" mTransientTextColorState: " + mTransientTextColorState);
+ pw.println(" mTransientTextIsError: " + mTransientTextIsError);
pw.println(" mInitialTextColorState: " + mInitialTextColorState);
pw.println(" mPowerPluggedInWired: " + mPowerPluggedInWired);
pw.println(" mPowerPluggedIn: " + mPowerPluggedIn);
@@ -630,7 +627,7 @@
mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
mInitialTextColorState);
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
- showTransientIndication(helpString, mInitialTextColorState, showSwipeToUnlock);
+ showTransientIndication(helpString, false /* isError */, showSwipeToUnlock);
if (!showSwipeToUnlock) {
hideTransientIndicationDelayed(TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
}
@@ -704,14 +701,13 @@
@Override
public void onTrustAgentErrorMessage(CharSequence message) {
- showTransientIndication(message, Utils.getColorError(mContext),
- false /* hideOnScreenOff */);
+ showTransientIndication(message, true /* isError */, false /* hideOnScreenOff */);
}
@Override
public void onScreenTurnedOn() {
if (mMessageToShowOnScreenOn != null) {
- showTransientIndication(mMessageToShowOnScreenOn, Utils.getColorError(mContext),
+ showTransientIndication(mMessageToShowOnScreenOn, true /* isError */,
false /* hideOnScreenOff */);
// We want to keep this message around in case the screen was off
hideTransientIndicationDelayed(HIDE_DELAY_MS);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index ecfe116..8efda21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -110,8 +110,6 @@
private final float mTouchSlop;
// Duration after which we consider the event as longpress.
private final int mLongPressTimeout;
- // The back gesture type
- private int mBackType;
private final PointF mDownPoint = new PointF();
private final PointF mEndPoint = new PointF();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 3074e33..f06cfec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -203,6 +203,7 @@
Log.wtf(TAG, "onFullyShown when view was null");
} else {
mKeyguardView.onResume();
+ mRoot.announceForAccessibility(mKeyguardView.getAccessibilityTitleForCurrentMode());
}
}
@@ -247,6 +248,7 @@
if (mExpansion == EXPANSION_VISIBLE) {
mKeyguardView.onResume();
mKeyguardView.resetSecurityContainer();
+ showPromptReason(mBouncerPromptReason);
}
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN);
@@ -438,7 +440,6 @@
mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
com.android.systemui.R.dimen.status_bar_height);
mRoot.setVisibility(View.INVISIBLE);
- mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());
final WindowInsets rootInsets = mRoot.getRootWindowInsets();
if (rootInsets != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 9ce31d0..69eaaa4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -360,7 +360,7 @@
if (record.isGuest && record.info == null) {
// No guest user. Create one.
UserInfo guest = mUserManager.createGuest(
- mContext, mContext.getString(R.string.guest_nickname));
+ mContext, mContext.getString(com.android.settingslib.R.string.guest_nickname));
if (guest == null) {
// Couldn't create guest, most likely because there already exists one, we just
// haven't reloaded the user list yet.
@@ -583,7 +583,7 @@
if (mUsers.isEmpty()) return null;
UserRecord item = mUsers.get(0);
if (item == null || item.info == null) return null;
- if (item.isGuest) return context.getString(R.string.guest_nickname);
+ if (item.isGuest) return context.getString(com.android.settingslib.R.string.guest_nickname);
return item.info.name;
}
@@ -671,10 +671,11 @@
public String getName(Context context, UserRecord item) {
if (item.isGuest) {
if (item.isCurrent) {
- return context.getString(R.string.guest_exit_guest);
+ return context.getString(com.android.settingslib.R.string.guest_exit_guest);
} else {
return context.getString(
- item.info == null ? R.string.guest_new_guest : R.string.guest_nickname);
+ item.info == null ? com.android.settingslib.R.string.guest_new_guest
+ : com.android.settingslib.R.string.guest_nickname);
}
} else if (item.isAddUser) {
return context.getString(R.string.user_add_user);
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 11885c5..442c7ea 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -187,8 +187,9 @@
}
private void updateMissingPrivateVolumes() {
- if (isTv()) {
+ if (isTv() || isAutomotive()) {
// On TV, TvSettings displays a modal full-screen activity in this case.
+ // Not applicable for automotive.
return;
}
@@ -595,6 +596,9 @@
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction("com.android.tv.settings.action.NEW_STORAGE");
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add intent to handle unsupported usb
+ return null;
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageWizardInit");
@@ -611,6 +615,9 @@
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction("com.android.tv.settings.action.NEW_STORAGE");
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add intent to handle unmountable usb
+ return null;
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageWizardInit");
@@ -669,6 +676,9 @@
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add volume settings intent for automotive
+ return null;
} else {
switch (vol.getType()) {
case VolumeInfo.TYPE_PRIVATE:
@@ -700,7 +710,7 @@
}
private PendingIntent buildForgetPendingIntent(VolumeRecord rec) {
- // Not used on TV
+ // Not used on TV and Automotive
final Intent intent = new Intent();
intent.setClassName("com.android.settings",
"com.android.settings.Settings$PrivateVolumeForgetActivity");
@@ -716,6 +726,9 @@
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction("com.android.tv.settings.action.MIGRATE_STORAGE");
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add storage migrate intent for automotive
+ return null;
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageWizardMigrateProgress");
@@ -735,6 +748,9 @@
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction("com.android.tv.settings.action.MOVE_APP");
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add storage move intent for automotive
+ return null;
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageWizardMoveProgress");
@@ -750,6 +766,9 @@
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add storage ready intent for automotive
+ return null;
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageWizardReady");
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index d973bb1..50b7af2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -32,7 +32,6 @@
import static java.lang.Thread.sleep;
import android.app.AppOpsManager;
-import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -61,8 +60,6 @@
@Mock
private AppOpsManager mAppOpsManager;
@Mock
- private PackageManager mPackageManager;
- @Mock
private AppOpsController.Callback mCallback;
@Mock
private AppOpsControllerImpl.H mMockHandler;
@@ -79,10 +76,6 @@
getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager);
- // All permissions of TEST_UID and TEST_UID_OTHER are user sensitive. None of
- // TEST_UID_NON_USER_SENSITIVE are user sensitive.
- getContext().setMockPackageManager(mPackageManager);
-
mController =
new AppOpsControllerImpl(mContext, mTestableLooper.getLooper(), mDumpManager);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
index 1db8e4c..74d0610 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
@@ -34,6 +34,7 @@
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Bundle;
import android.os.IBinder;
@@ -89,6 +90,8 @@
mAuthContainer.mBiometricCallback.onAction(
AuthBiometricView.Callback.ACTION_USER_CANCELED);
+ verify(mCallback).onSystemEvent(eq(
+ BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL));
verify(mCallback).onDismissed(
eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
eq(null) /* credentialAttestation */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index eb4d438..93aee33 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -161,7 +161,7 @@
verify(listingController).addCallback(capture(listingCallbackCaptor))
}
- private fun builderFromInfo(
+ private fun statelessBuilderFromInfo(
controlInfo: ControlInfo,
structure: CharSequence = ""
): Control.StatelessBuilder {
@@ -170,6 +170,15 @@
.setSubtitle(controlInfo.controlSubtitle).setStructure(structure)
}
+ private fun statefulBuilderFromInfo(
+ controlInfo: ControlInfo,
+ structure: CharSequence = ""
+ ): Control.StatefulBuilder {
+ return Control.StatefulBuilder(controlInfo.controlId, pendingIntent)
+ .setDeviceType(controlInfo.deviceType).setTitle(controlInfo.controlTitle)
+ .setSubtitle(controlInfo.controlSubtitle).setStructure(structure)
+ }
+
@Test
fun testStartOnUser() {
assertEquals(user, controller.currentUserId)
@@ -236,7 +245,7 @@
@Test
fun testLoadForComponent_noFavorites() {
var loaded = false
- val control = builderFromInfo(TEST_CONTROL_INFO).build()
+ val control = statelessBuilderFromInfo(TEST_CONTROL_INFO).build()
controller.loadForComponent(TEST_COMPONENT, Consumer { data ->
val controls = data.allControls
@@ -263,8 +272,8 @@
@Test
fun testLoadForComponent_favorites() {
var loaded = false
- val control = builderFromInfo(TEST_CONTROL_INFO).build()
- val control2 = builderFromInfo(TEST_CONTROL_INFO_2).build()
+ val control = statelessBuilderFromInfo(TEST_CONTROL_INFO).build()
+ val control2 = statelessBuilderFromInfo(TEST_CONTROL_INFO_2).build()
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO_2)
delayableExecutor.runAllReady()
@@ -445,7 +454,7 @@
delayableExecutor.runAllReady()
val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2)
- val control = builderFromInfo(newControlInfo).build()
+ val control = statelessBuilderFromInfo(newControlInfo).build()
controller.loadForComponent(TEST_COMPONENT, Consumer {})
@@ -461,11 +470,11 @@
}
@Test
- fun testFavoriteInformationModifiedOnRefresh() {
+ fun testFavoriteInformationModifiedOnRefreshWithOkStatus() {
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2)
- val control = builderFromInfo(newControlInfo).build()
+ val control = statefulBuilderFromInfo(newControlInfo).setStatus(Control.STATUS_OK).build()
controller.refreshStatus(TEST_COMPONENT, control)
@@ -477,6 +486,23 @@
}
@Test
+ fun testFavoriteInformationNotModifiedOnRefreshWithNonOkStatus() {
+ controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
+
+ val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2)
+ val control = statefulBuilderFromInfo(newControlInfo).setStatus(Control.STATUS_ERROR)
+ .build()
+
+ controller.refreshStatus(TEST_COMPONENT, control)
+
+ delayableExecutor.runAllReady()
+
+ val favorites = controller.getFavorites().flatMap { it.controls }
+ assertEquals(1, favorites.size)
+ assertEquals(TEST_CONTROL_INFO, favorites[0])
+ }
+
+ @Test
fun testSwitchUsers() {
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
delayableExecutor.runAllReady()
@@ -762,7 +788,8 @@
@Test
fun testSeedFavoritesForComponent() {
var succeeded = false
- val control = builderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure).build()
+ val control = statelessBuilderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure)
+ .build()
controller.seedFavoritesForComponent(TEST_COMPONENT, Consumer { accepted ->
succeeded = accepted
@@ -803,7 +830,8 @@
fun testSeedFavoritesForComponent_inProgressCallback() {
var succeeded = false
var seeded = false
- val control = builderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure).build()
+ val control = statelessBuilderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure)
+ .build()
controller.seedFavoritesForComponent(TEST_COMPONENT, Consumer { accepted ->
succeeded = accepted
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
index aeb31e1..11649ca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -76,11 +76,11 @@
when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
ScreenshotNotificationSmartActionsProvider smartActionsProvider = mock(
ScreenshotNotificationSmartActionsProvider.class);
- when(smartActionsProvider.getActions(any(), any(), any(),
+ when(smartActionsProvider.getActions(any(), any(), any(), any(),
eq(false))).thenThrow(
RuntimeException.class);
CompletableFuture<List<Notification.Action>> smartActionsFuture =
- ScreenshotSmartActions.getSmartActionsFuture("", bitmap,
+ ScreenshotSmartActions.getSmartActionsFuture("", "", bitmap,
smartActionsProvider, true, false);
Assert.assertNotNull(smartActionsFuture);
List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
@@ -98,7 +98,7 @@
when(smartActionsFuture.get(timeoutMs, TimeUnit.MILLISECONDS)).thenThrow(
RuntimeException.class);
List<Notification.Action> actions = ScreenshotSmartActions.getSmartActions(
- "", smartActionsFuture, timeoutMs, mSmartActionsProvider);
+ "", "", smartActionsFuture, timeoutMs, mSmartActionsProvider);
Assert.assertEquals(Collections.emptyList(), actions);
}
@@ -119,9 +119,9 @@
Bitmap bitmap = mock(Bitmap.class);
when(bitmap.getConfig()).thenReturn(Bitmap.Config.RGB_565);
CompletableFuture<List<Notification.Action>> smartActionsFuture =
- ScreenshotSmartActions.getSmartActionsFuture("", bitmap,
+ ScreenshotSmartActions.getSmartActionsFuture("", "", bitmap,
mSmartActionsProvider, true, true);
- verify(mSmartActionsProvider, never()).getActions(any(), any(), any(),
+ verify(mSmartActionsProvider, never()).getActions(any(), any(), any(), any(),
eq(false));
Assert.assertNotNull(smartActionsFuture);
List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
@@ -133,10 +133,10 @@
public void testScreenshotNotificationSmartActionsProviderInvokedOnce() {
Bitmap bitmap = mock(Bitmap.class);
when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
- ScreenshotSmartActions.getSmartActionsFuture("", bitmap, mSmartActionsProvider,
+ ScreenshotSmartActions.getSmartActionsFuture("", "", bitmap, mSmartActionsProvider,
true, true);
verify(mSmartActionsProvider, times(1))
- .getActions(any(), any(), any(), eq(true));
+ .getActions(any(), any(), any(), any(), eq(true));
}
// Tests for a hardware bitmap, a completed future is returned.
@@ -149,7 +149,7 @@
SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider(
mContext, null, mHandler);
CompletableFuture<List<Notification.Action>> smartActionsFuture =
- ScreenshotSmartActions.getSmartActionsFuture("", bitmap,
+ ScreenshotSmartActions.getSmartActionsFuture("", "", bitmap,
actionsProvider,
true, true);
Assert.assertNotNull(smartActionsFuture);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index fb40177..be5b190 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -192,8 +192,7 @@
assertThat(mTextView.getText()).isEqualTo(
mContext.getResources().getString(R.string.dock_alignment_slow_charging));
- assertThat(mTextView.getCurrentTextColor()).isEqualTo(
- Utils.getColorError(mContext).getDefaultColor());
+ assertThat(mTextView.getCurrentTextColor()).isEqualTo(Color.WHITE);
}
@Test
@@ -210,8 +209,7 @@
assertThat(mTextView.getText()).isEqualTo(
mContext.getResources().getString(R.string.dock_alignment_not_charging));
- assertThat(mTextView.getCurrentTextColor()).isEqualTo(
- Utils.getColorError(mContext).getDefaultColor());
+ assertThat(mTextView.getCurrentTextColor()).isEqualTo(Color.WHITE);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index 35971bd..e052ae2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -56,11 +57,13 @@
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -91,13 +94,14 @@
private Handler mHandler;
@Mock
private KeyguardSecurityModel mKeyguardSecurityModel;
-
+ @Rule
+ public MockitoRule mRule = MockitoJUnit.rule();
+ private ViewGroup mRootView;
private KeyguardBouncer mBouncer;
@Before
public void setup() {
allowTestableLooperAsMainThread();
- MockitoAnnotations.initMocks(this);
mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor);
mDependency.injectTestDependency(KeyguardSecurityModel.class, mKeyguardSecurityModel);
mDependency.injectMockDependency(KeyguardStateController.class);
@@ -115,6 +119,8 @@
protected void inflateView() {
super.inflateView();
mKeyguardView = mKeyguardHostView;
+ mRoot = spy(mRoot);
+ mRootView = mRoot;
}
};
}
@@ -217,6 +223,7 @@
mBouncer.setExpansion(0);
verify(mKeyguardHostView).onResume();
+ verify(mRootView).announceForAccessibility(any());
}
@Test
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index 6af5fe5..31c40d2 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -65,12 +65,7 @@
stubs_defaults {
name: "framework-tethering-stubs-defaults",
- srcs: [
- "src/android/net/TetheredClient.java",
- "src/android/net/TetheringManager.java",
- "src/android/net/TetheringConstants.java",
- ],
- libs: ["tethering-aidl-interfaces-java"],
+ srcs: [":framework-tethering-srcs"],
}
filegroup {
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index c84892d..4b2c921 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -307,28 +307,22 @@
userManager, this, mNotificationUpdater);
mExecutor = new TetheringThreadExecutor(mHandler);
mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor);
+ mNetdCallback = new NetdCallback();
// Load tethering configuration.
updateConfiguration();
- // NetdCallback should be registered after updateConfiguration() to ensure
- // TetheringConfiguration is created.
- mNetdCallback = new NetdCallback();
+ }
+
+ /**
+ * Start to register callbacks.
+ * Call this function when tethering is ready to handle callback events.
+ */
+ public void startStateMachineUpdaters() {
try {
mNetd.registerUnsolicitedEventListener(mNetdCallback);
} catch (RemoteException e) {
mLog.e("Unable to register netd UnsolicitedEventListener");
}
-
- startStateMachineUpdaters(mHandler);
- startTrackDefaultNetwork();
-
- final WifiManager wifiManager = getWifiManager();
- if (wifiManager != null) {
- wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback());
- }
- }
-
- private void startStateMachineUpdaters(Handler handler) {
mCarrierConfigChange.startListening();
mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener,
PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
@@ -341,7 +335,14 @@
filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED);
- mContext.registerReceiver(mStateReceiver, filter, null, handler);
+ mContext.registerReceiver(mStateReceiver, filter, null, mHandler);
+
+ final WifiManager wifiManager = getWifiManager();
+ if (wifiManager != null) {
+ wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback());
+ }
+
+ startTrackDefaultNetwork();
}
private class TetheringThreadExecutor implements Executor {
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
index c5329d8..c30be25 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
@@ -80,6 +80,7 @@
mContext = mDeps.getContext();
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mTethering = makeTethering(mDeps);
+ mTethering.startStateMachineUpdaters();
}
/**
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index 5ead110..a59c6fd 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -484,6 +484,7 @@
mServiceContext.registerReceiver(mBroadcastReceiver,
new IntentFilter(ACTION_TETHER_STATE_CHANGED));
mTethering = makeTethering();
+ mTethering.startStateMachineUpdaters();
verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
verify(mNetd).registerUnsolicitedEventListener(any());
final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor =
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index dcdb80b..ef0e044 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -45,6 +45,8 @@
IconPackRoundedSettingsOverlay \
IconPackRoundedSystemUIOverlay \
IconPackRoundedThemePickerOverlay \
+ IconShapeFlowerOverlay \
+ IconShapeHexagonOverlay \
IconShapeRoundedRectOverlay \
IconShapeSquircleOverlay \
IconShapeTeardropOverlay \
diff --git a/services/Android.bp b/services/Android.bp
index 52c5993..730b9a5 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -81,10 +81,6 @@
"framework-tethering-stubs-module_libs_api",
],
- plugins: [
- "compat-changeid-annotation-processor",
- ],
-
// Uncomment to enable output of certain warnings (deprecated, unchecked)
//javacflags: ["-Xlint"],
@@ -126,6 +122,7 @@
" --hide DeprecationMismatch" +
" --hide HiddenTypedefConstant",
visibility: ["//visibility:private"],
+ filter_packages: ["com.android."],
check_api: {
current: {
api_file: "api/current.txt",
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
index 2306329..a86d34d 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
@@ -35,11 +35,11 @@
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
-import android.view.inline.InlinePresentationSpec;
import android.view.inputmethod.InlineSuggestion;
import android.view.inputmethod.InlineSuggestionInfo;
import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InlineSuggestionsResponse;
+import android.widget.inline.InlinePresentationSpec;
import com.android.internal.view.inline.IInlineContentCallback;
import com.android.internal.view.inline.IInlineContentProvider;
@@ -263,7 +263,7 @@
private static InlinePresentation mergedInlinePresentation(
@NonNull InlineSuggestionsRequest request,
int index, @NonNull InlinePresentation inlinePresentation) {
- final List<InlinePresentationSpec> specs = request.getPresentationSpecs();
+ final List<InlinePresentationSpec> specs = request.getInlinePresentationSpecs();
if (specs.isEmpty()) {
return inlinePresentation;
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 5d2b9f3..ce539da 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -89,7 +89,6 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -919,35 +918,24 @@
private static class DataShareCallbackDelegate extends IDataShareCallback.Stub {
@NonNull private final DataShareRequest mDataShareRequest;
- @NonNull private final WeakReference<IDataShareWriteAdapter> mClientAdapterReference;
- @NonNull private final WeakReference<ContentCaptureManagerService> mParentServiceReference;
+ @NonNull private final IDataShareWriteAdapter mClientAdapter;
+ @NonNull private final ContentCaptureManagerService mParentService;
DataShareCallbackDelegate(@NonNull DataShareRequest dataShareRequest,
@NonNull IDataShareWriteAdapter clientAdapter,
ContentCaptureManagerService parentService) {
mDataShareRequest = dataShareRequest;
- mClientAdapterReference = new WeakReference<>(clientAdapter);
- mParentServiceReference = new WeakReference<>(parentService);
+ mClientAdapter = clientAdapter;
+ mParentService = parentService;
}
@Override
public void accept(IDataShareReadAdapter serviceAdapter) throws RemoteException {
Slog.i(TAG, "Data share request accepted by Content Capture service");
- final ContentCaptureManagerService parentService = mParentServiceReference.get();
- final IDataShareWriteAdapter clientAdapter = mClientAdapterReference.get();
- if (parentService == null || clientAdapter == null) {
- Slog.w(TAG, "Can't fulfill accept() request, because remote objects have been "
- + "GC'ed");
- return;
- }
-
- final WeakReference<IDataShareReadAdapter> serviceAdapterReference =
- new WeakReference<>(serviceAdapter);
-
Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe();
if (clientPipe == null) {
- clientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
+ mClientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
serviceAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
return;
}
@@ -959,7 +947,7 @@
if (servicePipe == null) {
bestEffortCloseFileDescriptors(sourceIn, sinkIn);
- clientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
+ mClientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
serviceAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
return;
}
@@ -967,9 +955,9 @@
ParcelFileDescriptor sourceOut = servicePipe.second;
ParcelFileDescriptor sinkOut = servicePipe.first;
- parentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
+ mParentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
- clientAdapter.write(sourceIn);
+ mClientAdapter.write(sourceIn);
serviceAdapter.start(sinkOut);
// File descriptor received by the client app will be a copy of the current one. Close
@@ -977,7 +965,7 @@
// current pipe.
bestEffortCloseFileDescriptor(sourceIn);
- parentService.mDataShareExecutor.execute(() -> {
+ mParentService.mDataShareExecutor.execute(() -> {
try (InputStream fis =
new ParcelFileDescriptor.AutoCloseInputStream(sinkIn);
OutputStream fos =
@@ -996,23 +984,23 @@
} catch (IOException e) {
Slog.e(TAG, "Failed to pipe client and service streams", e);
- sendErrorSignal(mClientAdapterReference, serviceAdapterReference,
+ sendErrorSignal(mClientAdapter, serviceAdapter,
ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
} finally {
- synchronized (parentService.mLock) {
- parentService.mPackagesWithShareRequests
+ synchronized (mParentService.mLock) {
+ mParentService.mPackagesWithShareRequests
.remove(mDataShareRequest.getPackageName());
}
}
});
- parentService.mHandler.postDelayed(() ->
+ mParentService.mHandler.postDelayed(() ->
enforceDataSharingTtl(
sourceIn,
sinkIn,
sourceOut,
sinkOut,
- serviceAdapterReference),
+ serviceAdapter),
MAX_DATA_SHARE_FILE_DESCRIPTORS_TTL_MS);
}
@@ -1020,31 +1008,17 @@
public void reject() throws RemoteException {
Slog.i(TAG, "Data share request rejected by Content Capture service");
- IDataShareWriteAdapter clientAdapter = mClientAdapterReference.get();
- if (clientAdapter == null) {
- Slog.w(TAG, "Can't fulfill reject() request, because remote objects have been "
- + "GC'ed");
- return;
- }
-
- clientAdapter.rejected();
+ mClientAdapter.rejected();
}
private void enforceDataSharingTtl(ParcelFileDescriptor sourceIn,
ParcelFileDescriptor sinkIn,
ParcelFileDescriptor sourceOut,
ParcelFileDescriptor sinkOut,
- WeakReference<IDataShareReadAdapter> serviceAdapterReference) {
+ IDataShareReadAdapter serviceAdapter) {
- final ContentCaptureManagerService parentService = mParentServiceReference.get();
- if (parentService == null) {
- Slog.w(TAG, "Can't enforce data sharing TTL, because remote objects have been "
- + "GC'ed");
- return;
- }
-
- synchronized (parentService.mLock) {
- parentService.mPackagesWithShareRequests
+ synchronized (mParentService.mLock) {
+ mParentService.mPackagesWithShareRequests
.remove(mDataShareRequest.getPackageName());
// Interaction finished successfully <=> all data has been written to Content
@@ -1069,7 +1043,7 @@
bestEffortCloseFileDescriptors(sourceIn, sinkIn, sourceOut, sinkOut);
if (!finishedSuccessfully) {
- sendErrorSignal(mClientAdapterReference, serviceAdapterReference,
+ sendErrorSignal(mClientAdapter, serviceAdapter,
ContentCaptureManager.DATA_SHARE_ERROR_TIMEOUT_INTERRUPTED);
}
}
@@ -1115,19 +1089,9 @@
}
private static void sendErrorSignal(
- WeakReference<IDataShareWriteAdapter> clientAdapterReference,
- WeakReference<IDataShareReadAdapter> serviceAdapterReference,
+ IDataShareWriteAdapter clientAdapter,
+ IDataShareReadAdapter serviceAdapter,
int errorCode) {
-
- final IDataShareWriteAdapter clientAdapter = clientAdapterReference.get();
- final IDataShareReadAdapter serviceAdapter = serviceAdapterReference.get();
-
- if (clientAdapter == null || serviceAdapter == null) {
- Slog.w(TAG, "Can't propagate error() to read/write data share adapters, because "
- + "remote objects have been GC'ed");
- return;
- }
-
try {
clientAdapter.error(errorCode);
} catch (RemoteException e) {
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 32bca35..9486b0d 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -17,7 +17,7 @@
package com.android.server.contentcapture;
import static android.service.contentcapture.ContentCaptureService.setClientState;
-import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID;
import static android.view.contentcapture.ContentCaptureSession.STATE_INTERNAL_ERROR;
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index aa63e4074..06ab426 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -16,9 +16,9 @@
package com.android.server.contentcapture;
import static android.service.contentcapture.ContentCaptureService.setClientState;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_FALSE;
import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_TRUE;
-import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID;
import static android.view.contentcapture.ContentCaptureSession.STATE_ACTIVE;
import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
import static android.view.contentcapture.ContentCaptureSession.STATE_SERVICE_RESURRECTED;
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 7a26b21..052026c 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -130,10 +130,6 @@
"netd_event_listener_interface-java",
"overlayable_policy_aidl-java",
],
-
- plugins: [
- "compat-changeid-annotation-processor",
- ],
}
java_genrule {
@@ -154,6 +150,10 @@
static_libs: ["services.core.priorityboosted"],
}
+java_library_host {
+ name: "core_cts_test_resources",
+ srcs: ["java/com/android/server/notification/SmallHash.java"]
+}
prebuilt_etc {
name: "gps_debug.conf",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 7d85966..c27ec66 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -427,17 +427,6 @@
public abstract String getNameForUid(int uid);
/**
- * Marks a package as installed (or not installed) for a given user.
- *
- * @param pkg the package whose installation is to be set
- * @param userId the user for whom to set it
- * @param installed the new installed state
- * @return true if the installed state changed as a result
- */
- public abstract boolean setInstalled(AndroidPackage pkg,
- @UserIdInt int userId, boolean installed);
-
- /**
* Request to perform the second phase of ephemeral resolution.
* @param responseObj The response of the first phase of ephemeral resolution
* @param origIntent The original intent that triggered ephemeral resolution
@@ -522,12 +511,6 @@
public abstract boolean isPackagePersistent(String packageName);
/**
- * Returns whether or not the given package represents a legacy system application released
- * prior to runtime permissions.
- */
- public abstract boolean isLegacySystemApp(AndroidPackage pkg);
-
- /**
* Get all overlay packages for a user.
* @param userId The user for which to get the overlays.
* @return A list of overlay packages. An empty list is returned if the
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 76a8e14..5d350be 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -63,6 +63,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.net.CaptivePortal;
@@ -5405,12 +5406,25 @@
}
}
+ private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) {
+ final PackageManager pm = mContext.getPackageManager();
+ final int userId = UserHandle.getCallingUserId();
+ try {
+ final int callingVersion = pm.getApplicationInfoAsUser(
+ callingPackageName, 0 /* flags */, userId).targetSdkVersion;
+ if (callingVersion < version) return false;
+ } catch (PackageManager.NameNotFoundException e) { }
+ return true;
+ }
+
@Override
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
Messenger messenger, int timeoutMs, IBinder binder, int legacyType,
@NonNull String callingPackageName) {
if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) {
- throw new SecurityException("Insufficient permissions to specify legacy type");
+ if (checkUnsupportedStartingFrom(Build.VERSION_CODES.M, callingPackageName)) {
+ throw new SecurityException("Insufficient permissions to specify legacy type");
+ }
}
final int callingUid = Binder.getCallingUid();
final NetworkRequest.Type type = (networkCapabilities == null)
@@ -7967,10 +7981,13 @@
return false;
}
+ final Network[] underlyingNetworks;
synchronized (mVpns) {
- if (getVpnIfOwner(callbackUid) != null) {
- return true;
- }
+ final Vpn vpn = getVpnIfOwner(callbackUid);
+ underlyingNetworks = (vpn == null) ? null : vpn.getUnderlyingNetworks();
+ }
+ if (underlyingNetworks != null) {
+ if (Arrays.asList(underlyingNetworks).contains(nai.network)) return true;
}
// Administrator UIDs also contains the Owner UID
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 9540f43..599485b 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -359,10 +359,14 @@
@VisibleForTesting
static final class UserRecord {
/* Maximum number of each type of resource that a single UID may possess */
- public static final int MAX_NUM_TUNNEL_INTERFACES = 2;
- public static final int MAX_NUM_ENCAP_SOCKETS = 2;
- public static final int MAX_NUM_TRANSFORMS = 4;
- public static final int MAX_NUM_SPIS = 8;
+
+ // Up to 4 active VPNs/IWLAN with potential soft handover.
+ public static final int MAX_NUM_TUNNEL_INTERFACES = 8;
+ public static final int MAX_NUM_ENCAP_SOCKETS = 16;
+
+ // SPIs and Transforms are both cheap, and are 1:1 correlated.
+ public static final int MAX_NUM_TRANSFORMS = 64;
+ public static final int MAX_NUM_SPIS = 64;
/**
* Store each of the OwnedResource types in an (thinly wrapped) sparse array for indexing
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index d814b9c..8ccff76 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -16,7 +16,6 @@
package com.android.server;
-import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
@@ -27,6 +26,9 @@
import static android.location.LocationManager.PASSIVE_PROVIDER;
import static android.os.PowerManager.locationPowerSaveModeToString;
+import static com.android.server.location.CallerIdentity.PERMISSION_COARSE;
+import static com.android.server.location.CallerIdentity.PERMISSION_FINE;
+
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import android.Manifest;
@@ -34,17 +36,16 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
-import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
+import android.location.GnssCapabilities;
import android.location.GnssMeasurementCorrections;
import android.location.GnssRequest;
import android.location.IBatchedLocationCallback;
@@ -58,6 +59,7 @@
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationManagerInternal;
+import android.location.LocationProvider;
import android.location.LocationRequest;
import android.location.LocationTime;
import android.os.Binder;
@@ -86,14 +88,15 @@
import com.android.internal.content.PackageMonitor;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.location.AbstractLocationProvider;
import com.android.server.location.AbstractLocationProvider.State;
import com.android.server.location.AppForegroundHelper;
+import com.android.server.location.AppOpsHelper;
import com.android.server.location.CallerIdentity;
+import com.android.server.location.CallerIdentity.PermissionLevel;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
@@ -176,10 +179,6 @@
private static final String WAKELOCK_KEY = "*location*";
- private static final int RESOLUTION_LEVEL_NONE = 0;
- private static final int RESOLUTION_LEVEL_COARSE = 1;
- private static final int RESOLUTION_LEVEL_FINE = 2;
-
private static final String NETWORK_LOCATION_SERVICE_ACTION =
"com.android.location.service.v3.NetworkLocationProvider";
private static final String FUSED_LOCATION_SERVICE_ACTION =
@@ -208,6 +207,7 @@
private final Context mContext;
private final Handler mHandler;
private final LocalService mLocalService;
+ private final AppOpsHelper mAppOpsHelper;
private final UserInfoHelper mUserInfoHelper;
private final SettingsHelper mSettingsHelper;
private final AppForegroundHelper mAppForegroundHelper;
@@ -217,8 +217,6 @@
private final PassiveLocationProviderManager mPassiveManager;
- private AppOpsManager mAppOps;
- private PackageManager mPackageManager;
private PowerManager mPowerManager;
private GeofenceManager mGeofenceManager;
@@ -252,6 +250,7 @@
LocalServices.addService(LocationManagerInternal.class, mLocalService);
+ mAppOpsHelper = new AppOpsHelper(mContext);
mUserInfoHelper = new UserInfoHelper(mContext);
mSettingsHelper = new SettingsHelper(mContext, mHandler);
mAppForegroundHelper = new AppForegroundHelper(mContext);
@@ -280,32 +279,17 @@
}
private void onSystemReady() {
+ mAppOpsHelper.onSystemReady();
mUserInfoHelper.onSystemReady();
mSettingsHelper.onSystemReady();
mAppForegroundHelper.onSystemReady();
synchronized (mLock) {
- mPackageManager = mContext.getPackageManager();
- mAppOps = mContext.getSystemService(AppOpsManager.class);
mPowerManager = mContext.getSystemService(PowerManager.class);
mGeofenceManager = new GeofenceManager(mContext, mSettingsHelper);
- PowerManagerInternal localPowerManager =
- LocalServices.getService(PowerManagerInternal.class);
-
// add listeners
- mAppOps.startWatchingMode(
- AppOpsManager.OP_COARSE_LOCATION,
- null,
- AppOpsManager.WATCH_FOREGROUND_CHANGES,
- new AppOpsManager.OnOpChangedInternalListener() {
- public void onOpChanged(int op, String packageName) {
- // onOpChanged invoked on ui thread, move to our thread to reduce risk
- // of blocking ui thread
- mHandler.post(() -> onAppOpChanged(packageName));
- }
- });
- mPackageManager.addOnPermissionsChangeListener(
+ mContext.getPackageManager().addOnPermissionsChangeListener(
uid -> {
// listener invoked on ui thread, move to our thread to reduce risk of
// blocking ui thread
@@ -316,7 +300,8 @@
});
});
- localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
+ LocalServices.getService(PowerManagerInternal.class).registerLowPowerModeObserver(
+ ServiceType.LOCATION,
state -> {
// listener invoked on ui thread, move to our thread to reduce risk of
// blocking ui thread
@@ -328,6 +313,8 @@
});
mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
+ mAppOpsHelper.addListener(this::onAppOpChanged);
+
mSettingsHelper.addOnLocationEnabledChangedListener(this::onLocationModeChanged);
mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener(
this::onBackgroundThrottleIntervalChanged);
@@ -336,40 +323,32 @@
mSettingsHelper.addOnIgnoreSettingsPackageWhitelistChangedListener(
this::onIgnoreSettingsWhitelistChanged);
- new PackageMonitor() {
+ PackageMonitor packageMonitor = new PackageMonitor() {
@Override
public void onPackageDisappeared(String packageName, int reason) {
synchronized (mLock) {
- LocationManagerService.this.onPackageDisappearedLocked(packageName);
+ LocationManagerService.this.onPackageDisappeared(packageName);
}
}
- }.register(mContext, mHandler.getLooper(), true);
+ };
+ packageMonitor.register(mContext, null, true, mHandler);
mUserInfoHelper.addListener(this::onUserChanged);
mAppForegroundHelper.addListener(this::onAppForegroundChanged);
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
- intentFilter.addAction(Intent.ACTION_SCREEN_ON);
-
+ IntentFilter screenIntentFilter = new IntentFilter();
+ screenIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
+ screenIntentFilter.addAction(Intent.ACTION_SCREEN_ON);
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (action == null) {
- return;
- }
- synchronized (mLock) {
- switch (action) {
- case Intent.ACTION_SCREEN_ON:
- case Intent.ACTION_SCREEN_OFF:
- onScreenStateChangedLocked();
- break;
- }
+ if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())
+ || Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
+ onScreenStateChanged();
}
}
- }, UserHandle.ALL, intentFilter, null, mHandler);
+ }, UserHandle.ALL, screenIntentFilter, null, mHandler);
// initialize the current users. we would get the user started notifications for these
// users eventually anyways, but this takes care of it as early as possible.
@@ -389,7 +368,7 @@
private void onAppOpChanged(String packageName) {
synchronized (mLock) {
for (Receiver receiver : mReceivers.values()) {
- if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
+ if (receiver.mCallerIdentity.packageName.equals(packageName)) {
receiver.updateMonitoring(true);
}
}
@@ -398,7 +377,7 @@
for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
String provider = entry.getKey();
for (UpdateRecord record : entry.getValue()) {
- if (record.mReceiver.mCallerIdentity.mPackageName.equals(packageName)) {
+ if (record.mReceiver.mCallerIdentity.packageName.equals(packageName)) {
affectedProviders.add(provider);
}
}
@@ -436,11 +415,12 @@
}
}
- @GuardedBy("mLock")
- private void onScreenStateChangedLocked() {
- if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
- for (LocationProviderManager manager : mProviderManagers) {
- applyRequirementsLocked(manager);
+ private void onScreenStateChanged() {
+ synchronized (mLock) {
+ if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
+ for (LocationProviderManager manager : mProviderManagers) {
+ applyRequirementsLocked(manager);
+ }
}
}
}
@@ -466,23 +446,24 @@
}
}
- @GuardedBy("mLock")
- private void onPackageDisappearedLocked(String packageName) {
- ArrayList<Receiver> deadReceivers = null;
+ private void onPackageDisappeared(String packageName) {
+ synchronized (mLock) {
+ ArrayList<Receiver> deadReceivers = null;
- for (Receiver receiver : mReceivers.values()) {
- if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
- if (deadReceivers == null) {
- deadReceivers = new ArrayList<>();
+ for (Receiver receiver : mReceivers.values()) {
+ if (receiver.mCallerIdentity.packageName.equals(packageName)) {
+ if (deadReceivers == null) {
+ deadReceivers = new ArrayList<>();
+ }
+ deadReceivers.add(receiver);
}
- deadReceivers.add(receiver);
}
- }
- // perform removal outside of mReceivers loop
- if (deadReceivers != null) {
- for (Receiver receiver : deadReceivers) {
- removeUpdatesLocked(receiver);
+ // perform removal outside of mReceivers loop
+ if (deadReceivers != null) {
+ for (Receiver receiver : deadReceivers) {
+ removeUpdatesLocked(receiver);
+ }
}
}
}
@@ -493,7 +474,7 @@
for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
String provider = entry.getKey();
for (UpdateRecord record : entry.getValue()) {
- if (record.mReceiver.mCallerIdentity.mUid == uid
+ if (record.mReceiver.mCallerIdentity.uid == uid
&& record.mIsForegroundUid != foreground) {
record.updateForeground(foreground);
@@ -574,17 +555,6 @@
Log.e(TAG, "no geocoder provider found");
}
- // bind to geofence proxy
- if (mGnssManagerService != null) {
- IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy();
- if (gpsGeofenceHardware != null) {
- GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware);
- if (provider == null) {
- Log.e(TAG, "unable to bind to GeofenceProxy");
- }
- }
- }
-
// bind to hardware activity recognition
HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy =
HardwareActivityRecognitionProxy.createAndRegister(mContext);
@@ -607,19 +577,33 @@
Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
Integer.parseInt(fragments[8]) /* powerRequirement */,
Integer.parseInt(fragments[9]) /* accuracy */);
- addTestProvider(name, properties, mContext.getOpPackageName());
+ LocationProviderManager manager = getLocationProviderManager(name);
+ if (manager == null) {
+ manager = new LocationProviderManager(name);
+ mProviderManagers.add(manager);
+ }
+ manager.setMockProvider(new MockProvider(properties));
}
// initialize gnss last because it has no awareness of boot phases and blindly assumes that
// all other location providers are loaded at initialization
if (GnssManagerService.isGnssSupported()) {
- mGnssManagerService = new GnssManagerService(mContext, mSettingsHelper,
+ mGnssManagerService = new GnssManagerService(mContext, mAppOpsHelper, mSettingsHelper,
mAppForegroundHelper, mLocationUsageLogger);
mGnssManagerService.onSystemReady();
LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER);
mProviderManagers.add(gnssManager);
gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider());
+
+ // bind to geofence proxy
+ IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy();
+ if (gpsGeofenceHardware != null) {
+ GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware);
+ if (provider == null) {
+ Log.e(TAG, "unable to bind to GeofenceProxy");
+ }
+ }
}
}
@@ -742,16 +726,16 @@
}
@Nullable
- public Location getLastFineLocation(int userId) {
+ public Location getLastLocation(int userId, @PermissionLevel int permissionlevel) {
synchronized (mLock) {
- return mLastLocation.get(userId);
- }
- }
-
- @Nullable
- public Location getLastCoarseLocation(int userId) {
- synchronized (mLock) {
- return mLastCoarseLocation.get(userId);
+ switch (permissionlevel) {
+ case PERMISSION_COARSE:
+ return mLastCoarseLocation.get(userId);
+ case PERMISSION_FINE:
+ return mLastLocation.get(userId);
+ default:
+ throw new AssertionError();
+ }
}
}
@@ -1037,7 +1021,6 @@
private final class Receiver extends LocationManagerServiceUtils.LinkedListenerBase implements
PendingIntent.OnFinished {
private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
- private final int mAllowedResolutionLevel; // resolution level allowed to receiver
private final ILocationListener mListener;
final PendingIntent mPendingIntent;
@@ -1054,11 +1037,9 @@
private int mPendingBroadcasts;
PowerManager.WakeLock mWakeLock;
- private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
- String packageName, @Nullable String featureId, WorkSource workSource,
- boolean hideFromAppOps, @NonNull String listenerIdentifier) {
- super(new CallerIdentity(uid, pid, packageName, featureId, listenerIdentifier),
- "LocationListener");
+ private Receiver(ILocationListener listener, PendingIntent intent, CallerIdentity identity,
+ WorkSource workSource, boolean hideFromAppOps) {
+ super(identity);
mListener = listener;
mPendingIntent = intent;
if (listener != null) {
@@ -1066,7 +1047,6 @@
} else {
mKey = intent;
}
- mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
if (workSource != null && workSource.isEmpty()) {
workSource = null;
}
@@ -1078,7 +1058,7 @@
// construct/configure wakelock
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
if (workSource == null) {
- workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName);
+ workSource = new WorkSource(mCallerIdentity.uid, mCallerIdentity.packageName);
}
mWakeLock.setWorkSource(workSource);
@@ -1136,7 +1116,7 @@
if (manager == null) {
continue;
}
- if (!manager.isEnabled(UserHandle.getUserId(mCallerIdentity.mUid))
+ if (!manager.isEnabled(UserHandle.getUserId(mCallerIdentity.uid))
&& !isSettingsExempt(updateRecord)) {
continue;
}
@@ -1156,42 +1136,43 @@
mOpMonitoring = updateMonitoring(
requestingLocation,
mOpMonitoring,
- AppOpsManager.OP_MONITOR_LOCATION);
+ false);
// Now update monitoring of high power requests only.
boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
mOpHighPowerMonitoring = updateMonitoring(
requestingHighPowerLocation,
mOpHighPowerMonitoring,
- AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
+ true);
if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
- // Send an intent to notify that a high power request has been added/removed.
- Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ // Send an intent to notify that a high power request has been added/removed.
+ Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
- /**
- * Update AppOps monitoring for a single location request and op type.
- *
- * @param allowMonitoring True if monitoring is allowed for this request/op.
- * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
- * @param op AppOps code for the op to update.
- * @return True if monitoring is on for this request/op after updating.
- */
private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
- int op) {
+ boolean highPower) {
if (!currentlyMonitoring) {
if (allowMonitoring) {
- return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
- mCallerIdentity.mPackageName, false, mCallerIdentity.mFeatureId, null)
- == AppOpsManager.MODE_ALLOWED;
+ if (!highPower) {
+ return mAppOpsHelper.startLocationMonitoring(mCallerIdentity);
+ } else {
+ return mAppOpsHelper.startHighPowerLocationMonitoring(mCallerIdentity);
+ }
}
} else {
- if (!allowMonitoring
- || mAppOps.checkOpNoThrow(op, mCallerIdentity.mUid,
- mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) {
- mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName);
+ if (!allowMonitoring || !mAppOpsHelper.checkLocationAccess(mCallerIdentity)) {
+ if (!highPower) {
+ mAppOpsHelper.stopLocationMonitoring(mCallerIdentity);
+ } else {
+ mAppOpsHelper.stopHighPowerLocationMonitoring(mCallerIdentity);
+ }
return false;
}
}
@@ -1230,7 +1211,7 @@
new Location(location));
try {
mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
- getResolutionPermission(mAllowedResolutionLevel),
+ CallerIdentity.asPermission(mCallerIdentity.permissionLevel),
PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
// call this after broadcasting so we do not increment
// if we throw an exception.
@@ -1265,7 +1246,7 @@
providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
try {
mPendingIntent.send(mContext, 0, providerIntent, this, mHandler,
- getResolutionPermission(mAllowedResolutionLevel),
+ CallerIdentity.asPermission(mCallerIdentity.permissionLevel),
PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
// call this after broadcasting so we do not increment
// if we throw an exception.
@@ -1289,8 +1270,6 @@
@Override
public void binderDied() {
- if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
-
synchronized (mLock) {
removeUpdatesLocked(this);
clearPendingBroadcastsLocked();
@@ -1380,11 +1359,9 @@
@Override
public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
- String featureId, String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
-
+ String featureId) {
return mGnssManagerService != null && mGnssManagerService.addGnssBatchingCallback(
- callback, packageName, featureId, listenerIdentifier);
+ callback, packageName, featureId);
}
@Override
@@ -1393,9 +1370,10 @@
}
@Override
- public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
+ public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName,
+ String featureId) {
return mGnssManagerService != null && mGnssManagerService.startGnssBatch(periodNanos,
- wakeOnFifoFull, packageName);
+ wakeOnFifoFull, packageName, featureId);
}
@Override
@@ -1419,110 +1397,6 @@
return null;
}
- private String getResolutionPermission(int resolutionLevel) {
- switch (resolutionLevel) {
- case RESOLUTION_LEVEL_FINE:
- return ACCESS_FINE_LOCATION;
- case RESOLUTION_LEVEL_COARSE:
- return ACCESS_COARSE_LOCATION;
- default:
- return null;
- }
- }
-
- private int getAllowedResolutionLevel(int pid, int uid) {
- if (mContext.checkPermission(ACCESS_FINE_LOCATION, pid, uid) == PERMISSION_GRANTED) {
- return RESOLUTION_LEVEL_FINE;
- } else if (mContext.checkPermission(ACCESS_COARSE_LOCATION, pid, uid)
- == PERMISSION_GRANTED) {
- return RESOLUTION_LEVEL_COARSE;
- } else {
- return RESOLUTION_LEVEL_NONE;
- }
- }
-
- private int getCallerAllowedResolutionLevel() {
- return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
- }
-
- private boolean checkCallingOrSelfLocationPermission() {
- return mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED
- || mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
- == PERMISSION_GRANTED;
- }
-
- private void enforceCallingOrSelfLocationPermission() {
- if (checkCallingOrSelfLocationPermission()) {
- return;
- }
-
- throw new SecurityException("uid " + Binder.getCallingUid() + " does not have "
- + ACCESS_COARSE_LOCATION + " or " + ACCESS_FINE_LOCATION + ".");
- }
-
- private void enforceCallingOrSelfPackageName(String packageName) {
- int uid = Binder.getCallingUid();
- if (ArrayUtils.contains(mPackageManager.getPackagesForUid(uid), packageName)) {
- return;
- }
-
- throw new SecurityException("invalid package \"" + packageName + "\" for uid " + uid);
- }
-
- public static int resolutionLevelToOp(int allowedResolutionLevel) {
- if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
- if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
- return AppOpsManager.OP_COARSE_LOCATION;
- } else {
- return AppOpsManager.OP_FINE_LOCATION;
- }
- }
- return -1;
- }
-
- private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
- switch (allowedResolutionLevel) {
- case RESOLUTION_LEVEL_COARSE:
- return AppOpsManager.OPSTR_COARSE_LOCATION;
- case RESOLUTION_LEVEL_FINE:
- // fall through
- case RESOLUTION_LEVEL_NONE:
- // fall through
- default:
- // Use the most restrictive ops if not sure.
- return AppOpsManager.OPSTR_FINE_LOCATION;
- }
- }
-
- private boolean reportLocationAccessNoThrow(int pid, int uid, String packageName,
- @Nullable String featureId, int allowedResolutionLevel, @Nullable String message) {
- int op = resolutionLevelToOp(allowedResolutionLevel);
- if (op >= 0) {
- if (mAppOps.noteOpNoThrow(op, uid, packageName, featureId, message)
- != AppOpsManager.MODE_ALLOWED) {
- return false;
- }
- }
-
- return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
- }
-
- private boolean checkLocationAccess(int pid, int uid, String packageName,
- int allowedResolutionLevel) {
- int op = resolutionLevelToOp(allowedResolutionLevel);
- if (op >= 0) {
- if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
- return false;
- }
- }
-
- return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
- }
-
- /**
- * 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() {
ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
@@ -1535,14 +1409,9 @@
return providers;
}
- /**
- * Return all providers by name, that match criteria and are optionally
- * enabled.
- * Can return passive provider, but never returns fused provider.
- */
@Override
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
- if (!checkCallingOrSelfLocationPermission()) {
+ if (!CallerIdentity.checkCallingOrSelfLocationPermission(mContext)) {
return Collections.emptyList();
}
@@ -1556,9 +1425,8 @@
if (enabledOnly && !manager.isEnabled(UserHandle.getCallingUserId())) {
continue;
}
- if (criteria != null
- && !android.location.LocationProvider.propertiesMeetCriteria(
- name, manager.getProperties(), criteria)) {
+ if (criteria != null && !LocationProvider.propertiesMeetCriteria(name,
+ manager.getProperties(), criteria)) {
continue;
}
providers.add(name);
@@ -1567,18 +1435,14 @@
}
}
- /**
- * Return the name of the best provider given a Criteria object.
- * This method has been deprecated from the public API,
- * and the whole LocationProvider (including #meetsCriteria)
- * has been deprecated as well. So this method now uses
- * some simplified logic.
- */
@Override
public String getBestProvider(Criteria criteria, boolean enabledOnly) {
- List<String> providers = getProviders(criteria, enabledOnly);
- if (providers.isEmpty()) {
- providers = getProviders(null, enabledOnly);
+ List<String> providers;
+ synchronized (mLock) {
+ providers = getProviders(criteria, enabledOnly);
+ if (providers.isEmpty()) {
+ providers = getProviders(null, enabledOnly);
+ }
}
if (!providers.isEmpty()) {
@@ -1601,7 +1465,7 @@
if (records != null) {
for (UpdateRecord record : records) {
if (!mUserInfoHelper.isCurrentUserId(
- UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
+ UserHandle.getUserId(record.mReceiver.mCallerIdentity.uid))) {
continue;
}
@@ -1658,20 +1522,17 @@
// initialize the low power mode to true and set to false if any of the records requires
providerRequest.setLowPowerMode(true);
for (UpdateRecord record : records) {
- int userId = UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid);
- if (!mUserInfoHelper.isCurrentUserId(userId)) {
+ CallerIdentity identity = record.mReceiver.mCallerIdentity;
+ if (!mUserInfoHelper.isCurrentUserId(identity.userId)) {
continue;
}
- if (!checkLocationAccess(
- record.mReceiver.mCallerIdentity.mPid,
- record.mReceiver.mCallerIdentity.mUid,
- record.mReceiver.mCallerIdentity.mPackageName,
- record.mReceiver.mAllowedResolutionLevel)) {
+
+ if (!mAppOpsHelper.checkLocationAccess(identity)) {
continue;
}
final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
|| (isForegroundOnlyMode && !record.mIsForegroundUid);
- if (!manager.isEnabled(userId) || isBatterySaverDisablingLocation) {
+ if (!manager.isEnabled(identity.userId) || isBatterySaverDisablingLocation) {
if (isSettingsExempt(record)) {
providerRequest.setLocationSettingsIgnored(true);
providerRequest.setLowPowerMode(false);
@@ -1718,7 +1579,7 @@
long thresholdInterval = (providerRequest.getInterval() + 1000) * 3 / 2;
for (UpdateRecord record : records) {
if (mUserInfoHelper.isCurrentUserId(
- UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
+ UserHandle.getUserId(record.mReceiver.mCallerIdentity.uid))) {
LocationRequest locationRequest = record.mRequest;
// Don't assign battery blame for update records whose
@@ -1735,8 +1596,8 @@
// Assign blame to caller if there's no WorkSource associated with
// the request or if it's invalid.
providerRequest.getWorkSource().add(
- record.mReceiver.mCallerIdentity.mUid,
- record.mReceiver.mCallerIdentity.mPackageName);
+ record.mReceiver.mCallerIdentity.uid,
+ record.mReceiver.mCallerIdentity.packageName);
}
}
}
@@ -1775,16 +1636,16 @@
}
private boolean isThrottlingExempt(CallerIdentity callerIdentity) {
- if (callerIdentity.mUid == Process.SYSTEM_UID) {
+ if (callerIdentity.uid == Process.SYSTEM_UID) {
return true;
}
if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
- callerIdentity.mPackageName)) {
+ callerIdentity.packageName)) {
return true;
}
- return mLocalService.isProviderPackage(callerIdentity.mPackageName);
+ return mLocalService.isProviderPackage(callerIdentity.packageName);
}
@@ -1794,11 +1655,11 @@
}
if (mSettingsHelper.getIgnoreSettingsPackageWhitelist().contains(
- record.mReceiver.mCallerIdentity.mPackageName)) {
+ record.mReceiver.mCallerIdentity.packageName)) {
return true;
}
- return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName);
+ return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.packageName);
}
@@ -1821,9 +1682,9 @@
mRealRequest = request;
mRequest = request;
mReceiver = receiver;
- mIsForegroundUid = mAppForegroundHelper.isAppForeground(mReceiver.mCallerIdentity.mUid);
+ mIsForegroundUid = mAppForegroundHelper.isAppForeground(mReceiver.mCallerIdentity.uid);
- if (D && receiver.mCallerIdentity.mPid == Process.myPid()) {
+ if (D && receiver.mCallerIdentity.pid == Process.myPid()) {
mStackTrace = new Throwable();
}
@@ -1835,7 +1696,7 @@
// Update statistics for historical location requests by package/provider
mRequestStatistics.startRequesting(
- mReceiver.mCallerIdentity.mPackageName, mReceiver.mCallerIdentity.mFeatureId,
+ mReceiver.mCallerIdentity.packageName, mReceiver.mCallerIdentity.featureId,
provider, request.getInterval(), mIsForegroundUid);
}
@@ -1845,7 +1706,7 @@
private void updateForeground(boolean isForeground) {
mIsForegroundUid = isForeground;
mRequestStatistics.updateForeground(
- mReceiver.mCallerIdentity.mPackageName, mReceiver.mCallerIdentity.mFeatureId,
+ mReceiver.mCallerIdentity.packageName, mReceiver.mCallerIdentity.featureId,
mProvider, isForeground);
}
@@ -1853,19 +1714,18 @@
* Method to be called when a record will no longer be used.
*/
private void disposeLocked(boolean removeReceiver) {
- String packageName = mReceiver.mCallerIdentity.mPackageName;
- mRequestStatistics.stopRequesting(packageName, mReceiver.mCallerIdentity.mFeatureId,
- mProvider);
+ CallerIdentity identity = mReceiver.mCallerIdentity;
+ mRequestStatistics.stopRequesting(identity.packageName, identity.featureId, mProvider);
mLocationUsageLogger.logLocationApiUsage(
LocationStatsEnums.USAGE_ENDED,
LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
- packageName,
+ identity.packageName,
mRealRequest,
mReceiver.isListener(),
mReceiver.isPendingIntent(),
/* geofence= */ null,
- mAppForegroundHelper.getImportance(mReceiver.mCallerIdentity.mUid));
+ mAppForegroundHelper.getImportance(mReceiver.mCallerIdentity.uid));
// remove from mRecordsByProvider
ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
@@ -1889,18 +1749,10 @@
public String toString() {
StringBuilder b = new StringBuilder("UpdateRecord[");
b.append(mProvider).append(" ");
- b.append(mReceiver.mCallerIdentity.mPackageName);
- String featureId = mReceiver.mCallerIdentity.mFeatureId;
- if (featureId != null) {
- b.append(" ").append(featureId).append(" ");
+ b.append(mReceiver.mCallerIdentity).append(" ");
+ if (!mIsForegroundUid) {
+ b.append("(background) ");
}
- b.append("(").append(mReceiver.mCallerIdentity.mUid);
- if (mIsForegroundUid) {
- b.append(" foreground");
- } else {
- b.append(" background");
- }
- b.append(") ");
b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource);
if (mStackTrace != null) {
@@ -1915,14 +1767,13 @@
}
@GuardedBy("mLock")
- private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
- String packageName, @Nullable String featureId, WorkSource workSource,
- boolean hideFromAppOps, @NonNull String listenerIdentifier) {
+ private Receiver getReceiverLocked(ILocationListener listener, CallerIdentity identity,
+ WorkSource workSource, boolean hideFromAppOps) {
IBinder binder = listener.asBinder();
Receiver receiver = mReceivers.get(binder);
- if (receiver == null) {
- receiver = new Receiver(listener, null, pid, uid, packageName, featureId, workSource,
- hideFromAppOps, listenerIdentifier);
+ if (receiver == null && identity != null) {
+ receiver = new Receiver(listener, null, identity, workSource,
+ hideFromAppOps);
if (!receiver.linkToListenerDeathNotificationLocked(
receiver.getListener().asBinder())) {
return null;
@@ -1933,13 +1784,12 @@
}
@GuardedBy("mLock")
- private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
- @Nullable String featureId, WorkSource workSource, boolean hideFromAppOps,
- @NonNull String listenerIdentifier) {
+ private Receiver getReceiverLocked(PendingIntent intent, CallerIdentity identity,
+ WorkSource workSource, boolean hideFromAppOps) {
Receiver receiver = mReceivers.get(intent);
- if (receiver == null) {
- receiver = new Receiver(null, intent, pid, uid, packageName, featureId, workSource,
- hideFromAppOps, listenerIdentifier);
+ if (receiver == null && identity != null) {
+ receiver = new Receiver(null, intent, identity, workSource,
+ hideFromAppOps);
mReceivers.put(intent, receiver);
}
return receiver;
@@ -1953,14 +1803,14 @@
* @return a version of request that meets the given resolution and consistency requirements
* @hide
*/
- private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
+ private LocationRequest createSanitizedRequest(LocationRequest request, CallerIdentity identity,
boolean callerHasLocationHardwarePermission) {
LocationRequest sanitizedRequest = new LocationRequest(request);
if (!callerHasLocationHardwarePermission) {
// allow setting low power mode only for callers with location hardware permission
sanitizedRequest.setLowPowerMode(false);
}
- if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
+ if (identity.permissionLevel < PERMISSION_FINE) {
switch (sanitizedRequest.getQuality()) {
case LocationRequest.ACCURACY_FINE:
sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
@@ -1986,72 +1836,58 @@
@Override
public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
- PendingIntent intent, String packageName, String featureId,
- String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
+ PendingIntent intent, String packageName, String featureId) {
+ if (request == null) {
+ request = DEFAULT_LOCATION_REQUEST;
+ }
- enforceCallingOrSelfLocationPermission();
- enforceCallingOrSelfPackageName(packageName);
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ identity.enforceLocationPermission();
+
+ WorkSource workSource = request.getWorkSource();
+ if (workSource != null && !workSource.isEmpty()) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.UPDATE_DEVICE_STATS, null);
+ }
+ boolean hideFromAppOps = request.getHideFromAppOps();
+ if (hideFromAppOps) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.UPDATE_APP_OPS_STATS, null);
+ }
+ if (request.isLocationSettingsIgnored()) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.WRITE_SECURE_SETTINGS, null);
+ }
+ boolean callerHasLocationHardwarePermission =
+ mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
+ == PERMISSION_GRANTED;
+ LocationRequest sanitizedRequest = createSanitizedRequest(request,
+ identity,
+ callerHasLocationHardwarePermission);
+
+ if (intent == null && listener == null) {
+ throw new IllegalArgumentException("need either listener or intent");
+ } else if (intent != null && listener != null) {
+ throw new IllegalArgumentException(
+ "cannot register both listener and intent");
+ }
+
+ mLocationUsageLogger.logLocationApiUsage(
+ LocationStatsEnums.USAGE_STARTED,
+ LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
+ packageName, request, listener != null, intent != null,
+ /* geofence= */ null,
+ mAppForegroundHelper.getImportance(identity.uid));
synchronized (mLock) {
- if (request == null) request = DEFAULT_LOCATION_REQUEST;
- int allowedResolutionLevel = getCallerAllowedResolutionLevel();
- WorkSource workSource = request.getWorkSource();
- if (workSource != null && !workSource.isEmpty()) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.UPDATE_DEVICE_STATS, null);
+ Receiver receiver;
+ if (intent != null) {
+ receiver = getReceiverLocked(intent, identity, workSource, hideFromAppOps);
+ } else {
+ receiver = getReceiverLocked(listener, identity, workSource, hideFromAppOps);
}
- boolean hideFromAppOps = request.getHideFromAppOps();
- if (hideFromAppOps) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.UPDATE_APP_OPS_STATS, null);
- }
- if (request.isLocationSettingsIgnored()) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.WRITE_SECURE_SETTINGS, null);
- }
- boolean callerHasLocationHardwarePermission =
- mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
- == PERMISSION_GRANTED;
- LocationRequest sanitizedRequest = createSanitizedRequest(request,
- allowedResolutionLevel,
- callerHasLocationHardwarePermission);
-
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
-
- long identity = Binder.clearCallingIdentity();
- try {
-
- // We don't check for MODE_IGNORED here; we will do that when we go to deliver
- // a location.
- checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
-
- if (intent == null && listener == null) {
- throw new IllegalArgumentException("need either listener or intent");
- } else if (intent != null && listener != null) {
- throw new IllegalArgumentException(
- "cannot register both listener and intent");
- }
-
- mLocationUsageLogger.logLocationApiUsage(
- LocationStatsEnums.USAGE_STARTED,
- LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
- packageName, request, listener != null, intent != null,
- /* geofence= */ null,
- mAppForegroundHelper.getImportance(uid));
-
- Receiver receiver;
- if (intent != null) {
- receiver = getReceiverLocked(intent, pid, uid, packageName, featureId,
- workSource, hideFromAppOps, listenerIdentifier);
- } else {
- receiver = getReceiverLocked(listener, pid, uid, packageName, featureId,
- workSource, hideFromAppOps, listenerIdentifier);
- }
+ if (receiver != null) {
requestLocationUpdatesLocked(sanitizedRequest, receiver);
- } finally {
- Binder.restoreCallingIdentity(identity);
}
}
}
@@ -2078,28 +1914,27 @@
oldRecord.disposeLocked(false);
}
- int userId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
- if (!manager.isEnabled(userId) && !isSettingsExempt(record)) {
- // Notify the listener that updates are currently disabled - but only if the request
- // does not ignore location settings
- receiver.callProviderEnabledLocked(name, false);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ int userId = UserHandle.getUserId(receiver.mCallerIdentity.uid);
+ if (!manager.isEnabled(userId) && !isSettingsExempt(record)) {
+ // Notify the listener that updates are currently disabled - but only if the request
+ // does not ignore location settings
+ receiver.callProviderEnabledLocked(name, false);
+ }
+
+ applyRequirementsLocked(name);
+
+ // Update the monitoring here just in case multiple location requests were added to the
+ // same receiver (this request may be high power and the initial might not have been).
+ receiver.updateMonitoring(true);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
-
- applyRequirementsLocked(name);
-
- // Update the monitoring here just in case multiple location requests were added to the
- // same receiver (this request may be high power and the initial might not have been).
- receiver.updateMonitoring(true);
}
@Override
- public void removeUpdates(ILocationListener listener, PendingIntent intent,
- String packageName) {
- enforceCallingOrSelfPackageName(packageName);
-
- int pid = Binder.getCallingPid();
- int uid = Binder.getCallingUid();
-
+ public void removeUpdates(ILocationListener listener, PendingIntent intent) {
if (intent == null && listener == null) {
throw new IllegalArgumentException("need either listener or intent");
} else if (intent != null && listener != null) {
@@ -2109,17 +1944,13 @@
synchronized (mLock) {
Receiver receiver;
if (intent != null) {
- receiver = getReceiverLocked(intent, pid, uid, packageName, null, null, false, "");
+ receiver = getReceiverLocked(intent, null, null, false);
} else {
- receiver = getReceiverLocked(listener, pid, uid, packageName, null, null, false,
- "");
+ receiver = getReceiverLocked(listener, null, null, false);
}
- long identity = Binder.clearCallingIdentity();
- try {
+ if (receiver != null) {
removeUpdatesLocked(receiver);
- } finally {
- Binder.restoreCallingIdentity(identity);
}
}
}
@@ -2161,25 +1992,14 @@
request = DEFAULT_LOCATION_REQUEST;
}
- enforceCallingOrSelfLocationPermission();
- enforceCallingOrSelfPackageName(packageName);
+ // unsafe is ok because app ops will verify the package name
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
+ identity.enforceLocationPermission();
- int allowedResolutionLevel = getCallerAllowedResolutionLevel();
- if (!reportLocationAccessNoThrow(Binder.getCallingPid(), Binder.getCallingUid(),
- packageName, featureId, allowedResolutionLevel, null)) {
- if (D) {
- Log.d(TAG, "not returning last loc for no op app: " + packageName);
- }
+ if (mSettingsHelper.isLocationPackageBlacklisted(identity.userId, identity.packageName)) {
return null;
}
-
- int userId = UserHandle.getCallingUserId();
-
- if (mSettingsHelper.isLocationPackageBlacklisted(userId, packageName)) {
- return null;
- }
-
- if (!mUserInfoHelper.isCurrentUserId(userId)) {
+ if (!mUserInfoHelper.isCurrentUserId(identity.userId)) {
return null;
}
@@ -2188,40 +2008,26 @@
if (manager == null) {
return null;
}
-
- if (!manager.isEnabled(userId) && !request.isLocationSettingsIgnored()) {
+ if (!manager.isEnabled(identity.userId) && !request.isLocationSettingsIgnored()) {
return null;
}
- Location location;
- if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
- location = manager.getLastCoarseLocation(userId);
- } else {
- location = manager.getLastFineLocation(userId);
- }
- if (location == null) {
+ // appops check should always be right before delivery
+ if (!mAppOpsHelper.noteLocationAccess(identity)) {
return null;
}
- // Don't return stale location to apps with foreground-only location permission.
- String op = resolutionLevelToOpStr(allowedResolutionLevel);
- long locationAgeMs = NANOSECONDS.toMillis(
- SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
- if (locationAgeMs > mSettingsHelper.getMaxLastLocationAgeMs()
- && (mAppOps.unsafeCheckOp(op, Binder.getCallingUid(), packageName)
- == AppOpsManager.MODE_FOREGROUND)) {
- return null;
- }
+ Location location = manager.getLastLocation(identity.userId, identity.permissionLevel);
// make a defensive copy - the client could be in the same process as us
- return new Location(location);
+ return location != null ? new Location(location) : null;
}
}
@Override
public boolean getCurrentLocation(LocationRequest locationRequest,
ICancellationSignal remoteCancellationSignal, ILocationListener listener,
- String packageName, String featureId, String listenerIdentifier) {
+ String packageName, String featureId) {
// side effect of validating locationRequest and packageName
Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
if (lastLocation != null) {
@@ -2246,13 +2052,12 @@
}
}
- requestLocationUpdates(locationRequest, listener, null, packageName, featureId,
- listenerIdentifier);
+ requestLocationUpdates(locationRequest, listener, null, packageName, featureId);
CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
remoteCancellationSignal);
if (cancellationSignal != null) {
cancellationSignal.setOnCancelListener(
- () -> removeUpdates(listener, null, packageName));
+ () -> removeUpdates(listener, null));
}
return true;
}
@@ -2265,14 +2070,14 @@
return null;
}
- Location location = gpsManager.getLastFineLocation(UserHandle.getCallingUserId());
+ Location location = gpsManager.getLastLocation(UserHandle.getCallingUserId(),
+ PERMISSION_FINE);
if (location == null) {
return null;
}
long currentNanos = SystemClock.elapsedRealtimeNanos();
- long deltaMs = NANOSECONDS.toMillis(
- currentNanos - location.getElapsedRealtimeNanos());
+ long deltaMs = NANOSECONDS.toMillis(location.getElapsedRealtimeAgeNanos(currentNanos));
return new LocationTime(location.getTime() + deltaMs, currentNanos);
}
}
@@ -2295,32 +2100,27 @@
@Override
public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
- String packageName, String featureId, String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
-
- mContext.enforceCallingOrSelfPermission(ACCESS_FINE_LOCATION, null);
- enforceCallingOrSelfPackageName(packageName);
-
- if (request == null) request = DEFAULT_LOCATION_REQUEST;
- int allowedResolutionLevel = getCallerAllowedResolutionLevel();
- if (intent == null) {
- throw new IllegalArgumentException("invalid pending intent: " + null);
+ String packageName, String featureId) {
+ if (request == null) {
+ request = DEFAULT_LOCATION_REQUEST;
}
- // Require that caller can manage given document
+
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ identity.enforceLocationPermission();
+
+ Objects.requireNonNull(intent);
+
boolean callerHasLocationHardwarePermission =
mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
== PERMISSION_GRANTED;
- LocationRequest sanitizedRequest = createSanitizedRequest(request,
- allowedResolutionLevel,
+ LocationRequest sanitizedRequest = createSanitizedRequest(request, identity,
callerHasLocationHardwarePermission);
if (D) {
Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
}
- // geo-fence manager uses the public location API, need to clear identity
- int uid = Binder.getCallingUid();
- if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
+ if (identity.userId != UserHandle.USER_SYSTEM) {
// temporary measure until geofences work for secondary users
Log.w(TAG, "proximity alerts are currently available only to the primary user");
return;
@@ -2334,15 +2134,9 @@
/* hasListener= */ false,
true,
geofence,
- mAppForegroundHelper.getImportance(uid));
+ mAppForegroundHelper.getImportance(identity.uid));
- long identity = Binder.clearCallingIdentity();
- try {
- mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
- uid, packageName, featureId, listenerIdentifier);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ mGeofenceManager.addFence(sanitizedRequest, geofence, intent, identity);
}
@Override
@@ -2350,7 +2144,6 @@
if (intent == null) {
throw new IllegalArgumentException("invalid pending intent: " + null);
}
- enforceCallingOrSelfPackageName(packageName);
if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
@@ -2387,13 +2180,9 @@
@Override
public boolean addGnssMeasurementsListener(@Nullable GnssRequest request,
- IGnssMeasurementsListener listener,
- String packageName, String featureId,
- String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
-
+ IGnssMeasurementsListener listener, String packageName, String featureId) {
return mGnssManagerService != null && mGnssManagerService.addGnssMeasurementsListener(
- request, listener, packageName, featureId, listenerIdentifier);
+ request, listener, packageName, featureId);
}
@Override
@@ -2414,18 +2203,17 @@
}
@Override
- public long getGnssCapabilities(String packageName) {
- return mGnssManagerService == null ? 0L : mGnssManagerService.getGnssCapabilities(
- packageName);
+ public long getGnssCapabilities() {
+ return mGnssManagerService == null ? GnssCapabilities.INVALID_CAPABILITIES
+ : mGnssManagerService.getGnssCapabilities();
}
@Override
public boolean addGnssAntennaInfoListener(IGnssAntennaInfoListener listener,
- String packageName, String featureId, String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
+ String packageName, String featureId) {
return mGnssManagerService != null && mGnssManagerService.addGnssAntennaInfoListener(
- listener, packageName, featureId, listenerIdentifier);
+ listener, packageName, featureId);
}
@Override
@@ -2437,11 +2225,9 @@
@Override
public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
- String packageName, String featureId, String listenerIdentifier) {
- Objects.requireNonNull(listenerIdentifier);
-
+ String packageName, String featureId) {
return mGnssManagerService != null && mGnssManagerService.addGnssNavigationMessageListener(
- listener, packageName, featureId, listenerIdentifier);
+ listener, packageName, featureId);
}
@Override
@@ -2453,29 +2239,27 @@
}
@Override
- public boolean sendExtraCommand(String providerName, String command, Bundle extras) {
- Objects.requireNonNull(providerName);
- Objects.requireNonNull(command);
-
+ public boolean sendExtraCommand(String provider, String command, Bundle extras) {
+ CallerIdentity.enforceCallingOrSelfLocationPermission(mContext);
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, null);
- enforceCallingOrSelfLocationPermission();
+
+ LocationProviderManager manager = getLocationProviderManager(
+ Objects.requireNonNull(provider));
+ if (manager != null) {
+ manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(),
+ Objects.requireNonNull(command), extras);
+ }
mLocationUsageLogger.logLocationApiUsage(
LocationStatsEnums.USAGE_STARTED,
LocationStatsEnums.API_SEND_EXTRA_COMMAND,
- providerName);
-
- LocationProviderManager manager = getLocationProviderManager(providerName);
- if (manager != null) {
- manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(), command,
- extras);
- }
+ provider);
mLocationUsageLogger.logLocationApiUsage(
LocationStatsEnums.USAGE_ENDED,
LocationStatsEnums.API_SEND_EXTRA_COMMAND,
- providerName);
+ provider);
return true;
}
@@ -2537,12 +2321,10 @@
@Override
public void setLocationEnabledForUser(boolean enabled, int userId) {
- if (UserHandle.getCallingUserId() != userId) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS,
- null);
- }
- mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS,
- "Requires WRITE_SECURE_SETTINGS permission");
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, false, "setLocationEnabledForUser", null);
+
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS, null);
LocationManager.invalidateLocalLocationEnabledCaches();
mSettingsHelper.setLocationEnabled(enabled, userId);
@@ -2601,7 +2383,7 @@
}
@GuardedBy("mLock")
- private void handleLocationChangedLocked(LocationProviderManager manager, Location location,
+ private void handleLocationChangedLocked(LocationProviderManager manager, Location fineLocation,
Location coarseLocation) {
if (!mProviderManagers.contains(manager)) {
Log.w(TAG, "received location from unknown provider: " + manager.getName());
@@ -2610,7 +2392,7 @@
// notify passive provider
if (manager != mPassiveManager) {
- mPassiveManager.updateLocation(location);
+ mPassiveManager.updateLocation(fineLocation);
}
long now = SystemClock.elapsedRealtime();
@@ -2624,59 +2406,45 @@
// Broadcast location to all listeners
for (UpdateRecord r : records) {
Receiver receiver = r.mReceiver;
+ CallerIdentity identity = receiver.mCallerIdentity;
boolean receiverDead = false;
- int userId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
- if (!manager.isEnabled(userId) && !isSettingsExempt(r)) {
+ if (!manager.isEnabled(identity.userId) && !isSettingsExempt(r)) {
continue;
}
- if (!mUserInfoHelper.isCurrentUserId(userId)
- && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) {
- if (D) {
- Log.d(TAG, "skipping loc update for background user " + userId
- + " (app: " + receiver.mCallerIdentity.mPackageName + ")");
- }
+ if (!mUserInfoHelper.isCurrentUserId(identity.userId)
+ && !isProviderPackage(identity.packageName)) {
continue;
}
- if (mSettingsHelper.isLocationPackageBlacklisted(userId,
- receiver.mCallerIdentity.mPackageName)) {
- if (D) {
- Log.d(TAG, "skipping loc update for blacklisted app: " +
- receiver.mCallerIdentity.mPackageName);
- }
+ if (mSettingsHelper.isLocationPackageBlacklisted(identity.userId,
+ identity.packageName)) {
continue;
}
- Location notifyLocation;
- if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
- notifyLocation = coarseLocation; // use coarse location
- } else {
- notifyLocation = location; // use fine location
+ Location location;
+ switch (identity.permissionLevel) {
+ case PERMISSION_COARSE:
+ location = coarseLocation;
+ break;
+ case PERMISSION_FINE:
+ location = fineLocation;
+ break;
+ default:
+ throw new AssertionError();
}
- if (shouldBroadcastSafeLocked(notifyLocation, r.mLastFixBroadcast, r, now)) {
- r.mLastFixBroadcast = notifyLocation;
- // Report location access before delivering location to the client. This will
- // note location delivery to appOps, so it should be called only when a
- // location is really being delivered to the client.
- if (!reportLocationAccessNoThrow(
- receiver.mCallerIdentity.mPid,
- receiver.mCallerIdentity.mUid,
- receiver.mCallerIdentity.mPackageName,
- receiver.mCallerIdentity.mFeatureId,
- receiver.mAllowedResolutionLevel,
- "Location sent to " + receiver.mCallerIdentity.mListenerIdentifier)) {
- if (D) {
- Log.d(TAG, "skipping loc update for no op app: "
- + receiver.mCallerIdentity.mPackageName);
- }
+
+ if (shouldBroadcastSafeLocked(location, r.mLastFixBroadcast, r, now)) {
+ r.mLastFixBroadcast = location;
+
+ // appops check should always be right before delivery
+ if (!mAppOpsHelper.noteLocationAccess(receiver.mCallerIdentity)) {
continue;
}
- if (!receiver.callLocationChangedLocked(notifyLocation)) {
- Log.w(TAG, "RemoteException calling onLocationChanged on "
- + receiver);
+
+ if (!receiver.callLocationChangedLocked(location)) {
receiverDead = true;
}
r.mRealRequest.decrementNumUpdates();
@@ -2733,7 +2501,6 @@
return null;
}
-
@Override
public String getFromLocationName(String locationName,
double lowerLeftLatitude, double lowerLeftLongitude,
@@ -2752,9 +2519,10 @@
@Override
public void addTestProvider(String provider, ProviderProperties properties,
- String packageName) {
- if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ String packageName, String featureId) {
+ // unsafe is ok because app ops will verify the package name
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
+ if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
return;
}
@@ -2770,9 +2538,10 @@
}
@Override
- public void removeTestProvider(String provider, String packageName) {
- if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ public void removeTestProvider(String provider, String packageName, String featureId) {
+ // unsafe is ok because app ops will verify the package name
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
+ if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
return;
}
@@ -2790,15 +2559,17 @@
}
@Override
- public void setTestProviderLocation(String provider, Location location, String packageName) {
- Preconditions.checkArgument(location.isComplete(),
- "incomplete location object, missing timestamp or accuracy?");
-
- if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ public void setTestProviderLocation(String provider, Location location, String packageName,
+ String featureId) {
+ // unsafe is ok because app ops will verify the package name
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
+ if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
return;
}
+ Preconditions.checkArgument(location.isComplete(),
+ "incomplete location object, missing timestamp or accuracy?");
+
LocationProviderManager manager = getLocationProviderManager(provider);
if (manager == null) {
throw new IllegalArgumentException("provider doesn't exist: " + provider);
@@ -2808,9 +2579,11 @@
}
@Override
- public void setTestProviderEnabled(String provider, boolean enabled, String packageName) {
- if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ public void setTestProviderEnabled(String provider, boolean enabled, String packageName,
+ String featureId) {
+ // unsafe is ok because app ops will verify the package name
+ CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
+ if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
return;
}
@@ -2824,12 +2597,8 @@
@Override
@NonNull
- public List<LocationRequest> getTestProviderCurrentRequests(String provider,
- String packageName) {
- if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
- != AppOpsManager.MODE_ALLOWED) {
- return Collections.emptyList();
- }
+ public List<LocationRequest> getTestProviderCurrentRequests(String provider) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
LocationProviderManager manager = getLocationProviderManager(provider);
if (manager == null) {
diff --git a/services/core/java/com/android/server/LocationManagerServiceUtils.java b/services/core/java/com/android/server/LocationManagerServiceUtils.java
index ba1c81c..9d0fe5e 100644
--- a/services/core/java/com/android/server/LocationManagerServiceUtils.java
+++ b/services/core/java/com/android/server/LocationManagerServiceUtils.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.os.IBinder;
import android.os.RemoteException;
-import android.util.Log;
import com.android.server.location.CallerIdentity;
@@ -32,9 +31,6 @@
*/
public class LocationManagerServiceUtils {
- private static final String TAG = "LocManagerServiceUtils";
- private static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
-
/**
* Listener that can be linked to a binder.
* @param <TListener> listener type
@@ -49,10 +45,9 @@
public LinkedListener(
@Nullable TRequest request,
@NonNull TListener listener,
- String listenerName,
@NonNull CallerIdentity callerIdentity,
@NonNull Consumer<TListener> binderDeathCallback) {
- super(callerIdentity, listenerName);
+ super(callerIdentity);
mListener = listener;
mRequest = request;
mBinderDeathCallback = binderDeathCallback;
@@ -65,7 +60,6 @@
@Override
public void binderDied() {
- if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
mBinderDeathCallback.accept(mListener);
}
}
@@ -75,28 +69,20 @@
*/
public abstract static class LinkedListenerBase implements IBinder.DeathRecipient {
protected final CallerIdentity mCallerIdentity;
- protected final String mListenerName;
- LinkedListenerBase(
- @NonNull CallerIdentity callerIdentity, @NonNull String listenerName) {
+ LinkedListenerBase(@NonNull CallerIdentity callerIdentity) {
mCallerIdentity = callerIdentity;
- mListenerName = listenerName;
}
@Override
public String toString() {
- return mListenerName + "[" + mCallerIdentity.mPackageName + "(" + mCallerIdentity.mPid
- + ")]";
+ return mCallerIdentity.toString();
}
public CallerIdentity getCallerIdentity() {
return mCallerIdentity;
}
- public String getListenerName() {
- return mListenerName;
- }
-
/**
* Link listener (i.e. callback) to a binder, so that it will be called upon binder's death.
*/
@@ -105,9 +91,6 @@
binder.linkToDeath(this, 0 /* flags */);
return true;
} catch (RemoteException e) {
- // if the remote process registering the listener is already dead, just swallow the
- // exception and return
- Log.w(TAG, "Could not link " + mListenerName + " death callback.", e);
return false;
}
}
@@ -119,7 +102,7 @@
try {
binder.unlinkToDeath(this, 0 /* flags */);
} catch (NoSuchElementException e) {
- Log.w(TAG, "Could not unlink " + mListenerName + " death callback.", e);
+ // ignore
}
}
}
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 41a104c..d9e7c38 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -1062,7 +1062,12 @@
public void updatePackagesLocked(List<MonitoredPackage> packages) {
for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
MonitoredPackage p = packages.get(pIndex);
- this.packages.put(p.getName(), p);
+ MonitoredPackage existingPackage = this.packages.get(p.getName());
+ if (existingPackage != null) {
+ existingPackage.updateHealthCheckDuration(p.mDurationMs);
+ } else {
+ this.packages.put(p.getName(), p);
+ }
}
}
@@ -1331,6 +1336,12 @@
return updateHealthCheckStateLocked();
}
+ /** Explicitly update the monitoring duration of the package. */
+ @GuardedBy("mLock")
+ public void updateHealthCheckDuration(long newDurationMs) {
+ mDurationMs = newDurationMs;
+ }
+
/**
* Marks the health check as passed and transitions to {@link HealthCheckState.PASSED}
* if not yet {@link HealthCheckState.FAILED}.
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 4d8c86c..9018caa 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -4459,8 +4459,9 @@
String.format("/storage/emulated/%d/Android/data/%s/",
userId, pkg);
+ int appUid =
+ UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
// Create package obb and data dir if it doesn't exist.
- int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
File file = new File(packageObbDir);
if (!file.exists()) {
vold.setupAppDir(packageObbDir, appUid);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 895282c..2bbf278 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -27,6 +27,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
+import android.app.compat.CompatChanges;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -39,8 +40,10 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.telephony.Annotation;
import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.DataFailureCause;
@@ -177,8 +180,38 @@
}
}
+ /**
+ * Wrapper class to facilitate testing -- encapsulates bits of configuration that are
+ * normally fetched from static methods with many dependencies.
+ */
+ public static class ConfigurationProvider {
+ /**
+ * @return The per-pid registration limit for PhoneStateListeners, as set from DeviceConfig
+ * @noinspection ConstantConditions
+ */
+ public int getRegistrationLimit() {
+ return Binder.withCleanCallingIdentity(() ->
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_TELEPHONY,
+ PhoneStateListener.FLAG_PER_PID_REGISTRATION_LIMIT,
+ PhoneStateListener.DEFAULT_PER_PID_REGISTRATION_LIMIT));
+ }
+
+ /**
+ * @param uid uid to check
+ * @return Whether enforcement of the per-pid registation limit for PhoneStateListeners is
+ * enabled in PlatformCompat for the given uid.
+ * @noinspection ConstantConditions
+ */
+ public boolean isRegistrationLimitEnabledInPlatformCompat(int uid) {
+ return Binder.withCleanCallingIdentity(() -> CompatChanges.isChangeEnabled(
+ PhoneStateListener.PHONE_STATE_LISTENER_LIMIT_CHANGE_ID, uid));
+ }
+ }
+
private final Context mContext;
+ private ConfigurationProvider mConfigurationProvider;
+
// access should be inside synchronized (mRecords) for these two fields
private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>();
private final ArrayList<Record> mRecords = new ArrayList<Record>();
@@ -506,10 +539,11 @@
// handler before they get to app code.
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public TelephonyRegistry(Context context) {
+ public TelephonyRegistry(Context context, ConfigurationProvider configurationProvider) {
CellLocation location = CellLocation.getEmpty();
mContext = context;
+ mConfigurationProvider = configurationProvider;
mBatteryStats = BatteryStatsService.getService();
int numPhones = getTelephonyManager().getActiveModemCount();
@@ -605,7 +639,7 @@
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
- Record r = add(b);
+ Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), false);
if (r == null) {
return;
@@ -659,7 +693,7 @@
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
- Record r = add(b);
+ Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), false);
if (r == null) {
return;
@@ -789,7 +823,11 @@
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
- Record r = add(b);
+ boolean doesLimitApply =
+ Binder.getCallingUid() != Process.SYSTEM_UID
+ && Binder.getCallingUid() != Process.PHONE_UID
+ && Binder.getCallingUid() != Process.myUid();
+ Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), doesLimitApply);
if (r == null) {
return;
@@ -1084,18 +1122,44 @@
return record.canReadCallLog() ? mCallIncomingNumber[phoneId] : "";
}
- private Record add(IBinder binder) {
+ private Record add(IBinder binder, int callingUid, int callingPid, boolean doesLimitApply) {
Record r;
synchronized (mRecords) {
final int N = mRecords.size();
+ // While iterating through the records, keep track of how many we have from this pid.
+ int numRecordsForPid = 0;
for (int i = 0; i < N; i++) {
r = mRecords.get(i);
if (binder == r.binder) {
// Already existed.
return r;
}
+ if (r.callerPid == callingPid) {
+ numRecordsForPid++;
+ }
}
+ // If we've exceeded the limit for registrations, log an error and quit.
+ int registrationLimit = mConfigurationProvider.getRegistrationLimit();
+
+ if (doesLimitApply
+ && registrationLimit >= 1
+ && numRecordsForPid >= registrationLimit) {
+ String errorMsg = "Pid " + callingPid + " has exceeded the number of permissible"
+ + "registered listeners. Ignoring request to add.";
+ loge(errorMsg);
+ if (mConfigurationProvider
+ .isRegistrationLimitEnabledInPlatformCompat(callingUid)) {
+ throw new IllegalStateException(errorMsg);
+ }
+ } else if (doesLimitApply && numRecordsForPid
+ >= PhoneStateListener.DEFAULT_PER_PID_REGISTRATION_LIMIT / 2) {
+ // Log the warning independently of the dynamically set limit -- apps shouldn't be
+ // doing this regardless of whether we're throwing them an exception for it.
+ Rlog.w(TAG, "Pid " + callingPid + " has exceeded half the number of permissible"
+ + "registered listeners. Now at " + numRecordsForPid);
+ }
+
r = new Record();
r.binder = binder;
r.deathRecipient = new TelephonyRegistryDeathRecipient(binder);
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 564f9f3..58c388e 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -84,6 +84,7 @@
import static android.app.UiModeManager.MODE_NIGHT_AUTO;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
import static android.app.UiModeManager.MODE_NIGHT_YES;
+import static android.os.UserHandle.USER_SYSTEM;
import static android.util.TimeUtils.isTimeBetween;
final class UiModeManagerService extends SystemService {
@@ -151,6 +152,7 @@
// Example: Activate dark mode in the day time until sunrise the next day
private boolean mOverrideNightModeOn;
private boolean mOverrideNightModeOff;
+ private int mOverrideNightModeUser = USER_SYSTEM;
private PowerManager.WakeLock mWakeLock;
@@ -668,10 +670,7 @@
mNightMode = mode;
resetNightModeOverrideLocked();
- // Only persist setting if not in car mode
- if (!mCarModeEnabled) {
- persistNightMode(user);
- }
+ persistNightMode(user);
// on screen off will update configuration instead
if ((mNightMode != MODE_NIGHT_AUTO && mNightMode != MODE_NIGHT_CUSTOM)
|| shouldApplyAutomaticChangesImmediately()) {
@@ -730,6 +729,8 @@
unregisterScreenOffEventLocked();
mOverrideNightModeOff = !active;
mOverrideNightModeOn = active;
+ mOverrideNightModeUser = user;
+ persistNightModeOverrides(user);
} else if (mNightMode == UiModeManager.MODE_NIGHT_NO
&& active) {
mNightMode = UiModeManager.MODE_NIGHT_YES;
@@ -1008,12 +1009,10 @@
}
private void persistNightMode(int user) {
+ // Only persist setting if not in car mode
+ if (mCarModeEnabled) return;
Secure.putIntForUser(getContext().getContentResolver(),
Secure.UI_NIGHT_MODE, mNightMode, user);
- Secure.putIntForUser(getContext().getContentResolver(),
- Secure.UI_NIGHT_MODE_OVERRIDE_ON, mOverrideNightModeOn ? 1 : 0, user);
- Secure.putIntForUser(getContext().getContentResolver(),
- Secure.UI_NIGHT_MODE_OVERRIDE_OFF, mOverrideNightModeOff ? 1 : 0, user);
Secure.putLongForUser(getContext().getContentResolver(),
Secure.DARK_THEME_CUSTOM_START_TIME,
mCustomAutoNightModeStartMilliseconds.toNanoOfDay() / 1000, user);
@@ -1022,6 +1021,15 @@
mCustomAutoNightModeEndMilliseconds.toNanoOfDay() / 1000, user);
}
+ private void persistNightModeOverrides(int user) {
+ // Only persist setting if not in car mode
+ if (mCarModeEnabled) return;
+ Secure.putIntForUser(getContext().getContentResolver(),
+ Secure.UI_NIGHT_MODE_OVERRIDE_ON, mOverrideNightModeOn ? 1 : 0, user);
+ Secure.putIntForUser(getContext().getContentResolver(),
+ Secure.UI_NIGHT_MODE_OVERRIDE_OFF, mOverrideNightModeOff ? 1 : 0, user);
+ }
+
private void updateConfigurationLocked() {
int uiMode = mDefaultUiModeType;
if (mUiModeLocked) {
@@ -1392,12 +1400,15 @@
}
}
- private void resetNightModeOverrideLocked() {
+ private boolean resetNightModeOverrideLocked() {
if (mOverrideNightModeOff || mOverrideNightModeOn) {
mOverrideNightModeOff = false;
mOverrideNightModeOn = false;
- persistNightMode(UserHandle.getCallingUserId());
+ persistNightModeOverrides(mOverrideNightModeUser);
+ mOverrideNightModeUser = USER_SYSTEM;
+ return true;
}
+ return false;
}
private void registerVrStateListener() {
@@ -1538,7 +1549,7 @@
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
final int currentId = intent.getIntExtra(
- Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM);
+ Intent.EXTRA_USER_HANDLE, USER_SYSTEM);
// only update if the value is actually changed
if (updateNightModeFromSettingsLocked(context, context.getResources(), currentId)) {
updateLocked(0, 0);
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 0561567..061ff42 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -120,6 +120,7 @@
"android.hardware.media.c2@1.0::IComponentStore",
"android.hardware.media.omx@1.0::IOmx",
"android.hardware.media.omx@1.0::IOmxStore",
+ "android.hardware.neuralnetworks@1.0::IDevice",
"android.hardware.power.stats@1.0::IPowerStats",
"android.hardware.sensors@1.0::ISensors",
"android.hardware.vr@1.0::IVr",
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index d77bee3..714aae1 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -4898,6 +4898,12 @@
return true;
}
+ // Is the calling UID a device owner app?
+ final boolean isDeviceOwner = mAm.mInternal.isDeviceOwner(callingUid);
+ if (isDeviceOwner) {
+ return true;
+ }
+
r.mInfoDenyWhileInUsePermissionInFgs =
"Background FGS start while-in-use permission restriction [callingPackage: "
+ callingPackage
@@ -4933,7 +4939,8 @@
+ r.mRecentCallingPackage
+ "; intent:" + r.intent.getIntent()
+ "] affected while-in-use permission:"
- + AppOpsManager.opToPublicName(op);
+ + AppOpsManager.opToPublicName(op)
+ + "; targetSdkVersion:" + r.appInfo.targetSdkVersion;
Slog.wtf(TAG, msg);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 38405e1..bd905da 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -636,6 +636,8 @@
*/
String mDeviceOwnerName;
+ private int mDeviceOwnerUid = Process.INVALID_UID;
+
final UserController mUserController;
@VisibleForTesting
public final PendingIntentController mPendingIntentController;
@@ -15566,7 +15568,7 @@
}
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
- int callingUid, int[] users) {
+ int callingUid, int[] users, int[] broadcastWhitelist) {
// TODO: come back and remove this assumption to triage all broadcasts
int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
@@ -15642,6 +15644,15 @@
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
+ if (receivers != null && broadcastWhitelist != null) {
+ for (int i = receivers.size() - 1; i >= 0; i--) {
+ final int uid = receivers.get(i).activityInfo.applicationInfo.uid;
+ if (uid >= Process.FIRST_APPLICATION_UID
+ && Arrays.binarySearch(broadcastWhitelist, UserHandle.getAppId(uid)) < 0) {
+ receivers.remove(i);
+ }
+ }
+ }
return receivers;
}
@@ -15736,7 +15747,8 @@
return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,
resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,
appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid,
- realCallingPid, userId, false /* allowBackgroundActivityStarts */);
+ realCallingPid, userId, false /* allowBackgroundActivityStarts */,
+ null /*broadcastWhitelist*/);
}
@GuardedBy("this")
@@ -15745,7 +15757,8 @@
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
- int realCallingPid, int userId, boolean allowBackgroundActivityStarts) {
+ int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
+ @Nullable int[] broadcastWhitelist) {
intent = new Intent(intent);
final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
@@ -15754,6 +15767,12 @@
intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
}
+ if (userId == UserHandle.USER_ALL && broadcastWhitelist != null) {
+ Slog.e(TAG, "broadcastWhitelist only applies when sending to individual users. "
+ + "Assuming restrictive whitelist.");
+ broadcastWhitelist = new int[]{};
+ }
+
// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
@@ -16240,7 +16259,8 @@
// Need to resolve the intent to interested receivers...
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
- receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
+ receivers = collectReceiverComponents(
+ intent, resolvedType, callingUid, users, broadcastWhitelist);
}
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
@@ -16270,6 +16290,17 @@
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()
+ " replacePending=" + replacePending);
+ if (registeredReceivers != null && broadcastWhitelist != null) {
+ // if a uid whitelist was provided, remove anything in the application space that wasn't
+ // in it.
+ for (int i = registeredReceivers.size() - 1; i >= 0; i--) {
+ final int uid = registeredReceivers.get(i).owningUid;
+ if (uid >= Process.FIRST_APPLICATION_UID
+ && Arrays.binarySearch(broadcastWhitelist, UserHandle.getAppId(uid)) < 0) {
+ registeredReceivers.remove(i);
+ }
+ }
+ }
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
@@ -16553,7 +16584,8 @@
return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType,
resultTo, resultCode, resultData, resultExtras, requiredPermissions,
OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid,
- realCallingPid, userId, allowBackgroundActivityStarts);
+ realCallingPid, userId, allowBackgroundActivityStarts,
+ null /*broadcastWhitelist*/);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -19184,6 +19216,32 @@
}
@Override
+ public int broadcastIntent(Intent intent,
+ IIntentReceiver resultTo,
+ String[] requiredPermissions,
+ boolean serialized, int userId, int[] appIdWhitelist) {
+ synchronized (ActivityManagerService.this) {
+ intent = verifyBroadcastLocked(intent);
+
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ return ActivityManagerService.this.broadcastIntentLocked(null /*callerApp*/,
+ null /*callerPackage*/, null /*callingFeatureId*/, intent,
+ null /*resolvedType*/, resultTo, 0 /*resultCode*/, null /*resultData*/,
+ null /*resultExtras*/, requiredPermissions, AppOpsManager.OP_NONE,
+ null /*options*/, serialized, false /*sticky*/, callingPid, callingUid,
+ callingUid, callingPid, userId, false /*allowBackgroundStarts*/,
+ appIdWhitelist);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ }
+
+ @Override
public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
boolean fgRequired, String callingPackage, @Nullable String callingFeatureId,
int userId, boolean allowBackgroundActivityStarts)
@@ -19491,6 +19549,20 @@
uid, op, mode);
}
}
+
+ @Override
+ public void setDeviceOwnerUid(int uid) {
+ synchronized (ActivityManagerService.this) {
+ mDeviceOwnerUid = uid;
+ }
+ }
+
+ @Override
+ public boolean isDeviceOwner(int uid) {
+ synchronized (ActivityManagerService.this) {
+ return uid >= 0 && mDeviceOwnerUid == uid;
+ }
+ }
}
long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index d4a0502..1412112 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -151,10 +151,14 @@
@EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q)
static final long CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID = 136219221L;
- //TODO: remove this when development is done.
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 30;
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 29;
+ // TODO: remove this when development is done.
+ // These are debug flags used between OomAdjuster and AppOpsService to detect and report absence
+ // of the real flags.
+ public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q = 1 << 27;
+ public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q = 1 << 28;
+ public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 29;
+ public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 30;
+ public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
/**
* For some direct access we need to power manager.
@@ -1501,7 +1505,7 @@
//TODO: remove this block when development is done.
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
- != 0 ? TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
+ != 0 ? DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
}
if (s.mAllowWhileInUsePermissionInFgs) {
boolean enabled = false;
@@ -1514,22 +1518,22 @@
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA
- : TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+ : DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- : TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+ : DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
} else {
// Remove fgsType check and assign PROCESS_CAPABILITY_FOREGROUND_CAMERA
// and MICROPHONE when finish debugging.
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA
- : TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+ : DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q;
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- : TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+ : DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q;
}
}
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index bee0e05..595275d 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -94,11 +94,9 @@
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
-import android.provider.DeviceConfig;
import android.system.Os;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.EventLog;
import android.util.LongSparseArray;
import android.util.Pair;
@@ -139,7 +137,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* Activity manager code dealing with processes.
@@ -155,10 +152,6 @@
static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
"persist.sys.vold_app_data_isolation_enabled";
- // A device config to control the minimum target SDK to enable app data isolation
- static final String ANDROID_APP_DATA_ISOLATION_MIN_SDK =
- "android_app_data_isolation_min_sdk";
-
// The minimum time we allow between crashes, for us to consider this
// application to be bad and stop and its services and reject broadcasts.
static final int MIN_CRASH_INTERVAL = 60 * 1000;
@@ -2127,25 +2120,6 @@
}
}
- private boolean shouldIsolateAppData(ProcessRecord app) {
- if (!mAppDataIsolationEnabled) {
- return false;
- }
- if (!UserHandle.isApp(app.uid)) {
- return false;
- }
- final int minTargetSdk = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
- ANDROID_APP_DATA_ISOLATION_MIN_SDK, Build.VERSION_CODES.R);
- if (app.info.targetSdkVersion < minTargetSdk) {
- return false;
- }
-
- // TODO(b/147266020): Remove non-standard gating above & switch to isChangeEnabled.
- mPlatformCompat.reportChange(APP_DATA_DIRECTORY_ISOLATION, app.info);
-
- return true;
- }
-
private Map<String, Pair<String, Long>> getPackageAppDataInfoMap(PackageManagerInternal pmInt,
String[] packages, int uid) {
Map<String, Pair<String, Long>> result = new ArrayMap<>(packages.length);
@@ -2157,6 +2131,15 @@
result.put(packageName, Pair.create(volumeUuid, inode));
}
}
+ if (mAppDataIsolationWhitelistedApps != null) {
+ for (String packageName : mAppDataIsolationWhitelistedApps) {
+ String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid();
+ long inode = pmInt.getCeDataInode(packageName, userId);
+ if (inode != 0) {
+ result.put(packageName, Pair.create(volumeUuid, inode));
+ }
+ }
+ }
return result;
}
@@ -2177,42 +2160,35 @@
app.setHasForegroundActivities(true);
}
- final Map<String, Pair<String, Long>> pkgDataInfoMap;
- final Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
- boolean bindMountAppStorageDirs = false;
- boolean bindMountAppsData = shouldIsolateAppData(app);
-
- // Get all packages belongs to the same shared uid. sharedPackages is empty array
- // if it doesn't have shared uid.
- final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
- final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
- app.info.packageName, app.userId);
- final String[] targetPackagesList = sharedPackages.length == 0
- ? new String[]{app.info.packageName} : sharedPackages;
- pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
-
- // Remove all packages in pkgDataInfoMap from mAppDataIsolationWhitelistedApps, so
- // it won't be mounted twice.
- final Set<String> whitelistedApps = new ArraySet<>(mAppDataIsolationWhitelistedApps);
- for (String pkg : targetPackagesList) {
- whitelistedApps.remove(pkg);
- }
- whitelistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,
- whitelistedApps.toArray(new String[0]), uid);
-
- int userId = UserHandle.getUserId(uid);
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
- if (mVoldAppDataIsolationEnabled && UserHandle.isApp(app.uid) &&
- !storageManagerInternal.isExternalStorageService(uid)) {
- bindMountAppStorageDirs = true;
- if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
- app.processName)) {
- // Cannot prepare Android/app and Android/obb directory,
- // so we won't mount it in zygote.
- app.bindMountPending = true;
- bindMountAppStorageDirs = false;
+ final Map<String, Pair<String, Long>> pkgDataInfoMap;
+ boolean bindMountAppStorageDirs = false;
+
+ if (mAppDataIsolationEnabled && UserHandle.isApp(app.uid)
+ && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info)) {
+ // Get all packages belongs to the same shared uid. sharedPackages is empty array
+ // if it doesn't have shared uid.
+ final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
+ final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
+ app.info.packageName, app.userId);
+ pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, sharedPackages.length == 0
+ ? new String[]{app.info.packageName} : sharedPackages, uid);
+
+ int userId = UserHandle.getUserId(uid);
+ if (mVoldAppDataIsolationEnabled
+ && !storageManagerInternal.isExternalStorageService(uid)) {
+ bindMountAppStorageDirs = true;
+ if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
+ app.processName)) {
+ // Cannot prepare Android/app and Android/obb directory,
+ // so we won't mount it in zygote.
+ app.bindMountPending = true;
+ bindMountAppStorageDirs = false;
+ }
}
+ } else {
+ pkgDataInfoMap = null;
}
final Process.ProcessStartResult startResult;
@@ -2230,8 +2206,7 @@
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
- app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
- bindMountAppsData, bindMountAppStorageDirs,
+ app.mDisabledCompatChanges, pkgDataInfoMap, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
@@ -2239,7 +2214,7 @@
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
- whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
+ bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
}
checkSlow(startTime, "startProcess: returned from zygote!");
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 636a0e9..e02c6f9 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -159,6 +159,9 @@
// when it never calls back.
private static final int USER_SWITCH_CALLBACKS_TIMEOUT_MS = 5 * 1000;
+ // TODO(b/149604218): STOPSHIP remove this constant and the logcat
+ private static final boolean TESTS_NEED_LOGCAT = true;
+
/**
* Maximum number of users we allow to be running at a time, including system user.
*
@@ -1668,6 +1671,9 @@
}
void continueUserSwitch(UserState uss, int oldUserId, int newUserId) {
+ if (TESTS_NEED_LOGCAT) {
+ Slog.d(TAG, "Continue user switch oldUser #" + oldUserId + ", newUser #" + newUserId);
+ }
EventLog.writeEvent(EventLogTags.UC_CONTINUE_USER_SWITCH, oldUserId, newUserId);
if (isUserSwitchUiEnabled()) {
@@ -1675,8 +1681,7 @@
}
uss.switching = false;
mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
- mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_COMPLETE_MSG,
- newUserId, 0));
+ mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_COMPLETE_MSG, newUserId, 0));
stopGuestOrEphemeralUserIfBackground(oldUserId);
stopBackgroundUsersIfEnforced(oldUserId);
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 6613d5f..8e6ef75 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -66,6 +66,11 @@
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
import static android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP;
+import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q;
+import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q;
import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS;
import static java.lang.Long.max;
@@ -248,9 +253,6 @@
private static final int RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS = 300000;
//TODO: remove this when development is done.
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 30;
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 29;
private static final int DEBUG_FGS_ALLOW_WHILE_IN_USE = 0;
private static final int DEBUG_FGS_ENFORCE_TYPE = 1;
@@ -552,7 +554,7 @@
if ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
return MODE_ALLOWED;
} else if ((capability
- & TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
+ & DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
// The FGS has the location capability, but due to FGS BG start
// restriction it lost the capability, use temp location capability
// to mark this case.
@@ -564,11 +566,14 @@
case OP_CAMERA:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
return MODE_ALLOWED;
- } else if ((capability & TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA)
+ } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q)
!= 0) {
- // CHANGE TO MODE_IGNORED when enforce this feature.
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
return MODE_ALLOWED;
+ } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA)
+ != 0) {
+ maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
+ return MODE_IGNORED;
} else {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
@@ -576,11 +581,14 @@
case OP_RECORD_AUDIO:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
return MODE_ALLOWED;
- } else if ((capability & TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE)
- != 0) {
- // CHANGE TO MODE_IGNORED when enforce this feature.
+ } else if ((capability
+ & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q) != 0) {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
return MODE_ALLOWED;
+ } else if ((capability
+ & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
+ maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
+ return MODE_IGNORED;
} else {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
@@ -597,10 +605,13 @@
case OP_CAMERA:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
return MODE_ALLOWED;
- } else if ((capability & TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
- // CHANGE TO MODE_IGNORED when enforce this feature.
+ } else if ((capability
+ & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q) != 0) {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
return MODE_ALLOWED;
+ } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
+ maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
+ return MODE_IGNORED;
} else {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
@@ -608,11 +619,14 @@
case OP_RECORD_AUDIO:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
return MODE_ALLOWED;
- } else if ((capability & TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE)
+ } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q)
!= 0) {
- // CHANGE TO MODE_IGNORED when enforce this feature.
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
return MODE_ALLOWED;
+ } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE)
+ != 0) {
+ maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
+ return MODE_IGNORED;
} else {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 94675ab..8bce504 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -634,6 +634,9 @@
}
};
+ @GuardedBy("mSettingsLock")
+ private boolean mRttEnabled = false;
+
///////////////////////////////////////////////////////////////////////////
// Construction
///////////////////////////////////////////////////////////////////////////
@@ -1053,7 +1056,7 @@
sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
sendEnabledSurroundFormats(mContentResolver, true);
updateAssistantUId(true);
- updateRttEanbled(mContentResolver);
+ AudioSystem.setRttEnabled(mRttEnabled);
}
synchronized (mAccessibilityServiceUidsLock) {
AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
@@ -1598,12 +1601,6 @@
}
}
- private void updateRttEanbled(ContentResolver cr) {
- final boolean rttEnabled = Settings.Secure.getIntForUser(cr,
- Settings.Secure.RTT_CALLING_MODE, 0, UserHandle.USER_CURRENT) != 0;
- AudioSystem.setRttEnabled(rttEnabled);
- }
-
private void readPersistedSettings() {
final ContentResolver cr = mContentResolver;
@@ -1648,7 +1645,7 @@
sendEncodedSurroundMode(cr, "readPersistedSettings");
sendEnabledSurroundFormats(cr, true);
updateAssistantUId(true);
- updateRttEanbled(cr);
+ AudioSystem.setRttEnabled(mRttEnabled);
}
mMuteAffectedStreams = System.getIntForUser(cr,
@@ -3684,6 +3681,27 @@
return mIsCallScreeningModeSupported;
}
+ /** @see AudioManager#setRttEnabled() */
+ @Override
+ public void setRttEnabled(boolean rttEnabled) {
+ if (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_PHONE_STATE)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setRttEnabled from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+ synchronized (mSettingsLock) {
+ mRttEnabled = rttEnabled;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ AudioSystem.setRttEnabled(rttEnabled);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
//==========================================================================================
// Sound Effects
//==========================================================================================
@@ -5825,8 +5843,6 @@
mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
- mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.RTT_CALLING_MODE), false, this);
}
@Override
@@ -5850,7 +5866,6 @@
updateEncodedSurroundOutput();
sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged);
updateAssistantUId(false);
- updateRttEanbled(mContentResolver);
}
}
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index ff8e3a9..a0876c0 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -158,7 +158,8 @@
|| bundle.getCharSequence(
BiometricPrompt.KEY_DEVICE_CREDENTIAL_SUBTITLE) != null
|| bundle.getCharSequence(
- BiometricPrompt.KEY_DEVICE_CREDENTIAL_DESCRIPTION) != null) {
+ BiometricPrompt.KEY_DEVICE_CREDENTIAL_DESCRIPTION) != null
+ || bundle.getBoolean(BiometricPrompt.KEY_RECEIVE_SYSTEM_EVENTS, false)) {
checkInternalPermission();
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 233416d..d49b590 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -112,6 +112,7 @@
private static final int MSG_CANCEL_AUTHENTICATION = 10;
private static final int MSG_ON_AUTHENTICATION_TIMED_OUT = 11;
private static final int MSG_ON_DEVICE_CREDENTIAL_PRESSED = 12;
+ private static final int MSG_ON_SYSTEM_EVENT = 13;
/**
* Authentication either just called and we have not transitioned to the CALLED state, or
@@ -360,6 +361,11 @@
break;
}
+ case MSG_ON_SYSTEM_EVENT: {
+ handleOnSystemEvent((int) msg.obj);
+ break;
+ }
+
default:
Slog.e(TAG, "Unknown message: " + msg);
break;
@@ -632,6 +638,11 @@
public void onDeviceCredentialPressed() {
mHandler.sendEmptyMessage(MSG_ON_DEVICE_CREDENTIAL_PRESSED);
}
+
+ @Override
+ public void onSystemEvent(int event) {
+ mHandler.obtainMessage(MSG_ON_SYSTEM_EVENT, event).sendToTarget();
+ }
};
@@ -1579,6 +1590,27 @@
mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
}
+ private void handleOnSystemEvent(int event) {
+ final boolean shouldReceive = mCurrentAuthSession.mBundle
+ .getBoolean(BiometricPrompt.KEY_RECEIVE_SYSTEM_EVENTS, false);
+ Slog.d(TAG, "onSystemEvent: " + event + ", shouldReceive: " + shouldReceive);
+
+ if (mCurrentAuthSession == null) {
+ Slog.e(TAG, "Auth session null");
+ return;
+ }
+
+ if (!shouldReceive) {
+ return;
+ }
+
+ try {
+ mCurrentAuthSession.mClientReceiver.onSystemEvent(event);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException", e);
+ }
+ }
+
/**
* Invoked when each service has notified that its client is ready to be started. When
* all biometrics are ready, this invokes the SystemUI dialog through StatusBar.
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index e09cf61..0d82433 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -31,7 +31,6 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.math.BigDecimal;
import java.util.List;
import javax.xml.datatype.DatatypeConfigurationException;
@@ -50,7 +49,6 @@
private float[] mNits;
private float[] mBrightness;
- private BigDecimal mHighBrightnessModeStart;
private DisplayDeviceConfig() {
}
@@ -88,18 +86,6 @@
return mBrightness;
}
- /**
- * Returns the point along the brightness value range {@link #getBrightness()} that
- * high-brightness-mode begins. If high-brightness-mode is not supported, then
- * Float.NaN is returned.
- *
- * @return The high brightness mode threshold, or Float.NaN if not supported.
- */
- public float getHighBrightnessModeStart() {
- return mHighBrightnessModeStart != null
- ? mHighBrightnessModeStart.floatValue() : HIGH_BRIGHTNESS_MODE_UNSUPPORTED;
- }
-
private void initFromFile(File configFile) {
if (!configFile.exists()) {
// Display configuration files aren't required to exist.
@@ -148,9 +134,6 @@
}
++i;
}
- final BigDecimal hbmStart = map.getHighBrightnessStart();
-
- mHighBrightnessModeStart = hbmStart;
mNits = nits;
mBrightness = backlight;
}
diff --git a/services/core/java/com/android/server/hdmi/README.md b/services/core/java/com/android/server/hdmi/README.md
new file mode 100644
index 0000000..2b510b5
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/README.md
@@ -0,0 +1,7 @@
+# Package com.android.server.hdmi
+
+HDMI service for Android with focus on CEC
+
+## Links
+
+* [CEC Key Handling](cec_key_handling.md)
diff --git a/services/core/java/com/android/server/hdmi/cec_key_handling.md b/services/core/java/com/android/server/hdmi/cec_key_handling.md
new file mode 100644
index 0000000..d150dd3
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/cec_key_handling.md
@@ -0,0 +1,36 @@
+# CEC Key Handling
+
+The mapping of CEC key codes to Android key codes are at
+[HdmiCecKeycode](HdmiCecKeycode.java)
+
+# Android TV
+
+Android TV requires special handling of some keys.
+
+The general action for key handling is described in the table
+
+| Android Key | TV Panel | OTT | Soundbar |
+| ----------- | ----------------- | ------------------- | ------------------- |
+| general | Send to active source | handle on device | handle on device |
+| POWER | Toggle the device power state | Toggle the TV power state | Toggle the TV power state |
+| TV_POWER | Toggle the device power state | Toggle the TV power state | Toggle the TV power state |
+| HOME | Turn on TV, Set active Source to TV, go to home screen | OTP, and go to home screen | OTP, and go to home screen |
+| volume keys | Handle on device or send to soundbar | Send to TV or soundbar | Handle on device or send to TV |
+
+Special cases and flags for each key are described below
+
+## POWER
+
+### TV Panel
+
+TODO
+
+### OTT
+
+TODO
+
+### Soundbar
+
+TODO
+
+
diff --git a/services/core/java/com/android/server/incident/PendingReports.java b/services/core/java/com/android/server/incident/PendingReports.java
index 9fcbab7..f39bebf 100644
--- a/services/core/java/com/android/server/incident/PendingReports.java
+++ b/services/core/java/com/android/server/incident/PendingReports.java
@@ -359,6 +359,8 @@
private void sendBroadcast(ComponentName receiver, int primaryUser) {
final Intent intent = new Intent(Intent.ACTION_PENDING_INCIDENT_REPORTS_CHANGED);
intent.setComponent(receiver);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
final BroadcastOptions options = BroadcastOptions.makeBasic();
options.setBackgroundActivityStartsAllowed(true);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index e6129b9..0b22586 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -76,6 +76,7 @@
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputMonitor;
+import android.view.InputWindowHandle;
import android.view.KeyEvent;
import android.view.PointerIcon;
import android.view.Surface;
@@ -220,7 +221,8 @@
int policyFlags);
private static native VerifiedInputEvent nativeVerifyInputEvent(long ptr, InputEvent event);
private static native void nativeToggleCapsLock(long ptr, int deviceId);
- private static native void nativeDisplayRemoved(long ptr, int displayId);
+ private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles,
+ int displayId);
private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
private static native void nativeSetFocusedApplication(long ptr,
@@ -1534,7 +1536,7 @@
/** Clean up input window handles of the given display. */
public void onDisplayRemoved(int displayId) {
- nativeDisplayRemoved(mPtr, displayId);
+ nativeSetInputWindows(mPtr, null /* windowHandles */, displayId);
}
@Override
diff --git a/services/core/java/com/android/server/location/AppOpsHelper.java b/services/core/java/com/android/server/location/AppOpsHelper.java
new file mode 100644
index 0000000..9c27916
--- /dev/null
+++ b/services/core/java/com/android/server/location/AppOpsHelper.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location;
+
+import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
+import static android.app.AppOpsManager.OP_MONITOR_LOCATION;
+
+import static com.android.server.LocationManagerService.D;
+import static com.android.server.LocationManagerService.TAG;
+
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.Binder;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.FgThread;
+
+import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Provides helpers and listeners for appops.
+ */
+public class AppOpsHelper {
+
+ /**
+ * Listener for current user changes.
+ */
+ public interface LocationAppOpListener {
+
+ /**
+ * Called when something has changed about a location appop for the given package.
+ */
+ void onAppOpsChanged(String packageName);
+ }
+
+ private final Context mContext;
+ private final CopyOnWriteArrayList<LocationAppOpListener> mListeners;
+
+ @GuardedBy("this")
+ @Nullable
+ private AppOpsManager mAppOps;
+
+ public AppOpsHelper(Context context) {
+ mContext = context;
+ mListeners = new CopyOnWriteArrayList<>();
+ }
+
+ /** Called when system is ready. */
+ public synchronized void onSystemReady() {
+ if (mAppOps != null) {
+ return;
+ }
+
+ mAppOps = Objects.requireNonNull(mContext.getSystemService(AppOpsManager.class));
+ mAppOps.startWatchingMode(
+ AppOpsManager.OP_COARSE_LOCATION,
+ null,
+ AppOpsManager.WATCH_FOREGROUND_CHANGES,
+ new AppOpsManager.OnOpChangedInternalListener() {
+ public void onOpChanged(int op, String packageName) {
+ // invoked on ui thread, move to fg thread so ui thread isn't blocked
+ FgThread.getHandler().sendMessage(
+ PooledLambda.obtainMessage(AppOpsHelper::onAppOpChanged,
+ AppOpsHelper.this, packageName));
+ }
+ });
+ }
+
+ private void onAppOpChanged(String packageName) {
+ if (D) {
+ Log.v(TAG, "location appop changed for " + packageName);
+ }
+
+ for (LocationAppOpListener listener : mListeners) {
+ listener.onAppOpsChanged(packageName);
+ }
+ }
+
+ /**
+ * Adds a listener for app ops events. Callbacks occur on an unspecified thread.
+ */
+ public void addListener(LocationAppOpListener listener) {
+ mListeners.add(listener);
+ }
+
+ /**
+ * Removes a listener for app ops events.
+ */
+ public void removeListener(LocationAppOpListener listener) {
+ mListeners.remove(listener);
+ }
+
+ /**
+ * Checks if the given identity may have locations delivered without noting that a location is
+ * being delivered. This is a looser guarantee than {@link #noteLocationAccess(CallerIdentity)},
+ * and this function does not validate package arguments and so should not be used with
+ * unvalidated arguments or before actually delivering locations.
+ *
+ * @see AppOpsManager#checkOpNoThrow(int, int, String)
+ */
+ public boolean checkLocationAccess(CallerIdentity callerIdentity) {
+ synchronized (this) {
+ Preconditions.checkState(mAppOps != null);
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ return mAppOps.checkOpNoThrow(
+ CallerIdentity.asAppOp(callerIdentity.permissionLevel),
+ callerIdentity.uid,
+ callerIdentity.packageName) == AppOpsManager.MODE_ALLOWED;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Notes location access to the given identity, ie, location delivery. This method should be
+ * called right before a location is delivered, and if it returns false, the location should not
+ * be delivered.
+ */
+ public boolean noteLocationAccess(CallerIdentity identity) {
+ return noteOpNoThrow(CallerIdentity.asAppOp(identity.permissionLevel), identity);
+ }
+
+ /**
+ * Notifies app ops that the given identity is using location at normal/low power levels. If
+ * this function returns false, do not later call
+ * {@link #stopLocationMonitoring(CallerIdentity)}.
+ */
+ public boolean startLocationMonitoring(CallerIdentity identity) {
+ return startLocationMonitoring(OP_MONITOR_LOCATION, identity);
+ }
+
+ /**
+ * Notifies app ops that the given identity is no longer using location at normal/low power
+ * levels.
+ */
+ public void stopLocationMonitoring(CallerIdentity identity) {
+ stopLocationMonitoring(OP_MONITOR_LOCATION, identity);
+ }
+
+ /**
+ * Notifies app ops that the given identity is using location at high levels. If this function
+ * returns false, do not later call {@link #stopLocationMonitoring(CallerIdentity)}.
+ */
+ public boolean startHighPowerLocationMonitoring(CallerIdentity identity) {
+ return startLocationMonitoring(OP_MONITOR_HIGH_POWER_LOCATION, identity);
+ }
+
+ /**
+ * Notifies app ops that the given identity is no longer using location at high power levels.
+ */
+ public void stopHighPowerLocationMonitoring(CallerIdentity identity) {
+ stopLocationMonitoring(OP_MONITOR_HIGH_POWER_LOCATION, identity);
+ }
+
+ /**
+ * Notes access to any mock location APIs. If this call returns false, access to the APIs should
+ * silently fail.
+ */
+ public boolean noteMockLocationAccess(CallerIdentity callerIdentity) {
+ synchronized (this) {
+ Preconditions.checkState(mAppOps != null);
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ // note that this is not the no throw version of noteOp, this call may throw exceptions
+ return mAppOps.noteOp(
+ AppOpsManager.OP_MOCK_LOCATION,
+ callerIdentity.uid,
+ callerIdentity.packageName,
+ callerIdentity.featureId,
+ null) == AppOpsManager.MODE_ALLOWED;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private boolean startLocationMonitoring(int appOp, CallerIdentity callerIdentity) {
+ synchronized (this) {
+ Preconditions.checkState(mAppOps != null);
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ return mAppOps.startOpNoThrow(
+ appOp,
+ callerIdentity.uid,
+ callerIdentity.packageName,
+ false,
+ callerIdentity.featureId,
+ null) == AppOpsManager.MODE_ALLOWED;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private void stopLocationMonitoring(int appOp, CallerIdentity callerIdentity) {
+ synchronized (this) {
+ Preconditions.checkState(mAppOps != null);
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mAppOps.finishOp(
+ appOp,
+ callerIdentity.uid,
+ callerIdentity.packageName,
+ callerIdentity.featureId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private boolean noteOpNoThrow(int appOp, CallerIdentity callerIdentity) {
+ synchronized (this) {
+ Preconditions.checkState(mAppOps != null);
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ return mAppOps.noteOpNoThrow(
+ appOp,
+ callerIdentity.uid,
+ callerIdentity.packageName,
+ callerIdentity.featureId,
+ null) == AppOpsManager.MODE_ALLOWED;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/location/CallerIdentity.java b/services/core/java/com/android/server/location/CallerIdentity.java
index 75ba5b8..b84fd13 100644
--- a/services/core/java/com/android/server/location/CallerIdentity.java
+++ b/services/core/java/com/android/server/location/CallerIdentity.java
@@ -16,25 +16,211 @@
package com.android.server.location;
-import android.annotation.NonNull;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.Binder;
+import android.os.UserHandle;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
/**
* Represents the calling process's uid, pid, and package name.
*/
-public class CallerIdentity {
- public final int mUid;
- public final int mPid;
- public final String mPackageName;
- public final @Nullable String mFeatureId;
- public final @NonNull String mListenerIdentifier;
+public final class CallerIdentity {
- public CallerIdentity(int uid, int pid, String packageName, @Nullable String featureId,
- @NonNull String listenerIdentifier) {
- mUid = uid;
- mPid = pid;
- mPackageName = packageName;
- mFeatureId = featureId;
- mListenerIdentifier = listenerIdentifier;
+ public static final int PERMISSION_NONE = 0;
+ public static final int PERMISSION_COARSE = 1;
+ public static final int PERMISSION_FINE = 2;
+
+ @IntDef({PERMISSION_NONE, PERMISSION_COARSE, PERMISSION_FINE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PermissionLevel {}
+
+ /**
+ * Converts the given permission level to the corresponding permission.
+ */
+ public static String asPermission(@PermissionLevel int permissionLevel) {
+ switch (permissionLevel) {
+ case PERMISSION_COARSE:
+ return ACCESS_COARSE_LOCATION;
+ case PERMISSION_FINE:
+ return ACCESS_FINE_LOCATION;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Converts the given permission level to the corresponding appop.
+ */
+ public static int asAppOp(@PermissionLevel int permissionLevel) {
+ switch (permissionLevel) {
+ case PERMISSION_COARSE:
+ return AppOpsManager.OP_COARSE_LOCATION;
+ case PERMISSION_FINE:
+ return AppOpsManager.OP_FINE_LOCATION;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Creates a CallerIdentity from the current binder identity, using the given package and
+ * feature id. The package will be checked to enforce it belongs to the calling uid, and a
+ * security exception will be thrown if it is invalid.
+ */
+ public static CallerIdentity fromBinder(Context context, String packageName,
+ @Nullable String featureId) {
+ int uid = Binder.getCallingUid();
+ if (!ArrayUtils.contains(context.getPackageManager().getPackagesForUid(uid), packageName)) {
+ throw new SecurityException("invalid package \"" + packageName + "\" for uid " + uid);
+ }
+
+ return fromBinderUnsafe(context, packageName, featureId);
+ }
+
+ /**
+ * Creates a CallerIdentity from the current binder identity, using the given package and
+ * feature id. The package will not be checked to enforce that it belongs to the calling uid -
+ * this method should only be used if the package will be validated by some other means, such as
+ * an appops call.
+ */
+ public static CallerIdentity fromBinderUnsafe(Context context, String packageName,
+ @Nullable String featureId) {
+ return new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(),
+ UserHandle.getCallingUserId(), packageName, featureId,
+ getBinderPermissionLevel(context));
+ }
+
+ /**
+ * Throws a security exception if the caller does not hold a location permission.
+ */
+ public static void enforceCallingOrSelfLocationPermission(Context context) {
+ enforceLocationPermission(Binder.getCallingUid(), getBinderPermissionLevel(context));
+ }
+
+ /**
+ * Returns false if the caller does not hold a location permission, true otherwise.
+ */
+ public static boolean checkCallingOrSelfLocationPermission(Context context) {
+ return checkLocationPermission(getBinderPermissionLevel(context));
+ }
+
+ private static void enforceLocationPermission(int uid, @PermissionLevel int permissionLevel) {
+ if (checkLocationPermission(permissionLevel)) {
+ return;
+ }
+
+ throw new SecurityException("uid " + uid + " does not have " + ACCESS_COARSE_LOCATION
+ + " or " + ACCESS_FINE_LOCATION + ".");
+ }
+
+ private static boolean checkLocationPermission(@PermissionLevel int permissionLevel) {
+ return permissionLevel >= PERMISSION_COARSE;
+ }
+
+ private static @PermissionLevel int getBinderPermissionLevel(Context context) {
+ if (context.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) == PERMISSION_GRANTED) {
+ return PERMISSION_FINE;
+ }
+ if (context.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED) {
+ return PERMISSION_COARSE;
+ }
+
+ return PERMISSION_NONE;
+ }
+
+ /** The calling UID. */
+ public final int uid;
+
+ /** The calling PID. */
+ public final int pid;
+
+ /** The calling user. */
+ public final int userId;
+
+ /** The calling package name. */
+ public final String packageName;
+
+ /** The calling feature id. */
+ public final @Nullable String featureId;
+
+ /**
+ * The calling location permission level. This field should only be used for validating
+ * permissions for API access. It should not be used for validating permissions for location
+ * access - that must be done through appops.
+ */
+ public final @PermissionLevel int permissionLevel;
+
+ @VisibleForTesting
+ public CallerIdentity(int uid, int pid, int userId, String packageName,
+ @Nullable String featureId, @PermissionLevel int permissionLevel) {
+ this.uid = uid;
+ this.pid = pid;
+ this.userId = userId;
+ this.packageName = Objects.requireNonNull(packageName);
+ this.featureId = featureId;
+ this.permissionLevel = Preconditions.checkArgumentInRange(permissionLevel, PERMISSION_NONE,
+ PERMISSION_FINE, "permissionLevel");
+ }
+
+ /**
+ * Throws a security exception if the CallerIdentity does not hold a location permission.
+ */
+ public void enforceLocationPermission() {
+ enforceLocationPermission(uid, permissionLevel);
+ }
+
+ @Override
+ public String toString() {
+ int length = 10 + packageName.length();
+ if (featureId != null) {
+ length += featureId.length();
+ }
+
+ StringBuilder builder = new StringBuilder(length);
+ builder.append(pid).append("/").append(packageName);
+ if (featureId != null) {
+ builder.append("[");
+ if (featureId.startsWith(packageName)) {
+ builder.append(featureId.substring(packageName.length()));
+ } else {
+ builder.append(featureId);
+ }
+ builder.append("]");
+ }
+ return builder.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof CallerIdentity)) {
+ return false;
+ }
+ CallerIdentity that = (CallerIdentity) o;
+ return uid == that.uid
+ && pid == that.pid
+ && packageName.equals(that.packageName)
+ && Objects.equals(featureId, that.featureId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(uid, pid, packageName, featureId);
}
}
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index 4e9c067..195b059 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -16,9 +16,6 @@
package com.android.server.location;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.Context;
@@ -38,7 +35,6 @@
import android.util.Slog;
import com.android.server.FgThread;
-import com.android.server.LocationManagerService;
import com.android.server.PendingIntentUtils;
import java.io.PrintWriter;
@@ -125,16 +121,10 @@
}
public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
- int allowedResolutionLevel, int uid, String packageName, @Nullable String featureId,
- @NonNull String listenerIdentifier) {
- if (D) {
- Slog.d(TAG, "addFence: request=" + request + ", geofence=" + geofence
- + ", intent=" + intent + ", uid=" + uid + ", packageName=" + packageName);
- }
-
+ CallerIdentity identity) {
GeofenceState state = new GeofenceState(geofence,
request.getExpirationRealtimeMs(SystemClock.elapsedRealtime()),
- allowedResolutionLevel, uid, packageName, featureId, listenerIdentifier, intent);
+ identity, intent);
synchronized (mLock) {
// first make sure it doesn't already exist
for (int i = mFences.size() - 1; i >= 0; i--) {
@@ -182,26 +172,14 @@
}
synchronized (mLock) {
- Iterator<GeofenceState> iter = mFences.iterator();
- while (iter.hasNext()) {
- GeofenceState state = iter.next();
- if (state.mPackageName.equals(packageName)) {
- iter.remove();
- }
- }
+ mFences.removeIf(state -> state.mIdentity.packageName.equals(packageName));
scheduleUpdateFencesLocked();
}
}
private void removeExpiredFencesLocked() {
long time = SystemClock.elapsedRealtime();
- Iterator<GeofenceState> iter = mFences.iterator();
- while (iter.hasNext()) {
- GeofenceState state = iter.next();
- if (state.mExpireAt < time) {
- iter.remove();
- }
- }
+ mFences.removeIf(state -> state.mExpireAt < time);
}
private void scheduleUpdateFencesLocked() {
@@ -266,24 +244,17 @@
double minFenceDistance = Double.MAX_VALUE;
boolean needUpdates = false;
for (GeofenceState state : mFences) {
- if (mSettingsStore.isLocationPackageBlacklisted(ActivityManager.getCurrentUser(),
- state.mPackageName)) {
- if (D) {
- Slog.d(TAG, "skipping geofence processing for blacklisted app: "
- + state.mPackageName);
- }
+ CallerIdentity identity = state.mIdentity;
+ if (mSettingsStore.isLocationPackageBlacklisted(identity.userId,
+ identity.packageName)) {
continue;
}
- int op = LocationManagerService.resolutionLevelToOp(state.mAllowedResolutionLevel);
+ int op = CallerIdentity.asAppOp(identity.permissionLevel);
if (op >= 0) {
- if (mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, state.mUid,
- state.mPackageName, state.mFeatureId, state.mListenerIdentifier)
+ if (mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, identity.uid,
+ identity.packageName, identity.featureId, null)
!= AppOpsManager.MODE_ALLOWED) {
- if (D) {
- Slog.d(TAG, "skipping geofence processing for no op app: "
- + state.mPackageName);
- }
continue;
}
}
@@ -429,7 +400,7 @@
public void dump(PrintWriter pw) {
for (GeofenceState state : mFences) {
- pw.println(state.mPackageName + " " + state.mFence);
+ pw.println(state.mIdentity + " " + state.mFence);
}
}
diff --git a/services/core/java/com/android/server/location/GeofenceState.java b/services/core/java/com/android/server/location/GeofenceState.java
index a91a1dc..13318bf 100644
--- a/services/core/java/com/android/server/location/GeofenceState.java
+++ b/services/core/java/com/android/server/location/GeofenceState.java
@@ -17,8 +17,6 @@
package com.android.server.location;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.PendingIntent;
import android.location.Geofence;
import android.location.Location;
@@ -37,29 +35,20 @@
public final Geofence mFence;
private final Location mLocation;
public final long mExpireAt;
- public final int mAllowedResolutionLevel;
- public final int mUid;
- public final String mPackageName;
- public final @Nullable String mFeatureId;
- public final @NonNull String mListenerIdentifier;
+ public final CallerIdentity mIdentity;
public final PendingIntent mIntent;
int mState; // current state
double mDistanceToCenter; // current distance to center of fence
- public GeofenceState(Geofence fence, long expireAt, int allowedResolutionLevel, int uid,
- String packageName, @Nullable String featureId, @NonNull String listenerIdentifier,
+ public GeofenceState(Geofence fence, long expireAt, CallerIdentity identity,
PendingIntent intent) {
mState = STATE_UNKNOWN;
mDistanceToCenter = Double.MAX_VALUE;
mFence = fence;
mExpireAt = expireAt;
- mAllowedResolutionLevel = allowedResolutionLevel;
- mUid = uid;
- mPackageName = packageName;
- mFeatureId = featureId;
- mListenerIdentifier = listenerIdentifier;
+ mIdentity = identity;
mIntent = intent;
mLocation = new Location("");
diff --git a/services/core/java/com/android/server/location/LocationPermissionUtil.java b/services/core/java/com/android/server/location/LocationPermissionUtil.java
index 4465f31..80b93b5 100644
--- a/services/core/java/com/android/server/location/LocationPermissionUtil.java
+++ b/services/core/java/com/android/server/location/LocationPermissionUtil.java
@@ -49,13 +49,13 @@
private static boolean hasPermissionLocationHardware(Context context,
CallerIdentity callerIdentity) {
return context.checkPermission(android.Manifest.permission.LOCATION_HARDWARE,
- callerIdentity.mPid, callerIdentity.mUid) == PackageManager.PERMISSION_GRANTED;
+ callerIdentity.pid, callerIdentity.uid) == PackageManager.PERMISSION_GRANTED;
}
private static boolean hasPermissionUpdateAppOpsStats(Context context,
CallerIdentity callerIdentity) {
return context.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
- callerIdentity.mPid, callerIdentity.mUid) == PackageManager.PERMISSION_GRANTED;
+ callerIdentity.pid, callerIdentity.uid) == PackageManager.PERMISSION_GRANTED;
}
private LocationPermissionUtil() {}
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index f665289..9c908df 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -179,13 +179,12 @@
if (LocationPermissionUtil.doesCallerReportToAppOps(context, callerIdentity)) {
// The caller is identified as a location provider that will report location
// access to AppOps. Skip noteOp but do checkOp to check for location permission.
- return mAppOps.checkOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.mUid,
- callerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED;
+ return mAppOps.checkOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.uid,
+ callerIdentity.packageName) == AppOpsManager.MODE_ALLOWED;
}
- return mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.mUid,
- callerIdentity.mPackageName, callerIdentity.mFeatureId,
- "Location sent to " + callerIdentity.mListenerIdentifier)
+ return mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.uid,
+ callerIdentity.packageName, callerIdentity.featureId, null)
== AppOpsManager.MODE_ALLOWED;
}
diff --git a/services/core/java/com/android/server/location/SettingsHelper.java b/services/core/java/com/android/server/location/SettingsHelper.java
index 5fe21bd..7ab258c 100644
--- a/services/core/java/com/android/server/location/SettingsHelper.java
+++ b/services/core/java/com/android/server/location/SettingsHelper.java
@@ -22,7 +22,6 @@
import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST;
import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS;
import static android.provider.Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST;
-import static android.provider.Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS;
import static android.provider.Settings.Secure.LOCATION_COARSE_ACCURACY_M;
import static android.provider.Settings.Secure.LOCATION_MODE;
import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
@@ -92,7 +91,6 @@
private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
private static final long DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS =
30 * 60 * 1000;
- private static final long DEFAULT_MAX_LAST_LOCATION_AGE_MS = 20 * 60 * 1000;
private static final float DEFAULT_COARSE_LOCATION_ACCURACY_M = 2000.0f;
private final Context mContext;
@@ -285,21 +283,6 @@
}
/**
- * Retrieve maximum age of the last location.
- */
- public long getMaxLastLocationAgeMs() {
- long identity = Binder.clearCallingIdentity();
- try {
- return Settings.Global.getLong(
- mContext.getContentResolver(),
- LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
- DEFAULT_MAX_LAST_LOCATION_AGE_MS);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- /**
* Retrieve the accuracy for coarsening location, ie, the grid size used for snap-to-grid
* coarsening.
*/
diff --git a/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java b/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java
index d839095..4ee1100 100644
--- a/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java
@@ -112,7 +112,7 @@
foreach((IGnssAntennaInfoListener listener, CallerIdentity callerIdentity) -> {
if (!hasPermission(mContext, callerIdentity)) {
logPermissionDisabledEventNotReported(
- TAG, callerIdentity.mPackageName, "GNSS antenna info");
+ TAG, callerIdentity.packageName, "GNSS antenna info");
return;
}
listener.onGnssAntennaInfoReceived(gnssAntennaInfos);
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 9e64e3a..711f45c 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -16,15 +16,11 @@
package com.android.server.location.gnss;
-import static android.app.AppOpsManager.OP_FINE_LOCATION;
import static android.location.LocationManager.GPS_PROVIDER;
import android.Manifest;
-import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.AppOpsManager;
import android.content.Context;
-import android.location.GnssCapabilities;
import android.location.GnssMeasurementCorrections;
import android.location.GnssRequest;
import android.location.IBatchedLocationCallback;
@@ -41,7 +37,6 @@
import android.os.IInterface;
import android.os.Process;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.stats.location.LocationStatsEnums;
import android.util.ArrayMap;
import android.util.Log;
@@ -54,6 +49,7 @@
import com.android.server.LocationManagerServiceUtils.LinkedListener;
import com.android.server.LocationManagerServiceUtils.LinkedListenerBase;
import com.android.server.location.AppForegroundHelper;
+import com.android.server.location.AppOpsHelper;
import com.android.server.location.CallerIdentity;
import com.android.server.location.LocationUsageLogger;
import com.android.server.location.RemoteListenerHelper;
@@ -76,6 +72,7 @@
}
private final Context mContext;
+ private final AppOpsHelper mAppOpsHelper;
private final SettingsHelper mSettingsHelper;
private final AppForegroundHelper mAppForegroundHelper;
private final LocationUsageLogger mLocationUsageLogger;
@@ -112,8 +109,6 @@
@GuardedBy("this")
@Nullable private LocationManagerInternal mLocationManagerInternal;
- @GuardedBy("this")
- @Nullable private AppOpsManager mAppOpsManager;
private final Object mGnssBatchingLock = new Object();
@@ -127,19 +122,21 @@
@GuardedBy("mGnssBatchingLock")
private boolean mGnssBatchingInProgress = false;
- public GnssManagerService(Context context, SettingsHelper settingsHelper,
- AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger) {
- this(context, settingsHelper, appForegroundHelper, locationUsageLogger, null);
+ public GnssManagerService(Context context, AppOpsHelper appOpsHelper,
+ SettingsHelper settingsHelper, AppForegroundHelper appForegroundHelper,
+ LocationUsageLogger locationUsageLogger) {
+ this(context, appOpsHelper, settingsHelper, appForegroundHelper, locationUsageLogger, null);
}
// Can use this constructor to inject GnssLocationProvider for testing
@VisibleForTesting
- GnssManagerService(Context context, SettingsHelper settingsHelper,
+ GnssManagerService(Context context, AppOpsHelper appOpsHelper, SettingsHelper settingsHelper,
AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger,
GnssLocationProvider gnssLocationProvider) {
Preconditions.checkState(isGnssSupported());
mContext = context;
+ mAppOpsHelper = appOpsHelper;
mSettingsHelper = settingsHelper;
mAppForegroundHelper = appForegroundHelper;
mLocationUsageLogger = locationUsageLogger;
@@ -169,11 +166,11 @@
return;
}
+ mAppOpsHelper.onSystemReady();
mSettingsHelper.onSystemReady();
mAppForegroundHelper.onSystemReady();
mLocationManagerInternal = LocalServices.getService(LocationManagerInternal.class);
- mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mAppForegroundHelper.addListener(this::onAppForegroundChanged);
}
@@ -207,11 +204,7 @@
* Get GNSS hardware capabilities. The capabilities returned are a bitfield as described in
* {@link android.location.GnssCapabilities}.
*/
- public long getGnssCapabilities(String packageName) {
- if (!checkLocationAppOp(packageName)) {
- return GnssCapabilities.INVALID_CAPABILITIES;
- }
-
+ public long getGnssCapabilities() {
return mGnssCapabilitiesProvider.getGnssCapabilities();
}
@@ -222,10 +215,6 @@
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
- return 0;
- }
-
synchronized (mGnssBatchingLock) {
return mGnssBatchingProvider.getBatchSize();
}
@@ -235,11 +224,13 @@
* Starts GNSS batch collection. GNSS positions are collected in a batch before being delivered
* as a collection.
*/
- public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
+ public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName,
+ String featureId) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ if (!mAppOpsHelper.checkLocationAccess(identity)) {
return false;
}
@@ -259,25 +250,19 @@
* Adds a GNSS batching callback for delivering GNSS location batch results.
*/
public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
- @Nullable String featureId, @NonNull String listenerIdentity) {
+ @Nullable String featureId) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
- return false;
- }
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
- CallerIdentity callerIdentity =
- new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName,
- featureId, listenerIdentity);
synchronized (mGnssBatchingLock) {
mGnssBatchingCallback = callback;
mGnssBatchingDeathCallback =
new LinkedListener<>(
/* request= */ null,
callback,
- "BatchedLocationCallback",
- callerIdentity,
+ identity,
(IBatchedLocationCallback listener) -> {
stopGnssBatch();
removeGnssBatchingCallback();
@@ -297,10 +282,6 @@
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
- return;
- }
-
synchronized (mGnssBatchingLock) {
mGnssBatchingProvider.flush();
}
@@ -378,7 +359,7 @@
LinkedListener<TRequest, TListener> linkedListener = entry.getValue();
CallerIdentity callerIdentity = linkedListener.getCallerIdentity();
TRequest request = linkedListener.getRequest();
- if (callerIdentity.mUid != uid) {
+ if (callerIdentity.uid != uid) {
continue;
}
@@ -396,21 +377,19 @@
TListener listener,
String packageName,
@Nullable String featureId,
- @NonNull String listenerIdentifier,
RemoteListenerHelper<TRequest, TListener> gnssDataProvider,
ArrayMap<IBinder,
LinkedListener<TRequest, TListener>> gnssDataListeners,
Consumer<TListener> binderDeathCallback) {
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
+ CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+ if (!mAppOpsHelper.checkLocationAccess(identity)) {
return false;
}
- CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
- Binder.getCallingPid(), packageName, featureId, listenerIdentifier);
LinkedListener<TRequest, TListener> linkedListener = new LinkedListener<>(request, listener,
- listenerIdentifier, callerIdentity, binderDeathCallback);
+ identity, binderDeathCallback);
IBinder binder = listener.asBinder();
if (!linkedListener.linkToListenerDeathNotificationLocked(binder)) {
return false;
@@ -429,11 +408,11 @@
/* hasListener= */ true,
/* hasIntent= */ false,
/* geofence= */ null,
- mAppForegroundHelper.getImportance(callerIdentity.mUid));
+ mAppForegroundHelper.getImportance(identity.uid));
}
- if (mAppForegroundHelper.isAppForeground(callerIdentity.mUid)
- || isThrottlingExempt(callerIdentity)) {
- gnssDataProvider.addListener(request, listener, callerIdentity);
+ if (mAppForegroundHelper.isAppForeground(identity.uid)
+ || isThrottlingExempt(identity)) {
+ gnssDataProvider.addListener(request, listener, identity);
}
return true;
}
@@ -463,7 +442,7 @@
gnssDataProvider == mGnssMeasurementsProvider
? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER
: LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK,
- linkedListener.getCallerIdentity().mPackageName,
+ linkedListener.getCallerIdentity().packageName,
/* LocationRequest= */ null,
/* hasListener= */ true,
/* hasIntent= */ false,
@@ -485,7 +464,6 @@
listener,
packageName,
featureId,
- "Gnss status",
mGnssStatusProvider,
mGnssStatusListeners,
this::unregisterGnssStatusCallback);
@@ -506,8 +484,7 @@
*/
public boolean addGnssMeasurementsListener(@Nullable GnssRequest request,
IGnssMeasurementsListener listener, String packageName,
- @Nullable String featureId,
- @NonNull String listenerIdentifier) {
+ @Nullable String featureId) {
if (request != null && request.isFullTracking()) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.LOCATION_HARDWARE,
null);
@@ -518,7 +495,6 @@
listener,
packageName,
featureId,
- listenerIdentifier,
mGnssMeasurementsProvider,
mGnssMeasurementsListeners,
this::removeGnssMeasurementsListener);
@@ -533,10 +509,6 @@
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (!checkLocationAppOp(packageName)) {
- return;
- }
-
mGnssMeasurementCorrectionsProvider.injectGnssMeasurementCorrections(
measurementCorrections);
}
@@ -556,18 +528,16 @@
*
* @param listener called when GNSS antenna info is received
* @param packageName name of requesting package
- * @return true if listener is successfully added, false otherwise
*/
public boolean addGnssAntennaInfoListener(
IGnssAntennaInfoListener listener, String packageName,
- @Nullable String featureId, @NonNull String listenerIdentifier) {
+ @Nullable String featureId) {
synchronized (mGnssAntennaInfoListeners) {
return addGnssDataListenerLocked(
/* request= */ null,
listener,
packageName,
featureId,
- listenerIdentifier,
mGnssAntennaInfoProvider,
mGnssAntennaInfoListeners,
this::removeGnssAntennaInfoListener);
@@ -591,14 +561,13 @@
*/
public boolean addGnssNavigationMessageListener(
IGnssNavigationMessageListener listener, String packageName,
- @Nullable String featureId, @NonNull String listenerIdentifier) {
+ @Nullable String featureId) {
synchronized (mGnssNavigationMessageListeners) {
return addGnssDataListenerLocked(
/* request= */ null,
listener,
packageName,
featureId,
- listenerIdentifier,
mGnssNavigationMessageProvider,
mGnssNavigationMessageListeners,
this::removeGnssNavigationMessageListener);
@@ -641,7 +610,7 @@
return;
}
- int userId = UserHandle.getUserId(gnssBatchingDeathCallback.getCallerIdentity().mUid);
+ int userId = gnssBatchingDeathCallback.getCallerIdentity().userId;
if (!mLocationManagerInternal.isProviderEnabledForUser(GPS_PROVIDER, userId)) {
Log.w(TAG, "reportLocationBatch() called without user permission");
return;
@@ -655,27 +624,19 @@
}
private boolean isThrottlingExempt(CallerIdentity callerIdentity) {
- if (callerIdentity.mUid == Process.SYSTEM_UID) {
+ if (callerIdentity.uid == Process.SYSTEM_UID) {
return true;
}
if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
- callerIdentity.mPackageName)) {
+ callerIdentity.packageName)) {
return true;
}
synchronized (this) {
Preconditions.checkState(mLocationManagerInternal != null);
}
- return mLocationManagerInternal.isProviderPackage(callerIdentity.mPackageName);
- }
-
- private boolean checkLocationAppOp(String packageName) {
- synchronized (this) {
- Preconditions.checkState(mAppOpsManager != null);
- }
- return mAppOpsManager.checkOp(OP_FINE_LOCATION, Binder.getCallingUid(), packageName)
- == AppOpsManager.MODE_ALLOWED;
+ return mLocationManagerInternal.isProviderPackage(callerIdentity.packageName);
}
/**
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index 76c3ad0..b426701 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -117,7 +117,7 @@
foreach((IGnssMeasurementsListener listener, CallerIdentity callerIdentity) -> {
if (!hasPermission(mContext, callerIdentity)) {
logPermissionDisabledEventNotReported(
- TAG, callerIdentity.mPackageName, "GNSS measurements");
+ TAG, callerIdentity.packageName, "GNSS measurements");
return;
}
listener.onGnssMeasurementsReceived(event);
diff --git a/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java
index d2ecdee..3417e6e 100644
--- a/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java
@@ -79,7 +79,7 @@
final float[] basebandCn0s) {
foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> {
if (!hasPermission(mContext, callerIdentity)) {
- logPermissionDisabledEventNotReported(TAG, callerIdentity.mPackageName,
+ logPermissionDisabledEventNotReported(TAG, callerIdentity.packageName,
"GNSS status");
return;
}
@@ -91,7 +91,7 @@
public void onNmeaReceived(final long timestamp, final String nmea) {
foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> {
if (!hasPermission(mContext, callerIdentity)) {
- logPermissionDisabledEventNotReported(TAG, callerIdentity.mPackageName, "NMEA");
+ logPermissionDisabledEventNotReported(TAG, callerIdentity.packageName, "NMEA");
return;
}
listener.onNmeaReceived(timestamp, nmea);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 1b4ec8a..3574a64 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1016,9 +1016,14 @@
}
private void enforceFrpResolved() {
- if (mInjector.settingsSecureGetInt(mContext.getContentResolver(),
- Settings.Secure.SECURE_FRP_MODE, 0, UserHandle.USER_SYSTEM) == 1) {
- throw new SecurityException("Cannot change credential while FRP is not resolved yet");
+ final ContentResolver cr = mContext.getContentResolver();
+ final boolean inSetupWizard = mInjector.settingsSecureGetInt(cr,
+ Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_SYSTEM) == 0;
+ final boolean secureFrp = mInjector.settingsSecureGetInt(cr,
+ Settings.Secure.SECURE_FRP_MODE, 0, UserHandle.USER_SYSTEM) == 1;
+ if (inSetupWizard && secureFrp) {
+ throw new SecurityException("Cannot change credential in SUW while factory reset"
+ + " protection is not resolved yet");
}
}
@@ -2161,6 +2166,13 @@
}
}
+ private PasswordMetrics loadPasswordMetrics(AuthenticationToken auth, int userHandle) {
+ synchronized (mSpManager) {
+ return mSpManager.getPasswordMetrics(auth, getSyntheticPasswordHandleLocked(userHandle),
+ userHandle);
+ }
+ }
+
/**
* Call after {@link #setUserPasswordMetrics} so metrics are updated before
* reporting the password changed.
@@ -2611,7 +2623,8 @@
return auth;
}
- private long getSyntheticPasswordHandleLocked(int userId) {
+ @VisibleForTesting
+ long getSyntheticPasswordHandleLocked(int userId) {
return getLong(SYNTHETIC_PASSWORD_HANDLE_KEY,
SyntheticPasswordManager.DEFAULT_HANDLE, userId);
}
@@ -2706,13 +2719,8 @@
resetLockouts.add(new PendingResetLockout(userId, response.getPayload()));
}
- // TODO: Move setUserPasswordMetrics() inside onCredentialVerified(): this will require
- // LSS to store an encrypted version of the latest password metric for every user,
- // because user credential is not known when onCredentialVerified() is called during
- // a token-based unlock.
- setUserPasswordMetrics(userCredential, userId);
onCredentialVerified(authResult.authToken, challengeType, challenge, resetLockouts,
- userId);
+ PasswordMetrics.computeForCredential(userCredential), userId);
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
if (response.getTimeout() > 0) {
requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
@@ -2724,7 +2732,16 @@
private void onCredentialVerified(AuthenticationToken authToken,
@ChallengeType int challengeType, long challenge,
- @Nullable ArrayList<PendingResetLockout> resetLockouts, int userId) {
+ @Nullable ArrayList<PendingResetLockout> resetLockouts, PasswordMetrics metrics,
+ int userId) {
+
+ if (metrics != null) {
+ synchronized (this) {
+ mUserPasswordMetrics.put(userId, metrics);
+ }
+ } else {
+ Slog.wtf(TAG, "Null metrics after credential verification");
+ }
unlockKeystore(authToken.deriveKeyStorePassword(), userId);
@@ -3118,7 +3135,9 @@
// TODO: Reset biometrics lockout here. Ideally that should be self-contained inside
// onCredentialVerified(), which will require some refactoring on the current lockout
// reset logic.
- onCredentialVerified(authResult.authToken, CHALLENGE_NONE, 0, null, userId);
+
+ onCredentialVerified(authResult.authToken, CHALLENGE_NONE, 0, null,
+ loadPasswordMetrics(authResult.authToken, userId), userId);
return true;
}
@@ -3193,6 +3212,12 @@
mStrongAuth.dump(pw);
pw.println();
pw.decreaseIndent();
+
+ pw.println("RebootEscrow:");
+ pw.increaseIndent();
+ mRebootEscrowManager.dump(pw);
+ pw.println();
+ pw.decreaseIndent();
}
/**
@@ -3408,7 +3433,8 @@
SyntheticPasswordManager.AuthenticationToken
authToken = new SyntheticPasswordManager.AuthenticationToken(spVersion);
authToken.recreateDirectly(syntheticPassword);
- onCredentialVerified(authToken, CHALLENGE_NONE, 0, null, userId);
+ onCredentialVerified(authToken, CHALLENGE_NONE, 0, null,
+ loadPasswordMetrics(authToken, userId), userId);
}
}
}
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
index dabf886..8d4efed 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
@@ -18,6 +18,7 @@
import static android.os.UserHandle.USER_SYSTEM;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
@@ -25,6 +26,7 @@
import android.hardware.rebootescrow.IRebootEscrow;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;
@@ -32,11 +34,15 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.widget.RebootEscrowListener;
import java.io.IOException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
+import java.util.Locale;
import java.util.NoSuchElementException;
class RebootEscrowManager {
@@ -63,6 +69,11 @@
private static final int BOOT_COUNT_TOLERANCE = 5;
/**
+ * Logs events for later debugging in bugreports.
+ */
+ private final RebootEscrowEventLog mEventLog;
+
+ /**
* Used to track when the reboot escrow is wanted. Should stay true once escrow is requested
* unless clearRebootEscrow is called. This will allow all the active users to be unlocked
* after reboot.
@@ -135,6 +146,10 @@
public void reportMetric(boolean success) {
FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, success);
}
+
+ public RebootEscrowEventLog getEventLog() {
+ return new RebootEscrowEventLog();
+ }
}
RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage) {
@@ -148,6 +163,7 @@
mCallbacks = callbacks;
mStorage = storage;
mUserManager = injector.getUserManager();
+ mEventLog = injector.getEventLog();
}
void loadRebootEscrowDataIfAvailable() {
@@ -173,6 +189,8 @@
return;
}
+ mEventLog.addEntry(RebootEscrowEvent.FOUND_ESCROW_DATA);
+
boolean allUsersUnlocked = true;
for (UserInfo user : rebootEscrowUsers) {
allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey);
@@ -221,6 +239,7 @@
// Overwrite the existing key with the null key
rebootEscrow.storeKey(new byte[32]);
+ mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK);
return RebootEscrowKey.fromKeyBytes(escrowKeyBytes);
} catch (RemoteException e) {
Slog.w(TAG, "Could not retrieve escrow data");
@@ -242,6 +261,7 @@
mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(),
escrowData.getSyntheticPassword(), userId);
Slog.i(TAG, "Restored reboot escrow data for user " + userId);
+ mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_LSKF_FOR_USER, userId);
return true;
} catch (IOException e) {
Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e);
@@ -278,6 +298,7 @@
}
mStorage.writeRebootEscrow(userId, escrowData.getBlob());
+ mEventLog.addEntry(RebootEscrowEvent.STORED_LSKF_FOR_USER, userId);
setRebootEscrowReady(true);
}
@@ -322,6 +343,8 @@
for (UserInfo user : users) {
mStorage.removeRebootEscrow(user.id);
}
+
+ mEventLog.addEntry(RebootEscrowEvent.CLEARED_LSKF_REQUEST);
}
boolean armRebootEscrowIfNeeded() {
@@ -356,6 +379,7 @@
if (armedRebootEscrow) {
mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM);
+ mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS);
}
return armedRebootEscrow;
@@ -375,6 +399,7 @@
clearRebootEscrowIfNeeded();
mRebootEscrowWanted = true;
+ mEventLog.addEntry(RebootEscrowEvent.REQUESTED_LSKF);
return true;
}
@@ -390,4 +415,123 @@
void setRebootEscrowListener(RebootEscrowListener listener) {
mRebootEscrowListener = listener;
}
+
+ @VisibleForTesting
+ public static class RebootEscrowEvent {
+ static final int FOUND_ESCROW_DATA = 1;
+ static final int SET_ARMED_STATUS = 2;
+ static final int CLEARED_LSKF_REQUEST = 3;
+ static final int RETRIEVED_STORED_KEK = 4;
+ static final int REQUESTED_LSKF = 5;
+ static final int STORED_LSKF_FOR_USER = 6;
+ static final int RETRIEVED_LSKF_FOR_USER = 7;
+
+ final int mEventId;
+ final Integer mUserId;
+ final long mWallTime;
+ final long mTimestamp;
+
+ RebootEscrowEvent(int eventId) {
+ this(eventId, null);
+ }
+
+ RebootEscrowEvent(int eventId, Integer userId) {
+ mEventId = eventId;
+ mUserId = userId;
+ mTimestamp = SystemClock.uptimeMillis();
+ mWallTime = System.currentTimeMillis();
+ }
+
+ String getEventDescription() {
+ switch (mEventId) {
+ case FOUND_ESCROW_DATA:
+ return "Found escrow data";
+ case SET_ARMED_STATUS:
+ return "Set armed status";
+ case CLEARED_LSKF_REQUEST:
+ return "Cleared request for LSKF";
+ case RETRIEVED_STORED_KEK:
+ return "Retrieved stored KEK";
+ case REQUESTED_LSKF:
+ return "Requested LSKF";
+ case STORED_LSKF_FOR_USER:
+ return "Stored LSKF for user";
+ case RETRIEVED_LSKF_FOR_USER:
+ return "Retrieved LSKF for user";
+ default:
+ return "Unknown event ID " + mEventId;
+ }
+ }
+ }
+
+ @VisibleForTesting
+ public static class RebootEscrowEventLog {
+ private RebootEscrowEvent[] mEntries = new RebootEscrowEvent[16];
+ private int mNextIndex = 0;
+
+ void addEntry(int eventId) {
+ addEntryInternal(new RebootEscrowEvent(eventId));
+ }
+
+ void addEntry(int eventId, int userId) {
+ addEntryInternal(new RebootEscrowEvent(eventId, userId));
+ }
+
+ private void addEntryInternal(RebootEscrowEvent event) {
+ final int index = mNextIndex;
+ mEntries[index] = event;
+ mNextIndex = (mNextIndex + 1) % mEntries.length;
+ }
+
+ void dump(@NonNull IndentingPrintWriter pw) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US);
+
+ for (int i = 0; i < mEntries.length; ++i) {
+ RebootEscrowEvent event = mEntries[(i + mNextIndex) % mEntries.length];
+ if (event == null) {
+ continue;
+ }
+
+ pw.print("Event #");
+ pw.println(i);
+
+ pw.println(" time=" + sdf.format(new Date(event.mWallTime))
+ + " (timestamp=" + event.mTimestamp + ")");
+
+ pw.print(" event=");
+ pw.println(event.getEventDescription());
+
+ if (event.mUserId != null) {
+ pw.print(" user=");
+ pw.println(event.mUserId);
+ }
+ }
+ }
+ }
+
+ void dump(@NonNull IndentingPrintWriter pw) {
+ pw.print("mRebootEscrowWanted=");
+ pw.println(mRebootEscrowWanted);
+
+ pw.print("mRebootEscrowReady=");
+ pw.println(mRebootEscrowReady);
+
+ pw.print("mRebootEscrowListener=");
+ pw.println(mRebootEscrowListener);
+
+ boolean keySet;
+ synchronized (mKeyGenerationLock) {
+ keySet = mPendingRebootEscrowKey != null;
+ }
+
+ pw.print("mPendingRebootEscrowKey is ");
+ pw.println(keySet ? "set" : "not set");
+
+ pw.println();
+ pw.println("Event log:");
+ pw.increaseIndent();
+ mEventLog.dump(pw);
+ pw.println();
+ pw.decreaseIndent();
+ }
}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index ac49fa2..fc46345 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.admin.PasswordMetrics;
import android.content.Context;
import android.content.pm.UserInfo;
import android.hardware.weaver.V1_0.IWeaver;
@@ -97,6 +98,7 @@
private static final int SECDISCARDABLE_LENGTH = 16 * 1024;
private static final String PASSWORD_DATA_NAME = "pwd";
private static final String WEAVER_SLOT_NAME = "weaver";
+ private static final String PASSWORD_METRICS_NAME = "metrics";
public static final long DEFAULT_HANDLE = 0L;
private static final byte[] DEFAULT_PASSWORD = "default-password".getBytes();
@@ -132,6 +134,7 @@
private static final byte[] PERSONALISATION_WEAVER_PASSWORD = "weaver-pwd".getBytes();
private static final byte[] PERSONALISATION_WEAVER_KEY = "weaver-key".getBytes();
private static final byte[] PERSONALISATION_WEAVER_TOKEN = "weaver-token".getBytes();
+ private static final byte[] PERSONALIZATION_PASSWORD_METRICS = "password-metrics".getBytes();
private static final byte[] PERSONALISATION_CONTEXT =
"android-synthetic-password-personalization-context".getBytes();
@@ -212,6 +215,11 @@
return derivePassword(PERSONALIZATION_PASSWORD_HASH);
}
+ /** Derives key used to encrypt password metrics */
+ public byte[] deriveMetricsKey() {
+ return derivePassword(PERSONALIZATION_PASSWORD_METRICS);
+ }
+
/**
* Assign escrow data to this auth token. This is a prerequisite to call
* {@link AuthenticationToken#recreateFromEscrow}.
@@ -778,7 +786,7 @@
synchronizeFrpPassword(pwd, 0, userId);
}
saveState(PASSWORD_DATA_NAME, pwd.toBytes(), handle, userId);
-
+ savePasswordMetrics(credential, authToken, handle, userId);
createSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED, authToken,
applicationId, sid, userId);
return handle;
@@ -1061,6 +1069,12 @@
// Perform verifyChallenge to refresh auth tokens for GK if user password exists.
result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId);
+
+ // Upgrade case: store the metrics if the device did not have stored metrics before, should
+ // only happen once on old synthetic password blobs.
+ if (result.authToken != null && !hasPasswordMetrics(handle, userId)) {
+ savePasswordMetrics(credential, result.authToken, handle, userId);
+ }
return result;
}
@@ -1216,6 +1230,7 @@
destroySyntheticPassword(handle, userId);
destroyState(SECDISCARDABLE_NAME, handle, userId);
destroyState(PASSWORD_DATA_NAME, handle, userId);
+ destroyState(PASSWORD_METRICS_NAME, handle, userId);
}
private void destroySyntheticPassword(long handle, int userId) {
@@ -1258,6 +1273,34 @@
return loadState(SECDISCARDABLE_NAME, handle, userId);
}
+ /**
+ * Retrieves the saved password metrics associated with a SP handle. Only meaningful to be
+ * called on the handle of a password-based synthetic password. A valid AuthenticationToken for
+ * the target user is required in order to be able to decrypt the encrypted password metrics on
+ * disk.
+ */
+ public @Nullable PasswordMetrics getPasswordMetrics(AuthenticationToken authToken, long handle,
+ int userId) {
+ final byte[] encrypted = loadState(PASSWORD_METRICS_NAME, handle, userId);
+ if (encrypted == null) return null;
+ final byte[] decrypted = SyntheticPasswordCrypto.decrypt(authToken.deriveMetricsKey(),
+ /* personalization= */ new byte[0], encrypted);
+ if (decrypted == null) return null;
+ return VersionedPasswordMetrics.deserialize(decrypted).getMetrics();
+ }
+
+ private void savePasswordMetrics(LockscreenCredential credential, AuthenticationToken authToken,
+ long handle, int userId) {
+ final byte[] encrypted = SyntheticPasswordCrypto.encrypt(authToken.deriveMetricsKey(),
+ /* personalization= */ new byte[0],
+ new VersionedPasswordMetrics(credential).serialize());
+ saveState(PASSWORD_METRICS_NAME, encrypted, handle, userId);
+ }
+
+ private boolean hasPasswordMetrics(long handle, int userId) {
+ return hasState(PASSWORD_METRICS_NAME, handle, userId);
+ }
+
private boolean hasState(String stateName, long handle, int userId) {
return !ArrayUtils.isEmpty(loadState(stateName, handle, userId));
}
diff --git a/services/core/java/com/android/server/locksettings/VersionedPasswordMetrics.java b/services/core/java/com/android/server/locksettings/VersionedPasswordMetrics.java
new file mode 100644
index 0000000..b06e381
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/VersionedPasswordMetrics.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.locksettings;
+
+import android.app.admin.PasswordMetrics;
+
+import com.android.internal.widget.LockscreenCredential;
+
+import java.nio.ByteBuffer;
+
+/**
+ * A versioned and serializable wrapper around {@link PasswordMetrics},
+ * for long-term persistence on disk.
+ */
+public class VersionedPasswordMetrics {
+ private static final int VERSION_1 = 1;
+
+ private final PasswordMetrics mMetrics;
+ private final int mVersion;
+
+ private VersionedPasswordMetrics(int version, PasswordMetrics metrics) {
+ mMetrics = metrics;
+ mVersion = version;
+ }
+
+ public VersionedPasswordMetrics(LockscreenCredential credential) {
+ this(VERSION_1, PasswordMetrics.computeForCredential(credential));
+ }
+
+ public int getVersion() {
+ return mVersion;
+ }
+
+ public PasswordMetrics getMetrics() {
+ return mMetrics;
+ }
+
+ /** Serialize object to a byte array. */
+ public byte[] serialize() {
+ final ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES * 11);
+ buffer.putInt(mVersion);
+ buffer.putInt(mMetrics.credType);
+ buffer.putInt(mMetrics.length);
+ buffer.putInt(mMetrics.letters);
+ buffer.putInt(mMetrics.upperCase);
+ buffer.putInt(mMetrics.lowerCase);
+ buffer.putInt(mMetrics.numeric);
+ buffer.putInt(mMetrics.symbols);
+ buffer.putInt(mMetrics.nonLetter);
+ buffer.putInt(mMetrics.nonNumeric);
+ buffer.putInt(mMetrics.seqLength);
+ return buffer.array();
+ }
+
+ /** Deserialize byte array to an object */
+ public static VersionedPasswordMetrics deserialize(byte[] data) {
+ final ByteBuffer buffer = ByteBuffer.allocate(data.length);
+ buffer.put(data, 0, data.length);
+ buffer.flip();
+ final int version = buffer.getInt();
+ PasswordMetrics metrics = new PasswordMetrics(buffer.getInt(), buffer.getInt(),
+ buffer.getInt(), buffer.getInt(), buffer.getInt(), buffer.getInt(), buffer.getInt(),
+ buffer.getInt(), buffer.getInt(), buffer.getInt());
+ return new VersionedPasswordMetrics(version, metrics);
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 9bbbc3b..6aae62e 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -708,7 +708,7 @@
}
List<RoutingSessionInfo> sessionInfos = new ArrayList<>();
- for (MediaRoute2Provider provider : managerRecord.mUserRecord.mHandler.mMediaProviders) {
+ for (MediaRoute2Provider provider : managerRecord.mUserRecord.mHandler.mRouteProviders) {
sessionInfos.addAll(provider.getSessionInfos());
}
return sessionInfos;
@@ -1059,7 +1059,7 @@
//TODO: Make this thread-safe.
private final SystemMediaRoute2Provider mSystemProvider;
- private final ArrayList<MediaRoute2Provider> mMediaProviders =
+ private final ArrayList<MediaRoute2Provider> mRouteProviders =
new ArrayList<>();
private final List<MediaRoute2ProviderInfo> mLastProviderInfos = new ArrayList<>();
@@ -1074,7 +1074,7 @@
mServiceRef = new WeakReference<>(service);
mUserRecord = userRecord;
mSystemProvider = new SystemMediaRoute2Provider(service.mContext, this);
- mMediaProviders.add(mSystemProvider);
+ mRouteProviders.add(mSystemProvider);
mWatcher = new MediaRoute2ProviderWatcher(service.mContext, this,
this, mUserRecord.mUserId);
}
@@ -1097,13 +1097,13 @@
@Override
public void onAddProviderService(@NonNull MediaRoute2ProviderServiceProxy proxy) {
proxy.setCallback(this);
- mMediaProviders.add(proxy);
+ mRouteProviders.add(proxy);
proxy.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference);
}
@Override
public void onRemoveProviderService(@NonNull MediaRoute2ProviderServiceProxy proxy) {
- mMediaProviders.remove(proxy);
+ mRouteProviders.remove(proxy);
}
@Override
@@ -1148,10 +1148,10 @@
//TODO: notify session info updates
private void onProviderStateChangedOnHandler(@NonNull MediaRoute2Provider provider) {
- int providerIndex = getProviderInfoIndex(provider.getUniqueId());
+ int providerInfoIndex = getLastProviderInfoIndex(provider.getUniqueId());
MediaRoute2ProviderInfo providerInfo = provider.getProviderInfo();
MediaRoute2ProviderInfo prevInfo =
- (providerIndex < 0) ? null : mLastProviderInfos.get(providerIndex);
+ (providerInfoIndex < 0) ? null : mLastProviderInfos.get(providerInfoIndex);
if (Objects.equals(prevInfo, providerInfo)) return;
@@ -1171,7 +1171,7 @@
this, getRouters(), new ArrayList<>(removedRoutes)));
}
} else {
- mLastProviderInfos.set(providerIndex, providerInfo);
+ mLastProviderInfos.set(providerInfoIndex, providerInfo);
List<MediaRoute2Info> addedRoutes = new ArrayList<>();
List<MediaRoute2Info> removedRoutes = new ArrayList<>();
List<MediaRoute2Info> changedRoutes = new ArrayList<>();
@@ -1219,7 +1219,7 @@
}
}
- private int getProviderInfoIndex(@NonNull String providerId) {
+ private int getLastProviderInfoIndex(@NonNull String providerId) {
for (int i = 0; i < mLastProviderInfos.size(); i++) {
MediaRoute2ProviderInfo providerInfo = mLastProviderInfos.get(i);
if (TextUtils.equals(providerInfo.getUniqueId(), providerId)) {
@@ -1795,13 +1795,13 @@
new RouteDiscoveryPreference.Builder(discoveryPreferences)
.build();
}
- for (MediaRoute2Provider provider : mMediaProviders) {
+ for (MediaRoute2Provider provider : mRouteProviders) {
provider.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference);
}
}
private MediaRoute2Provider findProvider(@Nullable String providerId) {
- for (MediaRoute2Provider provider : mMediaProviders) {
+ for (MediaRoute2Provider provider : mRouteProviders) {
if (TextUtils.equals(provider.getUniqueId(), providerId)) {
return provider;
}
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index c7d14e0..5b16d68 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -54,6 +54,7 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
+ static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
static final String SYSTEM_SESSION_ID = "SYSTEM_SESSION";
private final AudioManager mAudioManager;
@@ -67,14 +68,17 @@
SystemMediaRoute2Provider.class.getName());
private String mSelectedRouteId;
+ // For apps without MODIFYING_AUDIO_ROUTING permission.
+ // This should be the currently selected route.
MediaRoute2Info mDefaultRoute;
+ MediaRoute2Info mDeviceRoute;
final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
@Override
public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
mHandler.post(() -> {
- updateDefaultRoute(newRoutes);
+ updateDeviceRoute(newRoutes);
notifyProviderState();
});
}
@@ -97,8 +101,9 @@
newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
} catch (RemoteException e) {
}
- updateDefaultRoute(newAudioRoutes);
+ updateDeviceRoute(newAudioRoutes);
+ // .getInstance returns null if there is no bt adapter available
mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> {
publishProviderState();
@@ -109,14 +114,15 @@
}
});
updateSessionInfosIfNeeded();
-
mContext.registerReceiver(new VolumeChangeReceiver(),
new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION));
- mHandler.post(() -> {
- mBtRouteProvider.start();
- notifyProviderState();
- });
+ if (mBtRouteProvider != null) {
+ mHandler.post(() -> {
+ mBtRouteProvider.start();
+ notifyProviderState();
+ });
+ }
}
@Override
@@ -150,10 +156,12 @@
@Override
public void transferToRoute(long requestId, String sessionId, String routeId) {
- if (TextUtils.equals(routeId, mDefaultRoute.getId())) {
- mBtRouteProvider.transferTo(null);
- } else {
- mBtRouteProvider.transferTo(routeId);
+ if (mBtRouteProvider != null) {
+ if (TextUtils.equals(routeId, mDeviceRoute.getId())) {
+ mBtRouteProvider.transferTo(null);
+ } else {
+ mBtRouteProvider.transferTo(routeId);
+ }
}
}
@@ -170,7 +178,11 @@
// Do nothing since we don't support grouping volume yet.
}
- private void updateDefaultRoute(AudioRoutesInfo newRoutes) {
+ public MediaRoute2Info getDefaultRoute() {
+ return mDefaultRoute;
+ }
+
+ private void updateDeviceRoute(AudioRoutesInfo newRoutes) {
int name = R.string.default_audio_route_name;
if (newRoutes != null) {
mCurAudioRoutesInfo.mainType = newRoutes.mainType;
@@ -185,8 +197,8 @@
name = com.android.internal.R.string.default_audio_route_name_usb;
}
}
- mDefaultRoute = new MediaRoute2Info.Builder(
- DEFAULT_ROUTE_ID, mContext.getResources().getText(name).toString())
+ mDeviceRoute = new MediaRoute2Info.Builder(
+ DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
.setVolumeHandling(mAudioManager.isVolumeFixed()
? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
: MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
@@ -203,7 +215,7 @@
private void updateProviderState() {
MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
- builder.addRoute(mDefaultRoute);
+ builder.addRoute(mDeviceRoute);
if (mBtRouteProvider != null) {
for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
builder.addRoute(route);
@@ -228,11 +240,12 @@
MediaRoute2Info selectedRoute = mBtRouteProvider.getSelectedRoute();
if (selectedRoute == null) {
- selectedRoute = mDefaultRoute;
+ selectedRoute = mDeviceRoute;
} else {
- builder.addTransferableRoute(mDefaultRoute.getId());
+ builder.addTransferableRoute(mDeviceRoute.getId());
}
mSelectedRouteId = selectedRoute.getId();
+ mDefaultRoute = new MediaRoute2Info.Builder(DEFAULT_ROUTE_ID, selectedRoute).build();
builder.addSelectedRoute(mSelectedRouteId);
for (MediaRoute2Info route : mBtRouteProvider.getTransferableRoutes()) {
@@ -282,11 +295,11 @@
AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);
if (newVolume != oldVolume) {
- if (TextUtils.equals(mDefaultRoute.getId(), mSelectedRouteId)) {
- mDefaultRoute = new MediaRoute2Info.Builder(mDefaultRoute)
+ if (TextUtils.equals(mDeviceRoute.getId(), mSelectedRouteId)) {
+ mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
.setVolume(newVolume)
.build();
- } else {
+ } else if (mBtRouteProvider != null) {
mBtRouteProvider.setSelectedRouteVolume(newVolume);
}
publishProviderState();
diff --git a/services/core/java/com/android/server/notification/BubbleExtractor.java b/services/core/java/com/android/server/notification/BubbleExtractor.java
index f2eb176..2fa80cd 100644
--- a/services/core/java/com/android/server/notification/BubbleExtractor.java
+++ b/services/core/java/com/android/server/notification/BubbleExtractor.java
@@ -76,7 +76,8 @@
record.setAllowBubble(appCanShowBubble);
}
}
- final boolean applyFlag = mBubbleChecker.isNotificationAppropriateToBubble(record);
+ final boolean applyFlag = mBubbleChecker.isNotificationAppropriateToBubble(record)
+ && !record.isFlagBubbleRemoved();
if (applyFlag) {
record.getNotification().flags |= FLAG_BUBBLE;
} else {
diff --git a/services/core/java/com/android/server/notification/NotificationChannelLogger.java b/services/core/java/com/android/server/notification/NotificationChannelLogger.java
index 83f4ebb..a7b1877 100644
--- a/services/core/java/com/android/server/notification/NotificationChannelLogger.java
+++ b/services/core/java/com/android/server/notification/NotificationChannelLogger.java
@@ -184,14 +184,14 @@
* @return Small hash of the channel ID, if present, or 0 otherwise.
*/
static int getIdHash(@NonNull NotificationChannel channel) {
- return NotificationRecordLogger.smallHash(channel.getId());
+ return SmallHash.hash(channel.getId());
}
/**
* @return Small hash of the channel ID, if present, or 0 otherwise.
*/
static int getIdHash(@NonNull NotificationChannelGroup group) {
- return NotificationRecordLogger.smallHash(group.getId());
+ return SmallHash.hash(group.getId());
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 31dc094..4aeddc8 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -107,6 +107,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -1213,10 +1214,12 @@
// apps querying noMan will know that their notification is not showing
// as a bubble.
r.getNotification().flags &= ~FLAG_BUBBLE;
+ r.setFlagBubbleRemoved(true);
} else {
// Enqueue will trigger resort & if the flag is allowed to be true it'll
// be applied there.
r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE;
+ r.setFlagBubbleRemoved(false);
mHandler.post(new EnqueueNotificationRunnable(r.getUser().getIdentifier(),
r, isAppForeground));
}
@@ -1867,7 +1870,8 @@
ActivityTaskManagerInternal atm, UsageStatsManagerInternal appUsageStats,
DevicePolicyManagerInternal dpm, IUriGrantsManager ugm,
UriGrantsManagerInternal ugmInternal, AppOpsManager appOps, UserManager userManager,
- NotificationHistoryManager historyManager, StatsManager statsManager) {
+ NotificationHistoryManager historyManager, StatsManager statsManager,
+ TelephonyManager telephonyManager) {
mHandler = handler;
Resources resources = getContext().getResources();
mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
@@ -2010,7 +2014,15 @@
mInterruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter();
mUserProfiles.updateCache(getContext());
- listenForCallState();
+
+ telephonyManager.listen(new PhoneStateListener() {
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (mCallState == state) return;
+ if (DBG) Slog.d(TAG, "Call state changed: " + callStateToString(state));
+ mCallState = state;
+ }
+ }, PhoneStateListener.LISTEN_CALL_STATE);
mSettingsObserver = new SettingsObserver(mHandler);
@@ -2080,7 +2092,8 @@
getContext().getSystemService(UserManager.class),
new NotificationHistoryManager(getContext(), handler),
mStatsManager = (StatsManager) getContext().getSystemService(
- Context.STATS_MANAGER));
+ Context.STATS_MANAGER),
+ getContext().getSystemService(TelephonyManager.class));
// register for various Intents
IntentFilter filter = new IntentFilter();
@@ -2842,20 +2855,18 @@
record = mToastQueue.get(index);
record.update(duration);
} else {
- // Limit the number of toasts that any given package except the android
- // package can enqueue. Prevents DOS attacks and deals with leaks.
- if (!isSystemToast) {
- int count = 0;
- final int N = mToastQueue.size();
- for (int i = 0; i < N; i++) {
- final ToastRecord r = mToastQueue.get(i);
- if (r.pkg.equals(pkg)) {
- count++;
- if (count >= MAX_PACKAGE_NOTIFICATIONS) {
- Slog.e(TAG, "Package has already posted " + count
- + " toasts. Not showing more. Package=" + pkg);
- return;
- }
+ // Limit the number of toasts that any given package can enqueue.
+ // Prevents DOS attacks and deals with leaks.
+ int count = 0;
+ final int N = mToastQueue.size();
+ for (int i = 0; i < N; i++) {
+ final ToastRecord r = mToastQueue.get(i);
+ if (r.pkg.equals(pkg)) {
+ count++;
+ if (count >= MAX_PACKAGE_NOTIFICATIONS) {
+ Slog.e(TAG, "Package has already posted " + count
+ + " toasts. Not showing more. Package=" + pkg);
+ return;
}
}
}
@@ -5638,6 +5649,7 @@
final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
r.setIsAppImportanceLocked(mPreferencesHelper.getIsAppImportanceLocked(pkg, callingUid));
r.setPostSilently(postSilently);
+ r.setFlagBubbleRemoved(false);
if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
final boolean fgServiceShown = channel.isFgServiceShown();
@@ -8356,17 +8368,6 @@
}
}
- private void listenForCallState() {
- getContext().getSystemService(TelephonyManager.class).listen(new PhoneStateListener() {
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- if (mCallState == state) return;
- if (DBG) Slog.d(TAG, "Call state changed: " + callStateToString(state));
- mCallState = state;
- }
- }, PhoneStateListener.LISTEN_CALL_STATE);
- }
-
/**
* Generates a NotificationRankingUpdate from 'sbns', considering only
* notifications visible to the given listener.
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 3f24b38..54a0f9f 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -187,6 +187,7 @@
private boolean mSuggestionsGeneratedByAssistant;
private boolean mEditChoicesBeforeSending;
private boolean mHasSeenSmartReplies;
+ private boolean mFlagBubbleRemoved;
private boolean mPostSilently;
/**
* Whether this notification (and its channels) should be considered user locked. Used in
@@ -1201,6 +1202,19 @@
return stats.hasBeenVisiblyExpanded();
}
+ /**
+ * When the bubble state on a notif changes due to user action (e.g. dismiss a bubble) then
+ * this value is set until an update or bubble change event due to user action (e.g. create
+ * bubble from sysui)
+ **/
+ public boolean isFlagBubbleRemoved() {
+ return mFlagBubbleRemoved;
+ }
+
+ public void setFlagBubbleRemoved(boolean flagBubbleRemoved) {
+ mFlagBubbleRemoved = flagBubbleRemoved;
+ }
+
public void setSystemGeneratedSmartActions(
ArrayList<Notification.Action> systemGeneratedSmartActions) {
mSystemGeneratedSmartActions = systemGeneratedSmartActions;
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
index 6c833f96..eba5730 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLogger.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
@@ -359,43 +359,24 @@
* @return Small hash of the notification ID, and tag (if present).
*/
int getNotificationIdHash() {
- return smallHash(Objects.hashCode(r.getSbn().getTag()) ^ r.getSbn().getId());
+ return SmallHash.hash(Objects.hashCode(r.getSbn().getTag()) ^ r.getSbn().getId());
}
/**
* @return Small hash of the channel ID, if present, or 0 otherwise.
*/
int getChannelIdHash() {
- return smallHash(r.getSbn().getNotification().getChannelId());
+ return SmallHash.hash(r.getSbn().getNotification().getChannelId());
}
/**
* @return Small hash of the group ID, respecting group override if present. 0 otherwise.
*/
int getGroupIdHash() {
- return smallHash(r.getSbn().getGroup());
+ return SmallHash.hash(r.getSbn().getGroup());
}
}
- // "Small" hashes will be in the range [0, MAX_HASH).
- int MAX_HASH = (1 << 13);
-
- /**
- * Maps in to the range [0, MAX_HASH), keeping similar values distinct.
- * @param in An arbitrary integer.
- * @return in mod MAX_HASH, signs chosen to stay in the range [0, MAX_HASH).
- */
- static int smallHash(int in) {
- return Math.floorMod(in, MAX_HASH);
- }
-
- /**
- * @return Small hash of the string, if non-null, or 0 otherwise.
- */
- static int smallHash(@Nullable String in) {
- return smallHash(Objects.hashCode(in));
- }
-
}
diff --git a/services/core/java/com/android/server/notification/SmallHash.java b/services/core/java/com/android/server/notification/SmallHash.java
new file mode 100644
index 0000000..4483a5b
--- /dev/null
+++ b/services/core/java/com/android/server/notification/SmallHash.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import java.util.Objects;
+
+/**
+ * A simple hash function for use in privacy-sensitive logging. Few bits = lots of collisions.
+ * See {@link NotificationRecordLogger}.
+ */
+public class SmallHash {
+ // Hashes will be in the range [0, MAX_HASH).
+ public static final int MAX_HASH = (1 << 13);
+
+ /**
+ * @return Small hash of the string, if non-null, or 0 otherwise.
+ */
+ public static int hash(String in) {
+ return hash(Objects.hashCode(in));
+ }
+
+ /**
+ * Maps in to the range [0, MAX_HASH), keeping similar values distinct.
+ * @param in An arbitrary integer.
+ * @return in mod MAX_HASH, signs chosen to stay in the range [0, MAX_HASH).
+ */
+ public static int hash(int in) {
+ return Math.floorMod(in, MAX_HASH);
+ }
+}
diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java
index 20a4c75..e8e3834 100644
--- a/services/core/java/com/android/server/om/IdmapDaemon.java
+++ b/services/core/java/com/android/server/om/IdmapDaemon.java
@@ -116,10 +116,11 @@
}
}
- boolean verifyIdmap(String overlayPath, int policies, boolean enforce, int userId)
+ boolean verifyIdmap(String targetPath, String overlayPath, int policies, boolean enforce,
+ int userId)
throws Exception {
try (Connection connection = connect()) {
- return mService.verifyIdmap(overlayPath, policies, enforce, userId);
+ return mService.verifyIdmap(targetPath, overlayPath, policies, enforce, userId);
}
}
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 7c9be2d..43fc7ed 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -75,7 +75,7 @@
try {
int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId);
boolean enforce = enforceOverlayable(overlayPackage);
- if (mIdmapDaemon.verifyIdmap(overlayPath, policies, enforce, userId)) {
+ if (mIdmapDaemon.verifyIdmap(targetPath, overlayPath, policies, enforce, userId)) {
return true;
}
return mIdmapDaemon.createIdmap(targetPath, overlayPath, policies,
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 8349632..fce488d 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -16,6 +16,7 @@
package com.android.server.os;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -34,7 +35,6 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
import com.android.server.SystemConfig;
import java.io.FileDescriptor;
@@ -95,11 +95,22 @@
@Override
@RequiresPermission(android.Manifest.permission.DUMP)
public void cancelBugreport() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "startBugreport");
- // This tells init to cancel bugreportd service. Note that this is achieved through setting
- // a system property which is not thread-safe. So the lock here offers thread-safety only
- // among callers of the API.
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
+ "cancelBugreport");
synchronized (mLock) {
+ IDumpstate ds = getDumpstateBinderServiceLocked();
+ if (ds == null) {
+ Slog.w(TAG, "cancelBugreport: Could not find native dumpstate service");
+ return;
+ }
+ try {
+ ds.cancelBugreport();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException in cancelBugreport", e);
+ }
+ // This tells init to cancel bugreportd service. Note that this is achieved through
+ // setting a system property which is not thread-safe. So the lock here offers
+ // thread-safety only among callers of the API.
SystemProperties.set("ctl.stop", BUGREPORT_SERVICE);
}
}
@@ -177,8 +188,14 @@
@GuardedBy("mLock")
private boolean isDumpstateBinderServiceRunningLocked() {
- IDumpstate ds = IDumpstate.Stub.asInterface(ServiceManager.getService("dumpstate"));
- return ds != null;
+ return getDumpstateBinderServiceLocked() != null;
+ }
+
+ @GuardedBy("mLock")
+ @Nullable
+ private IDumpstate getDumpstateBinderServiceLocked() {
+ // Note that the binder service on the native side is "dumpstate".
+ return IDumpstate.Stub.asInterface(ServiceManager.getService("dumpstate"));
}
/*
@@ -202,8 +219,7 @@
int totalTimeWaitedMillis = 0;
int seedWaitTimeMillis = 500;
while (!timedOut) {
- // Note that the binder service on the native side is "dumpstate".
- ds = IDumpstate.Stub.asInterface(ServiceManager.getService("dumpstate"));
+ ds = getDumpstateBinderServiceLocked();
if (ds != null) {
Slog.i(TAG, "Got bugreport service handle.");
break;
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index c97f33b..142e813 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -61,11 +61,9 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
-import java.util.stream.Collectors;
/**
* ApexManager class handles communications with the apex service to perform operation and queries,
@@ -538,30 +536,42 @@
List<PackageInfo> getActivePackages() {
Preconditions.checkState(mAllPackagesCache != null,
"APEX packages have not been scanned");
- return mAllPackagesCache
- .stream()
- .filter(item -> isActive(item))
- .collect(Collectors.toList());
+ final List<PackageInfo> activePackages = new ArrayList<>();
+ for (int i = 0; i < mAllPackagesCache.size(); i++) {
+ final PackageInfo packageInfo = mAllPackagesCache.get(i);
+ if (isActive(packageInfo)) {
+ activePackages.add(packageInfo);
+ }
+ }
+ return activePackages;
}
@Override
List<PackageInfo> getFactoryPackages() {
Preconditions.checkState(mAllPackagesCache != null,
"APEX packages have not been scanned");
- return mAllPackagesCache
- .stream()
- .filter(item -> isFactory(item))
- .collect(Collectors.toList());
+ final List<PackageInfo> factoryPackages = new ArrayList<>();
+ for (int i = 0; i < mAllPackagesCache.size(); i++) {
+ final PackageInfo packageInfo = mAllPackagesCache.get(i);
+ if (isFactory(packageInfo)) {
+ factoryPackages.add(packageInfo);
+ }
+ }
+ return factoryPackages;
}
@Override
List<PackageInfo> getInactivePackages() {
Preconditions.checkState(mAllPackagesCache != null,
"APEX packages have not been scanned");
- return mAllPackagesCache
- .stream()
- .filter(item -> !isActive(item))
- .collect(Collectors.toList());
+ final List<PackageInfo> inactivePackages = new ArrayList<>();
+ for (int i = 0; i < mAllPackagesCache.size(); i++) {
+ final PackageInfo packageInfo = mAllPackagesCache.get(i);
+ if (!isActive(packageInfo)) {
+ inactivePackages.add(packageInfo);
+ }
+ }
+ return inactivePackages;
}
@Override
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 690b9f7..805d918 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -55,6 +55,7 @@
import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -507,7 +508,65 @@
private static boolean isSystemSigned(@NonNull PackageParser.SigningDetails sysSigningDetails,
PackageSetting pkgSetting) {
return pkgSetting.isSystem()
- && pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails);
+ && pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails);
+ }
+
+ private static void sort(int[] uids, int nextUidIndex) {
+ Arrays.sort(uids, 0, nextUidIndex);
+ }
+
+ /**
+ * Fetches all app Ids that a given setting is currently visible to, per provided user. This
+ * only includes UIDs >= {@link Process#FIRST_APPLICATION_UID} as all other UIDs can already see
+ * all applications.
+ *
+ * If the setting is visible to all UIDs, null is returned. If an app is not visible to any
+ * applications, the int array will be empty.
+ *
+ * @param users the set of users that should be evaluated for this calculation
+ * @param existingSettings the set of all package settings that currently exist on device
+ * @return a SparseArray mapping userIds to a sorted int array of appIds that may view the
+ * provided setting or null if the app is visible to all and no whitelist should be
+ * applied.
+ */
+ @Nullable
+ public SparseArray<int[]> getVisibilityWhitelist(PackageSetting setting, int[] users,
+ ArrayMap<String, PackageSetting> existingSettings) {
+ if (mForceQueryable.contains(setting.appId)) {
+ return null;
+ }
+ // let's reserve max memory to limit the number of allocations
+ SparseArray<int[]> result = new SparseArray<>(users.length);
+ for (int u = 0; u < users.length; u++) {
+ final int userId = users[u];
+ int[] appIds = new int[existingSettings.size()];
+ int[] buffer = null;
+ int whitelistSize = 0;
+ for (int i = existingSettings.size() - 1; i >= 0; i--) {
+ final PackageSetting existingSetting = existingSettings.valueAt(i);
+ final int existingAppId = existingSetting.appId;
+ if (existingAppId < Process.FIRST_APPLICATION_UID) {
+ continue;
+ }
+ final int loc = Arrays.binarySearch(appIds, 0, whitelistSize, existingAppId);
+ if (loc >= 0) {
+ continue;
+ }
+ final int existingUid = UserHandle.getUid(userId, existingAppId);
+ if (!shouldFilterApplication(existingUid, existingSetting, setting, userId)) {
+ if (buffer == null) {
+ buffer = new int[appIds.length];
+ }
+ final int insert = ~loc;
+ System.arraycopy(appIds, insert, buffer, 0, whitelistSize - insert);
+ appIds[insert] = existingUid;
+ System.arraycopy(buffer, 0, appIds, insert + 1, whitelistSize - insert);
+ whitelistSize++;
+ }
+ }
+ result.put(userId, Arrays.copyOf(appIds, whitelistSize));
+ }
+ return result;
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 34363c8..414449d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -93,6 +93,7 @@
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PackageManager.RESTRICTION_NONE;
+import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
import static android.content.pm.PackageParser.isApkFile;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.incremental.IncrementalManager.isIncrementalPath;
@@ -135,6 +136,7 @@
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.ApplicationPackageManager;
import android.app.BroadcastOptions;
@@ -415,7 +417,6 @@
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
-import java.util.stream.Collectors;
/**
* Keep track of all those APKs everywhere.
@@ -737,9 +738,10 @@
final private ArrayMap<String, File> mExpectingBetter = new ArrayMap<>();
/**
- * Tracks existing system packages prior to receiving an OTA. Keys are package name.
+ * Tracks existing packages prior to receiving an OTA. Keys are package name.
+ * Only non-null during an OTA, and even then it is nulled again once systemReady().
*/
- final private ArraySet<String> mExistingSystemPackages = new ArraySet<>();
+ private @Nullable ArraySet<String> mExistingPackages = null;
/**
* Whether or not system app permissions should be promoted from install to runtime.
*/
@@ -881,6 +883,7 @@
private final Singleton<UserManagerService> mUserManagerProducer;
private final Singleton<Settings> mSettingsProducer;
private final Singleton<ActivityTaskManagerInternal> mActivityTaskManagerProducer;
+ private final Singleton<ActivityManagerInternal> mActivityManagerInternalProducer;
private final Singleton<DeviceIdleInternal> mLocalDeviceIdleController;
private final Singleton<StorageManagerInternal> mStorageManagerInternalProducer;
private final Singleton<NetworkPolicyManagerInternal> mNetworkPolicyManagerProducer;
@@ -899,6 +902,7 @@
Producer<UserManagerService> userManagerProducer,
Producer<Settings> settingsProducer,
Producer<ActivityTaskManagerInternal> activityTaskManagerProducer,
+ Producer<ActivityManagerInternal> activityManagerInternalProducer,
Producer<DeviceIdleInternal> deviceIdleControllerProducer,
Producer<StorageManagerInternal> storageManagerInternalProducer,
Producer<NetworkPolicyManagerInternal> networkPolicyManagerProducer,
@@ -919,6 +923,7 @@
mUserManagerProducer = new Singleton<>(userManagerProducer);
mSettingsProducer = new Singleton<>(settingsProducer);
mActivityTaskManagerProducer = new Singleton<>(activityTaskManagerProducer);
+ mActivityManagerInternalProducer = new Singleton<>(activityManagerInternalProducer);
mLocalDeviceIdleController = new Singleton<>(deviceIdleControllerProducer);
mStorageManagerInternalProducer = new Singleton<>(storageManagerInternalProducer);
mNetworkPolicyManagerProducer = new Singleton<>(networkPolicyManagerProducer);
@@ -983,6 +988,10 @@
return mActivityTaskManagerProducer.get(this, mPackageManager);
}
+ public ActivityManagerInternal getActivityManagerInternal() {
+ return mActivityManagerInternalProducer.get(this, mPackageManager);
+ }
+
public DeviceIdleInternal getLocalDeviceIdleController() {
return mLocalDeviceIdleController.get(this, mPackageManager);
}
@@ -2118,16 +2127,23 @@
}
extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
// Send to all running apps.
+ final SparseArray<int[]> newBroadcastWhitelist;
+
+ synchronized (mLock) {
+ newBroadcastWhitelist = mAppsFilter.getVisibilityWhitelist(
+ getPackageSettingInternal(res.name, Process.SYSTEM_UID),
+ updateUserIds, mSettings.mPackages);
+ }
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, newBroadcastWhitelist);
if (installerPackageName != null) {
// Send to the installer, even if it's not running.
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
installerPackageName, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, null /* broadcastWhitelist */);
}
// if the required verifier is defined, but, is not the installer of record
// for the package, it gets notified
@@ -2137,7 +2153,7 @@
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
mRequiredVerifierPackage, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, null /* broadcastWhitelist */);
}
// If package installer is defined, notify package installer about new
// app installed
@@ -2145,7 +2161,7 @@
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/,
mRequiredInstallerPackage, null /*finishedReceiver*/,
- firstUserIds, instantUserIds);
+ firstUserIds, instantUserIds, null /* broadcastWhitelist */);
}
// Send replaced for users that don't see the package for the first time
@@ -2153,23 +2169,24 @@
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
packageName, extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, res.removedInfo.broadcastWhitelist);
if (installerPackageName != null) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
extras, 0 /*flags*/,
installerPackageName, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, null /*broadcastWhitelist*/);
}
if (notifyVerifier) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
extras, 0 /*flags*/,
mRequiredVerifierPackage, null /*finishedReceiver*/,
- updateUserIds, instantUserIds);
+ updateUserIds, instantUserIds, null /*broadcastWhitelist*/);
}
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
null /*package*/, null /*extras*/, 0 /*flags*/,
packageName /*targetPackage*/,
- null /*finishedReceiver*/, updateUserIds, instantUserIds);
+ null /*finishedReceiver*/, updateUserIds, instantUserIds,
+ null /*broadcastWhitelist*/);
} else if (launchedForRestore && !res.pkg.isSystem()) {
// First-install and we did a restore, so we're responsible for the
// first-launch broadcast.
@@ -2206,6 +2223,7 @@
sendResourcesChangedBroadcast(true, true, pkgList, uidArray, null);
}
} else if (!ArrayUtils.isEmpty(res.libraryConsumers)) { // if static shared lib
+ int[] allUsers = mInjector.getUserManagerService().getUserIds();
for (int i = 0; i < res.libraryConsumers.size(); i++) {
AndroidPackage pkg = res.libraryConsumers.get(i);
// send broadcast that all consumers of the static shared library have changed
@@ -2511,6 +2529,7 @@
i.getPermissionManagerServiceInternal().getPermissionSettings(),
lock),
new Injector.LocalServicesProducer<>(ActivityTaskManagerInternal.class),
+ new Injector.LocalServicesProducer<>(ActivityManagerInternal.class),
new Injector.LocalServicesProducer<>(DeviceIdleInternal.class),
new Injector.LocalServicesProducer<>(StorageManagerInternal.class),
new Injector.LocalServicesProducer<>(NetworkPolicyManagerInternal.class),
@@ -2570,9 +2589,10 @@
private void installWhitelistedSystemPackages() {
synchronized (mLock) {
final boolean scheduleWrite = mUserManager.installWhitelistedSystemPackages(
- isFirstBoot(), isDeviceUpgrading());
+ isFirstBoot(), isDeviceUpgrading(), mExistingPackages);
if (scheduleWrite) {
scheduleWritePackageRestrictionsLocked(UserHandle.USER_ALL);
+ scheduleWriteSettingsLocked();
}
}
}
@@ -2655,6 +2675,11 @@
+ partition.folder);
}
}
+
+ @Override
+ public String toString() {
+ return folder.getAbsolutePath() + ":" + scanFlag;
+ }
}
public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
@@ -2757,15 +2782,19 @@
mApexManager = ApexManager.getInstance();
mAppsFilter = mInjector.getAppsFilter();
+ final List<ScanPartition> scanPartitions = new ArrayList<>();
+ final List<ApexManager.ActiveApexInfo> activeApexInfos = mApexManager.getActiveApexInfos();
+ for (int i = 0; i < activeApexInfos.size(); i++) {
+ final ScanPartition scanPartition = resolveApexToScanPartition(activeApexInfos.get(i));
+ if (scanPartition != null) {
+ scanPartitions.add(scanPartition);
+ }
+ }
+
mDirsToScanAsSystem = new ArrayList<>();
mDirsToScanAsSystem.addAll(SYSTEM_PARTITIONS);
- mDirsToScanAsSystem.addAll(mApexManager.getActiveApexInfos().stream()
- .map(PackageManagerService::resolveApexToScanPartition)
- .filter(Objects::nonNull).collect(Collectors.toList()));
- Slog.d(TAG,
- "Directories scanned as system partitions: [" + mDirsToScanAsSystem.stream().map(
- d -> (d.folder.getAbsolutePath() + ":" + d.scanFlag))
- .collect(Collectors.joining(",")) + "]");
+ mDirsToScanAsSystem.addAll(scanPartitions);
+ Slog.d(TAG, "Directories scanned as system partitions: " + mDirsToScanAsSystem);
// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
@@ -2873,13 +2902,12 @@
mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;
- // save off the names of pre-existing system packages prior to scanning; we don't
- // want to automatically grant runtime permissions for new system apps
- if (mPromoteSystemApps) {
+ // Save the names of pre-existing packages prior to scanning, so we can determine
+ // which system packages are completely new due to an upgrade.
+ if (isDeviceUpgrading()) {
+ mExistingPackages = new ArraySet<>(mSettings.mPackages.size());
for (PackageSetting ps : mSettings.mPackages.values()) {
- if (isSystemApp(ps)) {
- mExistingSystemPackages.add(ps.name);
- }
+ mExistingPackages.add(ps.name);
}
}
@@ -3340,7 +3368,6 @@
}
// clear only after permissions and other defaults have been updated
- mExistingSystemPackages.clear();
mPromoteSystemApps = false;
// All the changes are done during package scanning.
@@ -12204,7 +12231,8 @@
@Override
public void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,
final int flags, final String targetPkg, final IIntentReceiver finishedReceiver,
- final int[] userIds, int[] instantUserIds) {
+ final int[] userIds, int[] instantUserIds,
+ @Nullable SparseArray<int[]> broadcastWhitelist) {
mHandler.post(() -> {
try {
final IActivityManager am = ActivityManager.getService();
@@ -12216,10 +12244,10 @@
resolvedUserIds = userIds;
}
doSendBroadcast(am, action, pkg, extras, flags, targetPkg, finishedReceiver,
- resolvedUserIds, false);
+ resolvedUserIds, false, broadcastWhitelist);
if (instantUserIds != null && instantUserIds != EMPTY_INT_ARRAY) {
doSendBroadcast(am, action, pkg, extras, flags, targetPkg, finishedReceiver,
- instantUserIds, true);
+ instantUserIds, true, null);
}
} catch (RemoteException ex) {
}
@@ -12289,8 +12317,7 @@
*/
private void doSendBroadcast(IActivityManager am, String action, String pkg, Bundle extras,
int flags, String targetPkg, IIntentReceiver finishedReceiver,
- int[] userIds, boolean isInstantApp)
- throws RemoteException {
+ int[] userIds, boolean isInstantApp, @Nullable SparseArray<int[]> broadcastWhitelist) {
for (int id : userIds) {
final Intent intent = new Intent(action,
pkg != null ? Uri.fromParts(PACKAGE_SCHEME, pkg, null) : null);
@@ -12317,9 +12344,10 @@
+ intent.toShortString(false, true, false, false)
+ " " + intent.getExtras(), here);
}
- am.broadcastIntentWithFeature(null, null, intent, null, finishedReceiver,
- 0, null, null, requiredPermissions, android.app.AppOpsManager.OP_NONE,
- null, finishedReceiver != null, false, id);
+ mInjector.getActivityManagerInternal().broadcastIntent(
+ intent, finishedReceiver, requiredPermissions,
+ finishedReceiver != null, id,
+ broadcastWhitelist == null ? null : broadcastWhitelist.get(id));
}
}
@@ -12447,7 +12475,10 @@
extras.putInt(Intent.EXTRA_UID, uid);
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- packageName, extras, 0, null, null, userIds, instantUserIds);
+ packageName, extras, 0, null, null, userIds, instantUserIds,
+ mAppsFilter.getVisibilityWhitelist(
+ getPackageSettingInternal(packageName, Process.SYSTEM_UID),
+ userIds, mSettings.mPackages));
if (sendBootCompleted && !ArrayUtils.isEmpty(userIds)) {
mHandler.post(() -> {
for (int userId : userIds) {
@@ -12653,7 +12684,7 @@
extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, distractionFlags);
sendPackageBroadcast(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED, null, extras,
- Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null, new int[]{userId}, null);
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null, new int[]{userId}, null, null);
}
private void sendPackagesSuspendedForUser(String[] pkgList, int[] uidList, int userId,
@@ -12665,7 +12696,7 @@
suspended ? Intent.ACTION_PACKAGES_SUSPENDED
: Intent.ACTION_PACKAGES_UNSUSPENDED,
null, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null,
- new int[] {userId}, null);
+ new int[] {userId}, null, null);
}
/**
@@ -12767,6 +12798,7 @@
pkgSetting.setInstalled(true, userId);
pkgSetting.setHidden(false, userId);
pkgSetting.setInstallReason(installReason, userId);
+ pkgSetting.setUninstallReason(PackageManager.UNINSTALL_REASON_UNKNOWN, userId);
mSettings.writePackageRestrictionsLPr(userId);
mSettings.writeKernelMappingLPr(pkgSetting);
installed = true;
@@ -13055,31 +13087,27 @@
? Intent.ACTION_MY_PACKAGE_SUSPENDED
: Intent.ACTION_MY_PACKAGE_UNSUSPENDED;
mHandler.post(() -> {
- try {
- final IActivityManager am = ActivityManager.getService();
- if (am == null) {
- Slog.wtf(TAG, "IActivityManager null. Cannot send MY_PACKAGE_ "
- + (suspended ? "" : "UN") + "SUSPENDED broadcasts");
- return;
+ final IActivityManager am = ActivityManager.getService();
+ if (am == null) {
+ Slog.wtf(TAG, "IActivityManager null. Cannot send MY_PACKAGE_ "
+ + (suspended ? "" : "UN") + "SUSPENDED broadcasts");
+ return;
+ }
+ final int[] targetUserIds = new int[] {userId};
+ for (String packageName : affectedPackages) {
+ final Bundle appExtras = suspended
+ ? getSuspendedPackageAppExtrasInternal(packageName, userId)
+ : null;
+ final Bundle intentExtras;
+ if (appExtras != null) {
+ intentExtras = new Bundle(1);
+ intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, appExtras);
+ } else {
+ intentExtras = null;
}
- final int[] targetUserIds = new int[] {userId};
- for (String packageName : affectedPackages) {
- final Bundle appExtras = suspended
- ? getSuspendedPackageAppExtrasInternal(packageName, userId)
- : null;
- final Bundle intentExtras;
- if (appExtras != null) {
- intentExtras = new Bundle(1);
- intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, appExtras);
- } else {
- intentExtras = null;
- }
- doSendBroadcast(am, action, null, intentExtras,
- Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null,
- targetUserIds, false);
- }
- } catch (RemoteException ex) {
- // Shouldn't happen as AMS is in the same process.
+ doSendBroadcast(am, action, null, intentExtras,
+ Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null,
+ targetUserIds, false, null);
}
});
}
@@ -14079,7 +14107,7 @@
private void sendFirstLaunchBroadcast(String pkgName, String installerPkg,
int[] userIds, int[] instantUserIds) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, pkgName, null, 0,
- installerPkg, null, userIds, instantUserIds);
+ installerPkg, null, userIds, instantUserIds, null /* broadcastWhitelist */);
}
private abstract class HandlerParams {
@@ -15599,7 +15627,8 @@
}
// It's implied that when a user requests installation, they want the app to be
- // installed and enabled.
+ // installed and enabled. (This does not apply to USER_ALL, which here means only
+ // install on users for which the app is already installed).
if (userId != UserHandle.USER_ALL) {
ps.setInstalled(true, userId);
ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName);
@@ -15617,7 +15646,7 @@
mSettings.addInstallerPackageNames(installSource);
// When replacing an existing package, preserve the original install reason for all
- // users that had the package installed before.
+ // users that had the package installed before. Similarly for uninstall reasons.
final Set<Integer> previousUserIds = new ArraySet<>();
if (res.removedInfo != null && res.removedInfo.installReasons != null) {
final int installReasonCount = res.removedInfo.installReasons.size();
@@ -15628,10 +15657,20 @@
previousUserIds.add(previousUserId);
}
}
+ if (res.removedInfo != null && res.removedInfo.uninstallReasons != null) {
+ for (int i = 0; i < res.removedInfo.uninstallReasons.size(); i++) {
+ final int previousUserId = res.removedInfo.uninstallReasons.keyAt(i);
+ final int previousReason = res.removedInfo.uninstallReasons.valueAt(i);
+ ps.setUninstallReason(previousReason, previousUserId);
+ }
+ }
// Set install reason for users that are having the package newly installed.
+ final int[] allUsersList = mUserManager.getUserIds();
if (userId == UserHandle.USER_ALL) {
- for (int currentUserId : mUserManager.getUserIds()) {
+ // TODO(b/152629990): It appears that the package doesn't actually get newly
+ // installed in this case, so the installReason shouldn't get modified?
+ for (int currentUserId : allUsersList) {
if (!previousUserIds.contains(currentUserId)) {
ps.setInstallReason(installReason, currentUserId);
}
@@ -15639,6 +15678,12 @@
} else if (!previousUserIds.contains(userId)) {
ps.setInstallReason(installReason, userId);
}
+ // Ensure that the uninstall reason is UNKNOWN for users with the package installed.
+ for (int currentUserId : allUsersList) {
+ if (ps.getInstalled(currentUserId)) {
+ ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, currentUserId);
+ }
+ }
mSettings.writeKernelMappingLPr(ps);
}
res.name = pkgName;
@@ -16145,6 +16190,8 @@
reconciledPkg.pkgSetting.firstInstallTime = deletedPkgSetting.firstInstallTime;
reconciledPkg.pkgSetting.lastUpdateTime = System.currentTimeMillis();
+ res.removedInfo.broadcastWhitelist = mAppsFilter.getVisibilityWhitelist(
+ reconciledPkg.pkgSetting, request.mAllUsers, mSettings.mPackages);
if (reconciledPkg.prepareResult.system) {
// Remove existing system package
removePackageLI(oldPackage, true);
@@ -17002,6 +17049,7 @@
final String pkgName11 = parsedPackage.getPackageName();
final int[] allUsers;
final int[] installedUsers;
+ final int[] uninstalledUsers;
synchronized (mLock) {
oldPackage = mPackages.get(pkgName11);
@@ -17076,6 +17124,7 @@
// In case of rollback, remember per-user/profile install state
allUsers = mUserManager.getUserIds();
installedUsers = ps.queryInstalledUsers(allUsers, true);
+ uninstalledUsers = ps.queryInstalledUsers(allUsers, false);
// don't allow an upgrade from full to ephemeral
@@ -17114,6 +17163,11 @@
final int userId = installedUsers[i];
res.removedInfo.installReasons.put(userId, ps.getInstallReason(userId));
}
+ res.removedInfo.uninstallReasons = new SparseArray<>(uninstalledUsers.length);
+ for (int i = 0; i < uninstalledUsers.length; i++) {
+ final int userId = uninstalledUsers[i];
+ res.removedInfo.uninstallReasons.put(userId, ps.getUninstallReason(userId));
+ }
sysPkg = oldPackage.isSystem();
if (sysPkg) {
@@ -17946,11 +18000,15 @@
int[] broadcastUsers = null;
int[] instantUserIds = null;
SparseArray<Integer> installReasons;
+ SparseArray<Integer> uninstallReasons;
boolean isRemovedPackageSystemUpdate = false;
boolean isUpdate;
boolean dataRemoved;
boolean removedForAllUsers;
boolean isStaticSharedLib;
+ // a two dimensional array mapping userId to the set of appIds that can receive notice
+ // of package changes
+ SparseArray<int[]> broadcastWhitelist;
// Clean up resources deleted packages.
InstallArgs args = null;
ArrayMap<String, PackageInstalledInfo> appearedChildPackages;
@@ -17984,19 +18042,19 @@
Bundle extras = new Bundle(2);
extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
extras.putBoolean(Intent.EXTRA_REPLACING, true);
- packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- removedPackage, extras, 0, null /*targetPackage*/, null, null, null);
- packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
- removedPackage, extras, 0, null /*targetPackage*/, null, null, null);
- packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
- null, null, 0, removedPackage, null, null, null);
+ packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, removedPackage, extras,
+ 0, null /*targetPackage*/, null, null, null, broadcastWhitelist);
+ packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage,
+ extras, 0, null /*targetPackage*/, null, null, null, broadcastWhitelist);
+ packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
+ removedPackage, null, null, null, null /* broadcastWhitelist */);
if (installerPackageName != null) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
removedPackage, extras, 0 /*flags*/,
- installerPackageName, null, null, null);
+ installerPackageName, null, null, null, null /* broadcastWhitelist */);
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
removedPackage, extras, 0 /*flags*/,
- installerPackageName, null, null, null);
+ installerPackageName, null, null, null, null /* broadcastWhitelist */);
}
}
@@ -18019,17 +18077,16 @@
if (removedPackage != null) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
removedPackage, extras, 0, null /*targetPackage*/, null,
- broadcastUsers, instantUserIds);
+ broadcastUsers, instantUserIds, broadcastWhitelist);
if (installerPackageName != null) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
removedPackage, extras, 0 /*flags*/,
- installerPackageName, null, broadcastUsers, instantUserIds);
+ installerPackageName, null, broadcastUsers, instantUserIds, null);
}
if (dataRemoved && !isRemovedPackageSystemUpdate) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
- removedPackage, extras,
- Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
- null, null, broadcastUsers, instantUserIds);
+ removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null,
+ null, broadcastUsers, instantUserIds, broadcastWhitelist);
packageSender.notifyPackageRemoved(removedPackage, removedUid);
}
}
@@ -18042,7 +18099,7 @@
packageSender.sendPackageBroadcast(Intent.ACTION_UID_REMOVED,
null, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
- null, null, broadcastUsers, instantUserIds);
+ null, null, broadcastUsers, instantUserIds, broadcastWhitelist);
}
}
@@ -18168,6 +18225,9 @@
installedStateChanged = true;
}
deletedPs.setInstalled(installed, userId);
+ if (installed) {
+ deletedPs.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
+ }
}
}
}
@@ -18350,6 +18410,9 @@
installedStateChanged = true;
}
ps.setInstalled(installed, userId);
+ if (installed) {
+ ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
+ }
mSettings.writeRuntimePermissionsForUserLPr(userId, false);
}
@@ -18622,7 +18685,9 @@
null /*enabledComponents*/,
null /*disabledComponents*/,
ps.readUserState(nextUserId).domainVerificationStatus,
- 0, PackageManager.INSTALL_REASON_UNKNOWN,
+ 0 /*linkGeneration*/,
+ PackageManager.INSTALL_REASON_UNKNOWN,
+ PackageManager.UNINSTALL_REASON_UNKNOWN,
null /*harmfulAppWarning*/);
}
mSettings.writeKernelMappingLPr(ps);
@@ -20375,8 +20440,7 @@
}
private void sendPackageChangedBroadcast(String packageName,
- boolean dontKillApp, ArrayList<String> componentNames, int packageUid,
- String reason) {
+ boolean dontKillApp, ArrayList<String> componentNames, int packageUid, String reason) {
if (DEBUG_INSTALL)
Log.v(TAG, "Sending package changed: package=" + packageName + " components="
+ componentNames);
@@ -20399,8 +20463,14 @@
final boolean isInstantApp = isInstantApp(packageName, userId);
final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
+ final SparseArray<int[]> broadcastWhitelist;
+ synchronized (mLock) {
+ broadcastWhitelist = isInstantApp ? null : mAppsFilter.getVisibilityWhitelist(
+ getPackageSettingInternal(packageName, Process.SYSTEM_UID),
+ userIds, mSettings.mPackages);
+ }
sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null,
- userIds, instantUserIds);
+ userIds, instantUserIds, broadcastWhitelist);
}
@Override
@@ -20773,6 +20843,8 @@
// installation on reboot. Make sure this is the last component to be call since the
// installation might require other components to be ready.
mInstallerService.restoreAndApplyStagedSessionIfNeeded();
+
+ mExistingPackages = null;
}
public void waitForAppDataPrepared() {
@@ -21634,7 +21706,7 @@
}
private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
- String[] pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
+ String[] pkgList, int[] uidArr, IIntentReceiver finishedReceiver) {
int size = pkgList.length;
if (size > 0) {
// Send broadcasts here
@@ -21648,7 +21720,8 @@
}
String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
: Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
- sendPackageBroadcast(action, null, extras, 0, null, finishedReceiver, null, null);
+ // TODO: not sure how to handle this one.
+ sendPackageBroadcast(action, null, extras, 0, null, finishedReceiver, null, null, null);
}
}
@@ -22725,16 +22798,17 @@
/**
* Called by UserManagerService.
*
- * @param installablePackages system packages that should be initially installed for this user,
- * or {@code null} if all system packages should be installed
+ * @param userTypeInstallablePackages system packages that should be initially installed for
+ * this type of user, or {@code null} if all system packages
+ * should be installed
* @param disallowedPackages packages that should not be initially installed. Takes precedence
* over installablePackages.
*/
- void createNewUser(int userId, @Nullable Set<String> installablePackages,
+ void createNewUser(int userId, @Nullable Set<String> userTypeInstallablePackages,
String[] disallowedPackages) {
synchronized (mInstallLock) {
mSettings.createNewUserLI(this, mInstaller, userId,
- installablePackages, disallowedPackages);
+ userTypeInstallablePackages, disallowedPackages);
}
synchronized (mLock) {
scheduleWritePackageRestrictionsLocked(userId);
@@ -23748,19 +23822,6 @@
}
@Override
- public boolean setInstalled(AndroidPackage pkg, @UserIdInt int userId,
- boolean installed) {
- synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName());
- if (ps.getInstalled(userId) != installed) {
- ps.setInstalled(installed, userId);
- return true;
- }
- return false;
- }
- }
-
- @Override
public void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
Intent origIntent, String resolvedType, String callingPackage,
@Nullable String callingFeatureId, boolean isRequesterInstantApp,
@@ -23830,16 +23891,6 @@
}
@Override
- public boolean isLegacySystemApp(AndroidPackage pkg) {
- synchronized (mLock) {
- final PackageSetting ps = getPackageSetting(pkg.getPackageName());
- return mPromoteSystemApps
- && ps.isSystem()
- && mExistingSystemPackages.contains(ps.name);
- }
- }
-
- @Override
public List<PackageInfo> getOverlayPackages(int userId) {
final ArrayList<PackageInfo> overlayPackages = new ArrayList<PackageInfo>();
synchronized (mLock) {
@@ -24844,7 +24895,8 @@
*/
void sendPackageBroadcast(final String action, final String pkg,
final Bundle extras, final int flags, final String targetPkg,
- final IIntentReceiver finishedReceiver, final int[] userIds, int[] instantUserIds);
+ final IIntentReceiver finishedReceiver, final int[] userIds, int[] instantUserIds,
+ @Nullable SparseArray<int[]> broadcastWhitelist);
void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted,
boolean includeStopped, int appId, int[] userIds, int[] instantUserIds);
void notifyPackageAdded(String packageName, int uid);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 8a9f1b3..b4eacf6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -105,6 +105,7 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
+import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
import dalvik.system.DexFile;
@@ -118,7 +119,6 @@
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
@@ -1278,42 +1278,7 @@
pw.println("Success");
return 0;
}
-
- long timeoutMs = params.timeoutMs <= 0
- ? DEFAULT_WAIT_MS
- : params.timeoutMs;
- PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
- .getSessionInfo(sessionId);
- long currentTime = System.currentTimeMillis();
- long endTime = currentTime + timeoutMs;
- // Using a loop instead of BroadcastReceiver since we can receive session update
- // broadcast only if packageInstallerName is "android". We can't always force
- // "android" as packageIntallerName, e.g, rollback auto implies
- // "-i com.android.shell".
- while (currentTime < endTime) {
- if (si != null
- && (si.isStagedSessionReady() || si.isStagedSessionFailed())) {
- break;
- }
- SystemClock.sleep(Math.min(endTime - currentTime, 100));
- currentTime = System.currentTimeMillis();
- si = mInterface.getPackageInstaller().getSessionInfo(sessionId);
- }
- if (si == null) {
- pw.println("Failure [failed to retrieve SessionInfo]");
- return 1;
- }
- if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) {
- pw.println("Failure [timed out after " + timeoutMs + " ms]");
- return 1;
- }
- if (!si.isStagedSessionReady()) {
- pw.println("Error [" + si.getStagedSessionErrorCode() + "] ["
- + si.getStagedSessionErrorMessage() + "]");
- return 1;
- }
- pw.println("Success. Reboot device to apply staged session");
- return 0;
+ return doWaitForStagedSessionRead(sessionId, params.timeoutMs, pw);
} finally {
if (abandonSession) {
try {
@@ -1324,14 +1289,92 @@
}
}
+ private int doWaitForStagedSessionRead(int sessionId, long timeoutMs, PrintWriter pw)
+ throws RemoteException {
+ if (timeoutMs <= 0) {
+ timeoutMs = DEFAULT_WAIT_MS;
+ }
+ PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
+ .getSessionInfo(sessionId);
+ if (si == null) {
+ pw.println("Failure [Unknown session " + sessionId + "]");
+ return 1;
+ }
+ if (!si.isStaged()) {
+ pw.println("Failure [Session " + sessionId + " is not a staged session]");
+ return 1;
+ }
+ long currentTime = System.currentTimeMillis();
+ long endTime = currentTime + timeoutMs;
+ // Using a loop instead of BroadcastReceiver since we can receive session update
+ // broadcast only if packageInstallerName is "android". We can't always force
+ // "android" as packageIntallerName, e.g, rollback auto implies
+ // "-i com.android.shell".
+ while (currentTime < endTime) {
+ if (si != null && (si.isStagedSessionReady() || si.isStagedSessionFailed())) {
+ break;
+ }
+ SystemClock.sleep(Math.min(endTime - currentTime, 100));
+ currentTime = System.currentTimeMillis();
+ si = mInterface.getPackageInstaller().getSessionInfo(sessionId);
+ }
+ if (si == null) {
+ pw.println("Failure [failed to retrieve SessionInfo]");
+ return 1;
+ }
+ if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) {
+ pw.println("Failure [timed out after " + timeoutMs + " ms]");
+ return 1;
+ }
+ if (!si.isStagedSessionReady()) {
+ pw.println("Error [" + si.getStagedSessionErrorCode() + "] ["
+ + si.getStagedSessionErrorMessage() + "]");
+ return 1;
+ }
+ pw.println("Success. Reboot device to apply staged session");
+ return 0;
+ }
+
private int runInstallAbandon() throws RemoteException {
final int sessionId = Integer.parseInt(getNextArg());
return doAbandonSession(sessionId, true /*logSuccess*/);
}
private int runInstallCommit() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ String opt;
+ boolean waitForStagedSessionReady = true;
+ long timeoutMs = -1;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "--wait":
+ waitForStagedSessionReady = true;
+ // If there is only one remaining argument, then it represents the sessionId, we
+ // shouldn't try to parse it as timeoutMs.
+ if (getRemainingArgsCount() > 1) {
+ try {
+ timeoutMs = Long.parseLong(peekNextArg());
+ getNextArg();
+ } catch (NumberFormatException ignore) {
+ }
+ }
+ break;
+ case "--no-wait":
+ waitForStagedSessionReady = false;
+ break;
+ }
+ }
final int sessionId = Integer.parseInt(getNextArg());
- return doCommitSession(sessionId, true /*logSuccess*/);
+ if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
+ return 1;
+ }
+ final PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
+ .getSessionInfo(sessionId);
+ if (si == null || !si.isStaged() || !waitForStagedSessionReady) {
+ pw.println("Success");
+ return 0;
+ }
+ return doWaitForStagedSessionRead(sessionId, timeoutMs, pw);
}
private int runInstallCreate() throws RemoteException {
@@ -3025,9 +3068,9 @@
// 1. Single file from stdin.
if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) {
final String name = "base." + (isApex ? "apex" : "apk");
- final String metadata = "-" + name;
+ final Metadata metadata = Metadata.forStdIn(name);
session.addFile(LOCATION_DATA_APP, name, sessionSizeBytes,
- metadata.getBytes(StandardCharsets.UTF_8), null);
+ metadata.toByteArray(), null);
return 0;
}
@@ -3056,9 +3099,10 @@
private int processArgForStdin(String arg, PackageInstaller.Session session) {
final String[] fileDesc = arg.split(":");
- String name, metadata;
+ String name, fileId;
long sizeBytes;
byte[] signature = null;
+ int streamingVersion = 0;
try {
if (fileDesc.length < 2) {
@@ -3067,14 +3111,22 @@
}
name = fileDesc[0];
sizeBytes = Long.parseUnsignedLong(fileDesc[1]);
- metadata = name;
+ fileId = name;
if (fileDesc.length > 2 && !TextUtils.isEmpty(fileDesc[2])) {
- metadata = fileDesc[2];
+ fileId = fileDesc[2];
}
if (fileDesc.length > 3) {
signature = Base64.getDecoder().decode(fileDesc[3]);
}
+ if (fileDesc.length > 4) {
+ streamingVersion = Integer.parseUnsignedInt(fileDesc[4]);
+ if (streamingVersion < 0 || streamingVersion > 1) {
+ getErrPrintWriter().println(
+ "Unsupported streaming version: " + streamingVersion);
+ return 1;
+ }
+ }
} catch (IllegalArgumentException e) {
getErrPrintWriter().println(
"Unable to parse file parameters: " + arg + ", reason: " + e);
@@ -3086,9 +3138,14 @@
return 1;
}
+ final Metadata metadata;
+
if (signature != null) {
- // Streaming/adb mode.
- metadata = "+" + metadata;
+ // Streaming/adb mode. Versions:
+ // 0: data only streaming, tree has to be fully available,
+ // 1: tree and data streaming.
+ metadata = (streamingVersion == 0) ? Metadata.forDataOnlyStreaming(fileId)
+ : Metadata.forStreaming(fileId);
try {
if (V4Signature.readFrom(signature) == null) {
getErrPrintWriter().println("V4 signature is invalid in: " + arg);
@@ -3101,11 +3158,10 @@
}
} else {
// Single-shot read from stdin.
- metadata = "-" + metadata;
+ metadata = Metadata.forStdIn(fileId);
}
- session.addFile(LOCATION_DATA_APP, name, sizeBytes,
- metadata.getBytes(StandardCharsets.UTF_8), signature);
+ session.addFile(LOCATION_DATA_APP, name, sizeBytes, metadata.toByteArray(), signature);
return 0;
}
@@ -3115,7 +3171,7 @@
final File file = new File(inPath);
final String name = file.getName();
final long size = file.length();
- final byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8);
+ final Metadata metadata = Metadata.forLocalFile(inPath);
byte[] v4signatureBytes = null;
// Try to load the v4 signature file for the APK; it might not exist.
@@ -3132,7 +3188,7 @@
}
}
- session.addFile(LOCATION_DATA_APP, name, size, metadata, v4signatureBytes);
+ session.addFile(LOCATION_DATA_APP, name, size, metadata.toByteArray(), v4signatureBytes);
}
private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes,
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
index 6d83d70..2aa6e573 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -24,7 +24,6 @@
import android.os.ParcelFileDescriptor;
import android.os.ShellCommand;
import android.service.dataloader.DataLoaderService;
-import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;
@@ -114,6 +113,74 @@
}
}
+ static class Metadata {
+ /**
+ * Full files read from stdin.
+ */
+ static final byte STDIN = 0;
+ /**
+ * Full files read from local file.
+ */
+ static final byte LOCAL_FILE = 1;
+ /**
+ * Signature tree read from stdin, data streamed.
+ */
+ static final byte DATA_ONLY_STREAMING = 2;
+ /**
+ * Everything streamed.
+ */
+ static final byte STREAMING = 3;
+
+ private final byte mMode;
+ private final String mData;
+
+ static Metadata forStdIn(String fileId) {
+ return new Metadata(STDIN, fileId);
+ }
+
+ static Metadata forLocalFile(String filePath) {
+ return new Metadata(LOCAL_FILE, filePath);
+ }
+
+ static Metadata forDataOnlyStreaming(String fileId) {
+ return new Metadata(DATA_ONLY_STREAMING, fileId);
+ }
+
+ static Metadata forStreaming(String fileId) {
+ return new Metadata(STREAMING, fileId);
+ }
+
+ private Metadata(byte mode, String data) {
+ this.mMode = mode;
+ this.mData = (data == null) ? "" : data;
+ }
+
+ static Metadata fromByteArray(byte[] bytes) throws IOException {
+ if (bytes == null || bytes.length == 0) {
+ return null;
+ }
+ byte mode = bytes[0];
+ String data = new String(bytes, 1, bytes.length - 1, StandardCharsets.UTF_8);
+ return new Metadata(mode, data);
+ }
+
+ byte[] toByteArray() {
+ byte[] dataBytes = this.mData.getBytes(StandardCharsets.UTF_8);
+ byte[] result = new byte[1 + dataBytes.length];
+ result[0] = this.mMode;
+ System.arraycopy(dataBytes, 0, result, 1, dataBytes.length);
+ return result;
+ }
+
+ byte getMode() {
+ return this.mMode;
+ }
+
+ String getData() {
+ return this.mData;
+ }
+ }
+
private static class DataLoader implements DataLoaderService.DataLoader {
private DataLoaderParams mParams = null;
private FileSystemConnector mConnector = null;
@@ -136,19 +203,31 @@
}
try {
for (InstallationFile file : addedFiles) {
- String filePath = new String(file.getMetadata(), StandardCharsets.UTF_8);
- if (TextUtils.isEmpty(filePath) || filePath.startsWith(STDIN_PATH)) {
- final ParcelFileDescriptor inFd = getStdInPFD(shellCommand);
- mConnector.writeData(file.getName(), 0, file.getLengthBytes(), inFd);
- } else {
- ParcelFileDescriptor incomingFd = null;
- try {
- incomingFd = getLocalFile(shellCommand, filePath);
- mConnector.writeData(file.getName(), 0, incomingFd.getStatSize(),
- incomingFd);
- } finally {
- IoUtils.closeQuietly(incomingFd);
+ Metadata metadata = Metadata.fromByteArray(file.getMetadata());
+ if (metadata == null) {
+ Slog.e(TAG, "Invalid metadata for file: " + file.getName());
+ return false;
+ }
+ switch (metadata.getMode()) {
+ case Metadata.STDIN: {
+ final ParcelFileDescriptor inFd = getStdInPFD(shellCommand);
+ mConnector.writeData(file.getName(), 0, file.getLengthBytes(), inFd);
+ break;
}
+ case Metadata.LOCAL_FILE: {
+ ParcelFileDescriptor incomingFd = null;
+ try {
+ incomingFd = getLocalFile(shellCommand, metadata.getData());
+ mConnector.writeData(file.getName(), 0, incomingFd.getStatSize(),
+ incomingFd);
+ } finally {
+ IoUtils.closeQuietly(incomingFd);
+ }
+ break;
+ }
+ default:
+ Slog.e(TAG, "Unsupported metadata mode: " + metadata.getMode());
+ return false;
}
}
return true;
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 318a233..7cb3df5 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -24,6 +24,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.UninstallReason;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.content.pm.Signature;
@@ -315,6 +316,14 @@
modifyUserState(userId).installReason = installReason;
}
+ int getUninstallReason(int userId) {
+ return readUserState(userId).uninstallReason;
+ }
+
+ void setUninstallReason(@UninstallReason int uninstallReason, int userId) {
+ modifyUserState(userId).uninstallReason = uninstallReason;
+ }
+
void setOverlayPaths(List<String> overlayPaths, int userId) {
modifyUserState(userId).setOverlayPaths(overlayPaths == null ? null :
overlayPaths.toArray(new String[overlayPaths.size()]));
@@ -471,7 +480,7 @@
ArrayMap<String, PackageUserState.SuspendParams> suspendParams, boolean instantApp,
boolean virtualPreload, String lastDisableAppCaller,
ArraySet<String> enabledComponents, ArraySet<String> disabledComponents,
- int domainVerifState, int linkGeneration, int installReason,
+ int domainVerifState, int linkGeneration, int installReason, int uninstallReason,
String harmfulAppWarning) {
PackageUserState state = modifyUserState(userId);
state.ceDataInode = ceDataInode;
@@ -489,6 +498,7 @@
state.domainVerificationStatus = domainVerifState;
state.appLinkGeneration = linkGeneration;
state.installReason = installReason;
+ state.uninstallReason = uninstallReason;
state.instantApp = instantApp;
state.virtualPreload = virtualPreload;
state.harmfulAppWarning = harmfulAppWarning;
@@ -502,7 +512,7 @@
otherState.virtualPreload, otherState.lastDisableAppCaller,
otherState.enabledComponents, otherState.disabledComponents,
otherState.domainVerificationStatus, otherState.appLinkGeneration,
- otherState.installReason, otherState.harmfulAppWarning);
+ otherState.installReason, otherState.uninstallReason, otherState.harmfulAppWarning);
}
ArraySet<String> getEnabledComponents(int userId) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 62541ab..f6ca87d 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -24,6 +24,8 @@
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
+import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
+import static android.content.pm.PackageManager.UNINSTALL_REASON_USER_TYPE;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
@@ -266,6 +268,7 @@
private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
private static final String ATTR_INSTALL_REASON = "install-reason";
+ private static final String ATTR_UNINSTALL_REASON = "uninstall-reason";
private static final String ATTR_INSTANT_APP = "instant-app";
private static final String ATTR_VIRTUAL_PRELOAD = "virtual-preload";
private static final String ATTR_HARMFUL_APP_WARNING = "harmful-app-warning";
@@ -684,7 +687,9 @@
null /*enabledComponents*/,
null /*disabledComponents*/,
INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED,
- 0, PackageManager.INSTALL_REASON_UNKNOWN,
+ 0 /*linkGeneration*/,
+ PackageManager.INSTALL_REASON_UNKNOWN,
+ PackageManager.UNINSTALL_REASON_UNKNOWN,
null /*harmfulAppWarning*/);
}
}
@@ -768,6 +773,7 @@
if (allUserInfos != null) {
for (UserInfo userInfo : allUserInfos) {
pkgSetting.setInstalled(true, userInfo.id);
+ pkgSetting.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userInfo.id);
}
}
}
@@ -1580,7 +1586,9 @@
null /*enabledComponents*/,
null /*disabledComponents*/,
INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED,
- 0, PackageManager.INSTALL_REASON_UNKNOWN,
+ 0 /*linkGeneration*/,
+ PackageManager.INSTALL_REASON_UNKNOWN,
+ PackageManager.UNINSTALL_REASON_UNKNOWN,
null /*harmfulAppWarning*/);
}
return;
@@ -1678,6 +1686,8 @@
}
final int installReason = XmlUtils.readIntAttribute(parser,
ATTR_INSTALL_REASON, PackageManager.INSTALL_REASON_UNKNOWN);
+ final int uninstallReason = XmlUtils.readIntAttribute(parser,
+ ATTR_UNINSTALL_REASON, PackageManager.UNINSTALL_REASON_UNKNOWN);
ArraySet<String> enabledComponents = null;
ArraySet<String> disabledComponents = null;
@@ -1751,7 +1761,7 @@
hidden, distractionFlags, suspended, suspendParamsMap,
instantApp, virtualPreload,
enabledCaller, enabledComponents, disabledComponents, verifState,
- linkGeneration, installReason, harmfulAppWarning);
+ linkGeneration, installReason, uninstallReason, harmfulAppWarning);
} else if (tagName.equals("preferred-activities")) {
readPreferredActivitiesLPw(parser, userId);
} else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
@@ -2079,6 +2089,10 @@
serializer.attribute(null, ATTR_INSTALL_REASON,
Integer.toString(ustate.installReason));
}
+ if (ustate.uninstallReason != PackageManager.UNINSTALL_REASON_UNKNOWN) {
+ serializer.attribute(null, ATTR_UNINSTALL_REASON,
+ Integer.toString(ustate.uninstallReason));
+ }
if (ustate.harmfulAppWarning != null) {
serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
ustate.harmfulAppWarning);
@@ -4126,7 +4140,7 @@
}
void createNewUserLI(@NonNull PackageManagerService service, @NonNull Installer installer,
- @UserIdInt int userHandle, @Nullable Set<String> installablePackages,
+ @UserIdInt int userHandle, @Nullable Set<String> userTypeInstallablePackages,
String[] disallowedPackages) {
final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
Trace.TRACE_TAG_PACKAGE_MANAGER);
@@ -4137,7 +4151,7 @@
String[] seinfos;
int[] targetSdkVersions;
int packagesCount;
- final boolean skipPackageWhitelist = installablePackages == null;
+ final boolean skipPackageWhitelist = userTypeInstallablePackages == null;
synchronized (mLock) {
Collection<PackageSetting> packages = mPackages.values();
packagesCount = packages.size();
@@ -4152,13 +4166,20 @@
if (ps.pkg == null) {
continue;
}
- final boolean shouldInstall = ps.isSystem() &&
- (skipPackageWhitelist || installablePackages.contains(ps.name)) &&
+ final boolean shouldMaybeInstall = ps.isSystem() &&
!ArrayUtils.contains(disallowedPackages, ps.name) &&
!ps.getPkgState().isHiddenUntilInstalled();
+ final boolean shouldReallyInstall = shouldMaybeInstall &&
+ (skipPackageWhitelist || userTypeInstallablePackages.contains(ps.name));
// Only system apps are initially installed.
- ps.setInstalled(shouldInstall, userHandle);
- if (!shouldInstall) {
+ ps.setInstalled(shouldReallyInstall, userHandle);
+ // If userTypeInstallablePackages is the *only* reason why we're not installing,
+ // then uninstallReason is USER_TYPE. If there's a different reason, or if we
+ // actually are installing, put UNKNOWN.
+ final int uninstallReason = (shouldMaybeInstall && !shouldReallyInstall) ?
+ UNINSTALL_REASON_USER_TYPE : UNINSTALL_REASON_UNKNOWN;
+ ps.setUninstallReason(uninstallReason, userHandle);
+ if (!shouldReallyInstall) {
writeKernelMappingLPr(ps);
}
// Need to create a data directory for all apps under this user. Accumulate all
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 342c907..60292b4 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -75,13 +75,11 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Predicate;
-import java.util.stream.Collectors;
/**
* This class handles staged install sessions, i.e. install sessions that require packages to
@@ -222,6 +220,7 @@
// which will be propagated to populate stagedSessionErrorMessage of this session.
final ApexInfoList apexInfoList = mApexManager.submitStagedSession(apexSessionParams);
final List<PackageInfo> result = new ArrayList<>();
+ final List<String> apexPackageNames = new ArrayList<>();
for (ApexInfo apexInfo : apexInfoList.apexInfos) {
final PackageInfo packageInfo;
int flags = PackageManager.GET_META_DATA;
@@ -245,9 +244,10 @@
checkRequiredVersionCode(session, activePackage);
checkDowngrade(session, activePackage, packageInfo);
result.add(packageInfo);
+ apexPackageNames.add(packageInfo.packageName);
}
- Slog.d(TAG, "Session " + session.sessionId + " has following APEX packages: ["
- + result.stream().map(p -> p.packageName).collect(Collectors.joining(",")) + "]");
+ Slog.d(TAG, "Session " + session.sessionId + " has following APEX packages: "
+ + apexPackageNames);
return result;
}
@@ -313,13 +313,16 @@
return filter.test(session);
}
synchronized (mStagedSessions) {
- return !(Arrays.stream(session.getChildSessionIds())
- // Retrieve cached sessions matching ids.
- .mapToObj(i -> mStagedSessions.get(i))
- // Filter only the ones containing APEX.
- .filter(childSession -> filter.test(childSession))
- .collect(Collectors.toList())
- .isEmpty());
+ final int[] childSessionIds = session.getChildSessionIds();
+ for (int id : childSessionIds) {
+ // Retrieve cached sessions matching ids.
+ final PackageInstallerSession s = mStagedSessions.get(id);
+ // Filter only the ones containing APEX.
+ if (filter.test(s)) {
+ return true;
+ }
+ }
+ return false;
}
}
@@ -669,15 +672,15 @@
// contain an APK, and with those then create a new multi-package group of sessions,
// carrying over all the session parameters and unmarking them as staged. On commit the
// sessions will be installed atomically.
- final List<PackageInstallerSession> childSessions;
+ final List<PackageInstallerSession> childSessions = new ArrayList<>();
synchronized (mStagedSessions) {
- childSessions =
- Arrays.stream(session.getChildSessionIds())
- // Retrieve cached sessions matching ids.
- .mapToObj(i -> mStagedSessions.get(i))
- // Filter only the ones containing APKs.
- .filter(childSession -> !isApexSession(childSession))
- .collect(Collectors.toList());
+ final int[] childSessionIds = session.getChildSessionIds();
+ for (int id : childSessionIds) {
+ final PackageInstallerSession s = mStagedSessions.get(id);
+ if (!isApexSession(s)) {
+ childSessions.add(s);
+ }
+ }
}
if (childSessions.isEmpty()) {
// APEX-only multi-package staged session, nothing to do.
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index ef8cad1..d2443fa 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3438,10 +3438,10 @@
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
t.traceEnd();
- final Set<String> installablePackages =
+ final Set<String> userTypeInstallablePackages =
mSystemPackageInstaller.getInstallablePackagesForUserType(userType);
t.traceBegin("PM.createNewUser");
- mPm.createNewUser(userId, installablePackages, disallowedPackages);
+ mPm.createNewUser(userId, userTypeInstallablePackages, disallowedPackages);
t.traceEnd();
userInfo.partial = false;
@@ -3562,8 +3562,10 @@
}
/** Install/uninstall system packages for all users based on their user-type, as applicable. */
- boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade) {
- return mSystemPackageInstaller.installWhitelistedSystemPackages(isFirstBoot, isUpgrade);
+ boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade,
+ @Nullable ArraySet<String> existingPackages) {
+ return mSystemPackageInstaller.installWhitelistedSystemPackages(
+ isFirstBoot, isUpgrade, existingPackages);
}
private long getCreationTime() {
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index d6480d3..85c2306 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.res.Resources;
@@ -74,6 +75,14 @@
* <li>Otherwise, the package is implicitly treated as blacklisted for all users</li>
* </ul>
*
+ * <p>Packages are only installed/uninstalled by this mechanism when a new user is created or during
+ * an update. In the case of updates:<ul>
+ * <li>new packages are (un)installed per the whitelist/blacklist</li>
+ * <li>pre-existing installed blacklisted packages are never uninstalled</li>
+ * <li>pre-existing not-installed whitelisted packages are only installed if the reason why they
+ * had been previously uninstalled was due to UserSystemPackageInstaller</li>
+ * </ul>
+ *
* <p><b>NOTE:</b> the {@code SystemConfig} state is only updated on first boot or after a system
* update. So, to verify changes during development, you can emulate the latter by calling:
* <pre><code>
@@ -171,8 +180,12 @@
*
* This is responsible for enforcing the whitelist for pre-existing users (i.e. USER_SYSTEM);
* enforcement for new users is done when they are created in UserManagerService.createUser().
+ *
+ * @param preExistingPackages list of packages on the device prior to the upgrade. Cannot be
+ * null if isUpgrade is true.
*/
- boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade) {
+ boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade,
+ @Nullable ArraySet<String> preExistingPackages) {
final int mode = getWhitelistMode();
checkWhitelistedSystemPackages(mode);
final boolean isConsideredUpgrade = isUpgrade && !isIgnoreOtaMode(mode);
@@ -198,20 +211,51 @@
final boolean install =
(userWhitelist == null || userWhitelist.contains(pkg.getPackageName()))
&& !pkgSetting.getPkgState().isHiddenUntilInstalled();
- if (isConsideredUpgrade && !isFirstBoot && !install) {
- return; // To be careful, we don’t uninstall apps during OTAs
+ if (pkgSetting.getInstalled(userId) == install
+ || !shouldChangeInstallationState(pkgSetting, install, userId, isFirstBoot,
+ isConsideredUpgrade, preExistingPackages)) {
+ return;
}
- final boolean changed = pmInt.setInstalled(pkg, userId, install);
- if (changed) {
- Slog.i(TAG, (install ? "Installed " : "Uninstalled ")
- + pkg.getPackageName() + " for user " + userId);
- }
+ pkgSetting.setInstalled(install, userId);
+ pkgSetting.setUninstallReason(
+ install ? PackageManager.UNINSTALL_REASON_UNKNOWN :
+ PackageManager.UNINSTALL_REASON_USER_TYPE,
+ userId);
+ Slog.i(TAG, (install ? "Installed " : "Uninstalled ")
+ + pkg.getPackageName() + " for user " + userId);
});
}
return true;
}
/**
+ * Returns whether to proceed with install/uninstall for the given package.
+ * In particular, do not install a package unless it was only uninstalled due to the user type;
+ * and do not uninstall a package if it previously was installed (prior to the OTA).
+ *
+ * Should be called only within PackageManagerInternal.forEachPackageSetting() since it
+ * requires the LP lock.
+ *
+ * @param preOtaPkgs list of packages on the device prior to the upgrade.
+ * Cannot be null if isUpgrade is true.
+ */
+ private static boolean shouldChangeInstallationState(PackageSetting pkgSetting,
+ boolean install,
+ @UserIdInt int userId,
+ boolean isFirstBoot,
+ boolean isUpgrade,
+ @Nullable ArraySet<String> preOtaPkgs) {
+ if (install) {
+ // Only proceed with install if we are the only reason why it had been uninstalled.
+ return pkgSetting.getUninstallReason(userId)
+ == PackageManager.UNINSTALL_REASON_USER_TYPE;
+ } else {
+ // Only proceed with uninstall if the package is new to the device.
+ return isFirstBoot || (isUpgrade && !preOtaPkgs.contains(pkgSetting.name));
+ }
+ }
+
+ /**
* Checks whether the system packages and the mWhitelistedPackagesForUserTypes whitelist are
* in 1-to-1 correspondence.
*/
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 765ecb9..82c02a4 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -3319,47 +3319,51 @@
if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged()
&& !platformPackage && platformPermission) {
if (!hasPrivappWhitelistEntry(perm, pkg)) {
- ApexManager apexMgr = ApexManager.getInstance();
- String apexContainingPkg = apexMgr.getActiveApexPackageNameContainingPackage(pkg);
-
// Only enforce whitelist this on boot
if (!mSystemReady
// Updated system apps do not need to be whitelisted
- && !pkgSetting.getPkgState().isUpdatedSystemApp()
- // Apps that are in updated apexs' do not need to be whitelisted
- && (apexContainingPkg == null || apexMgr.isFactory(
- apexMgr.getPackageInfo(apexContainingPkg, MATCH_ACTIVE_PACKAGE)))) {
- // it's only a reportable violation if the permission isn't explicitly denied
- ArraySet<String> deniedPermissions = null;
- if (pkg.isVendor()) {
- deniedPermissions = SystemConfig.getInstance()
- .getVendorPrivAppDenyPermissions(pkg.getPackageName());
- } else if (pkg.isProduct()) {
- deniedPermissions = SystemConfig.getInstance()
- .getProductPrivAppDenyPermissions(pkg.getPackageName());
- } else if (pkg.isSystemExt()) {
- deniedPermissions = SystemConfig.getInstance()
- .getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
- } else {
- deniedPermissions = SystemConfig.getInstance()
- .getPrivAppDenyPermissions(pkg.getPackageName());
- }
- final boolean permissionViolation =
- deniedPermissions == null || !deniedPermissions.contains(perm);
- if (permissionViolation) {
- Slog.w(TAG, "Privileged permission " + perm + " for package "
- + pkg.getPackageName() + " (" + pkg.getCodePath()
- + ") not in privapp-permissions whitelist");
+ && !pkgSetting.getPkgState().isUpdatedSystemApp()) {
+ ApexManager apexMgr = ApexManager.getInstance();
+ String apexContainingPkg = apexMgr.getActiveApexPackageNameContainingPackage(
+ pkg);
- if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
- if (mPrivappPermissionsViolations == null) {
- mPrivappPermissionsViolations = new ArraySet<>();
- }
- mPrivappPermissionsViolations.add(
- pkg.getPackageName() + " (" + pkg.getCodePath() + "): " + perm);
+ // Apps that are in updated apexs' do not need to be whitelisted
+ if (apexContainingPkg == null || apexMgr.isFactory(
+ apexMgr.getPackageInfo(apexContainingPkg, MATCH_ACTIVE_PACKAGE))) {
+ // it's only a reportable violation if the permission isn't explicitly
+ // denied
+ ArraySet<String> deniedPermissions = null;
+ if (pkg.isVendor()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getVendorPrivAppDenyPermissions(pkg.getPackageName());
+ } else if (pkg.isProduct()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getProductPrivAppDenyPermissions(pkg.getPackageName());
+ } else if (pkg.isSystemExt()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
+ } else {
+ deniedPermissions = SystemConfig.getInstance()
+ .getPrivAppDenyPermissions(pkg.getPackageName());
}
- } else {
- return false;
+ final boolean permissionViolation =
+ deniedPermissions == null || !deniedPermissions.contains(perm);
+ if (permissionViolation) {
+ Slog.w(TAG, "Privileged permission " + perm + " for package "
+ + pkg.getPackageName() + " (" + pkg.getCodePath()
+ + ") not in privapp-permissions whitelist");
+
+ if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
+ if (mPrivappPermissionsViolations == null) {
+ mPrivappPermissionsViolations = new ArraySet<>();
+ }
+ mPrivappPermissionsViolations.add(
+ pkg.getPackageName() + " (" + pkg.getCodePath() + "): "
+ + perm);
+ }
+ } else {
+ return false;
+ }
}
}
if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 1e12565..c973640 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -49,7 +49,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -2091,7 +2090,6 @@
// Window manager does the checking for this.
outAppOp[0] = OP_TOAST_WINDOW;
return ADD_OKAY;
- case TYPE_DREAM:
case TYPE_INPUT_METHOD:
case TYPE_WALLPAPER:
case TYPE_PRESENTATION:
@@ -2230,7 +2228,6 @@
case TYPE_STATUS_BAR:
case TYPE_NAVIGATION_BAR:
case TYPE_WALLPAPER:
- case TYPE_DREAM:
return false;
default:
// Hide only windows below the keyguard host window.
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index efe2af3..7eb3f01 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -31,7 +31,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -806,9 +805,6 @@
return canAddInternalSystemWindow ? 13 : 10;
case TYPE_APPLICATION_OVERLAY:
return 12;
- case TYPE_DREAM:
- // used for Dreams (screensavers with TYPE_DREAM windows)
- return 14;
case TYPE_INPUT_METHOD:
// on-screen keyboards and other such input method user interfaces go here.
return 15;
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 2783d0b..4f4019c 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -107,7 +107,8 @@
private final AtomicBoolean mHalReady = new AtomicBoolean();
/** Watches temperatures to forecast when throttling will occur */
- private final TemperatureWatcher mTemperatureWatcher = new TemperatureWatcher();
+ @VisibleForTesting
+ final TemperatureWatcher mTemperatureWatcher = new TemperatureWatcher();
/** Invalid throttling status */
private static final int INVALID_THROTTLING = Integer.MIN_VALUE;
@@ -1069,16 +1070,19 @@
}
}
- private class TemperatureWatcher {
+ @VisibleForTesting
+ class TemperatureWatcher {
private final Handler mHandler = BackgroundThread.getHandler();
/** Map of skin temperature sensor name to a corresponding list of samples */
@GuardedBy("mSamples")
- private final ArrayMap<String, ArrayList<Sample>> mSamples = new ArrayMap<>();
+ @VisibleForTesting
+ final ArrayMap<String, ArrayList<Sample>> mSamples = new ArrayMap<>();
/** Map of skin temperature sensor name to the corresponding SEVERE temperature threshold */
@GuardedBy("mSamples")
- private ArrayMap<String, Float> mSevereThresholds = new ArrayMap<>();
+ @VisibleForTesting
+ ArrayMap<String, Float> mSevereThresholds = new ArrayMap<>();
@GuardedBy("mSamples")
private long mLastForecastCallTimeMillis = 0;
@@ -1146,7 +1150,8 @@
* Calculates the trend using a linear regression. As the samples are degrees Celsius with
* associated timestamps in milliseconds, the slope is in degrees Celsius per millisecond.
*/
- private float getSlopeOf(List<Sample> samples) {
+ @VisibleForTesting
+ float getSlopeOf(List<Sample> samples) {
long sumTimes = 0L;
float sumTemperatures = 0.0f;
for (int s = 0; s < samples.size(); ++s) {
@@ -1177,7 +1182,8 @@
*/
private static final float DEGREES_BETWEEN_ZERO_AND_ONE = 30.0f;
- private float normalizeTemperature(float temperature, float severeThreshold) {
+ @VisibleForTesting
+ float normalizeTemperature(float temperature, float severeThreshold) {
synchronized (mSamples) {
float zeroNormalized = severeThreshold - DEGREES_BETWEEN_ZERO_AND_ONE;
if (temperature <= zeroNormalized) {
@@ -1245,7 +1251,15 @@
}
}
- private class Sample {
+ @VisibleForTesting
+ // Since Sample is inside an inner class, we can't make it static
+ // This allows test code to create Sample objects via ThermalManagerService
+ Sample createSampleForTesting(long time, float temperature) {
+ return new Sample(time, temperature);
+ }
+
+ @VisibleForTesting
+ class Sample {
public long time;
public float temperature;
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
index 482090a..841aca5 100644
--- a/services/core/java/com/android/server/security/FileIntegrityService.java
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -18,14 +18,19 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.security.IFileIntegrityService;
import android.util.Slog;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import java.io.ByteArrayInputStream;
@@ -58,10 +63,10 @@
}
@Override
- public boolean isAppSourceCertificateTrusted(@Nullable byte[] certificateBytes) {
- enforceAnyCallingPermissions(
- android.Manifest.permission.REQUEST_INSTALL_PACKAGES,
- android.Manifest.permission.INSTALL_PACKAGES);
+ public boolean isAppSourceCertificateTrusted(@Nullable byte[] certificateBytes,
+ @NonNull String packageName) {
+ checkCallerPermission(packageName);
+
try {
if (!isApkVeritySupported()) {
return false;
@@ -77,14 +82,30 @@
}
}
- private void enforceAnyCallingPermissions(String ...permissions) {
- for (String permission : permissions) {
- if (getContext().checkCallingPermission(permission)
- == PackageManager.PERMISSION_GRANTED) {
- return;
- }
+ private void checkCallerPermission(String packageName) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ final PackageManagerInternal packageManager =
+ LocalServices.getService(PackageManagerInternal.class);
+ final int packageUid = packageManager.getPackageUid(
+ packageName, 0 /*flag*/, callingUserId);
+ if (callingUid != packageUid) {
+ throw new SecurityException(
+ "Calling uid " + callingUid + " does not own package " + packageName);
}
- throw new SecurityException("Insufficient permission");
+
+ if (getContext().checkCallingPermission(android.Manifest.permission.INSTALL_PACKAGES)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+
+ final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ final int mode = appOpsManager.checkOpNoThrow(
+ AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, callingUid, packageName);
+ if (mode != AppOpsManager.MODE_ALLOWED) {
+ throw new SecurityException(
+ "Caller should have INSTALL_PACKAGES or REQUEST_INSTALL_PACKAGES");
+ }
}
};
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
index a9e8d3f..06f2d65 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
@@ -108,6 +108,12 @@
public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddlewareService, Dumpable {
private static final String TAG = "SoundTriggerMiddlewareValidation";
+ private enum ModuleState {
+ ALIVE,
+ DETACHED,
+ DEAD
+ };
+
private final @NonNull ISoundTriggerMiddlewareService mDelegate;
private final @NonNull Context mContext;
private Map<Integer, Set<ModuleService>> mModules;
@@ -381,6 +387,7 @@
private ISoundTriggerModule mDelegate;
private @NonNull Map<Integer, ModelState> mLoadedModels = new HashMap<>();
private final int mHandle;
+ private ModuleState mState = ModuleState.ALIVE;
ModuleService(int handle, @NonNull ISoundTriggerCallback callback) {
mCallback = callback;
@@ -406,7 +413,7 @@
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
@@ -430,7 +437,7 @@
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
@@ -453,7 +460,7 @@
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -486,7 +493,7 @@
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -520,7 +527,7 @@
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -549,7 +556,7 @@
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -577,7 +584,7 @@
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -605,7 +612,7 @@
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -634,7 +641,7 @@
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -663,10 +670,10 @@
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has already been detached.");
}
- if (!mLoadedModels.isEmpty()) {
+ if (mState == ModuleState.ALIVE && !mLoadedModels.isEmpty()) {
throw new IllegalStateException("Cannot detach while models are loaded.");
}
@@ -682,13 +689,13 @@
// Override toString() in order to have the delegate's ID in it.
@Override
public String toString() {
- return mDelegate.toString();
+ return Objects.toString(mDelegate.toString());
}
private void detachInternal() {
try {
mDelegate.detach();
- mDelegate = null;
+ mState = ModuleState.DETACHED;
mCallback.asBinder().unlinkToDeath(this, 0);
mModules.get(mHandle).remove(this);
} catch (RemoteException e) {
@@ -697,13 +704,18 @@
}
void dump(PrintWriter pw) {
- pw.printf("Loaded models for session %s (handle, active)", toString());
- pw.println();
- pw.println("-------------------------------");
- for (Map.Entry<Integer, ModelState> entry : mLoadedModels.entrySet()) {
- pw.print(entry.getKey());
- pw.print('\t');
- pw.print(entry.getValue().activityState.name());
+ if (mState == ModuleState.ALIVE) {
+ pw.printf("Loaded models for session %s (handle, active)", toString());
+ pw.println();
+ pw.println("-------------------------------");
+ for (Map.Entry<Integer, ModelState> entry : mLoadedModels.entrySet()) {
+ pw.print(entry.getKey());
+ pw.print('\t');
+ pw.print(entry.getValue().activityState.name());
+ pw.println();
+ }
+ } else {
+ pw.printf("Session %s is dead", toString());
pw.println();
}
}
@@ -762,6 +774,7 @@
public void onModuleDied() {
synchronized (SoundTriggerMiddlewareValidation.this) {
try {
+ mState = ModuleState.DEAD;
mCallback.onModuleDied();
} catch (RemoteException e) {
// Dead client will be handled by binderDied() - no need to handle here.
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 2f814f5..62ec936 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2504,7 +2504,7 @@
final DisplayContent display = stack.getDisplay();
next = display.topRunningActivity();
if (next != null) {
- display.positionStackAtTop(next.getRootTask(),
+ display.mTaskContainers.positionStackAtTop(next.getRootTask(),
false /* includingParents */, "finish-display-top");
}
}
@@ -2679,7 +2679,7 @@
final ActivityRecord next = display.topRunningActivity();
final boolean isLastStackOverEmptyHome =
next == null && stack.isFocusedStackOnDisplay()
- && display.getOrCreateRootHomeTask() != null;
+ && display.mTaskContainers.getOrCreateRootHomeTask() != null;
if (isLastStackOverEmptyHome) {
// Don't destroy activity immediately if this is the last activity on the display and
// the display contains home stack. Although there is no next activity at the moment,
@@ -3160,7 +3160,7 @@
}
// Reset the last saved PiP snap fraction on removal.
- mDisplayContent.mPinnedStackControllerLocked.resetReentryBounds(mActivityComponent);
+ mDisplayContent.mPinnedStackControllerLocked.onActivityHidden(mActivityComponent);
mWmService.mEmbeddedWindowController.onActivityRemoved(this);
mRemovingFromDisplay = false;
}
@@ -4426,7 +4426,7 @@
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
mAppStopped = true;
// Reset the last saved PiP snap fraction on app stop.
- mDisplayContent.mPinnedStackControllerLocked.resetReentryBounds(mActivityComponent);
+ mDisplayContent.mPinnedStackControllerLocked.onActivityHidden(mActivityComponent);
destroySurfaces();
// Remove any starting window that was added for this app if they are still around.
removeStartingWindow();
@@ -4477,7 +4477,7 @@
// case where this is the top activity in a pinned stack.
final boolean isTop = this == stack.getTopNonFinishingActivity();
final boolean isTopNotPinnedStack = stack.isAttached()
- && stack.getDisplay().isTopNotPinnedStack(stack);
+ && stack.getDisplay().mTaskContainers.isTopNotPinnedStack(stack);
final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
@@ -5201,7 +5201,7 @@
}
finishLaunchTickingLocked();
if (task != null) {
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
}
}
@@ -6651,17 +6651,6 @@
}
}
- void savePinnedStackBounds() {
- // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
- // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
- final ActivityStack pinnedStack = mDisplayContent.getRootPinnedTask();
- if (pinnedStack == null) return;
- final Rect stackBounds = mTmpRect;
- pinnedStack.getBounds(stackBounds);
- mDisplayContent.mPinnedStackControllerLocked.saveReentryBounds(
- mActivityComponent, stackBounds);
- }
-
/** Returns true if the configuration is compatible with this activity. */
boolean isConfigurationCompatible(Configuration config) {
final int orientation = getRequestedOrientation();
@@ -7389,7 +7378,7 @@
*/
boolean isResumedActivityOnDisplay() {
final DisplayContent display = getDisplay();
- return display != null && this == display.getResumedActivity();
+ return display != null && this == display.mTaskContainers.getResumedActivity();
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 9089859..9815d6d 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -670,7 +670,7 @@
// Since always on top is only on when the stack is freeform or pinned, the state
// can be toggled when the windowing mode changes. We must make sure the stack is
// placed properly when always on top state changes.
- display.positionStackAtTop(this, false /* includingParents */);
+ display.mTaskContainers.positionStackAtTop(this, false /* includingParents */);
}
}
@@ -742,7 +742,7 @@
// Need to make sure windowing mode is supported. If we in the process of creating the stack
// no need to resolve the windowing mode again as it is already resolved to the right mode.
if (!creating) {
- windowingMode = display.validateWindowingMode(windowingMode,
+ windowingMode = display.mTaskContainers.validateWindowingMode(windowingMode,
null /* ActivityRecord */, topTask, getActivityType());
}
if (display.getRootSplitScreenPrimaryTask() == this
@@ -752,7 +752,8 @@
windowingMode = mRestoreOverrideWindowingMode;
}
- final boolean alreadyInSplitScreenMode = display.isSplitScreenModeActivated();
+ final boolean alreadyInSplitScreenMode = display.mTaskContainers
+ .isSplitScreenModeActivated();
// Don't send non-resizeable notifications if the windowing mode changed was a side effect
// of us entering split-screen mode.
@@ -769,7 +770,7 @@
// warning toast about it.
mAtmService.getTaskChangeNotificationController()
.notifyActivityDismissingDockedStack();
- display.onSplitScreenModeDismissed();
+ display.mTaskContainers.onSplitScreenModeDismissed();
}
}
@@ -861,7 +862,7 @@
// TODO (b/78247419): Fix the rotation animation from fullscreen to minimized mode
final boolean isRecentsComponentHome =
mAtmService.getRecentTasks().isRecentsComponentHomeActivity(mCurrentUser);
- final ActivityStack recentStack = display.getOrCreateStack(
+ final ActivityStack recentStack = display.mTaskContainers.getOrCreateStack(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
isRecentsComponentHome ? ACTIVITY_TYPE_HOME : ACTIVITY_TYPE_RECENTS,
true /* onTop */);
@@ -1058,7 +1059,7 @@
// cutting between them.
// TODO(b/70677280): This is a workaround until we can fix as part of b/70677280.
final ActivityStack topFullScreenStack =
- display.getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ display.mTaskContainers.getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
if (topFullScreenStack != null) {
final ActivityStack primarySplitScreenStack = display.getRootSplitScreenPrimaryTask();
if (primarySplitScreenStack != null && display.getIndexOf(topFullScreenStack)
@@ -1071,11 +1072,11 @@
if (!isActivityTypeHome() && returnsToHomeStack()) {
// Make sure the home stack is behind this stack since that is where we should return to
// when this stack is no longer visible.
- display.moveHomeStackToFront(reason + " returnToHome");
+ display.mTaskContainers.moveHomeStackToFront(reason + " returnToHome");
}
if (isRootTask()) {
- display.positionStackAtTop(this, false /* includingParents */, reason);
+ display.mTaskContainers.positionStackAtTop(this, false /* includingParents */, reason);
}
if (task == null) {
task = this;
@@ -1092,7 +1093,7 @@
return;
}
- getDisplay().positionStackAtBottom(this, reason);
+ getDisplay().mTaskContainers.positionStackAtBottom(this, reason);
if (task != null && task != this) {
positionChildAtBottom(task);
}
@@ -1460,7 +1461,7 @@
boolean isTopStackOnDisplay() {
final DisplayContent display = getDisplay();
- return display != null && display.isTopStack(this);
+ return display != null && display.mTaskContainers.isTopStack(this);
}
/**
@@ -1667,7 +1668,8 @@
*/
boolean isTopSplitScreenStack() {
return inSplitScreenWindowingMode()
- && this == getDisplay().getTopStackInWindowingMode(getWindowingMode());
+ && this == getDisplay().mTaskContainers
+ .getTopStackInWindowingMode(getWindowingMode());
}
/** @return True if the resizing of the primary-split-screen stack affects this stack size. */
@@ -1900,7 +1902,7 @@
// If the top activity is the resumed one, nothing to do.
if (mResumedActivity == next && next.isState(RESUMED)
- && display.allResumedActivitiesComplete()) {
+ && display.mTaskContainers.allResumedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
@@ -1979,7 +1981,7 @@
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
ActivityRecord lastResumed = null;
- final ActivityStack lastFocusedStack = display.getLastFocusedStack();
+ final ActivityStack lastFocusedStack = display.mTaskContainers.getLastFocusedStack();
if (lastFocusedStack != null && lastFocusedStack != this) {
// So, why aren't we using prev here??? See the param comment on the method. prev doesn't
// represent the last resumed activity. However, the last focus stack does if it isn't null.
@@ -1993,7 +1995,7 @@
}
}
- boolean pausing = display.pauseBackStacks(userLeaving, next);
+ boolean pausing = display.mTaskContainers.pauseBackStacks(userLeaving, next);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
@@ -2022,7 +2024,7 @@
}
return true;
} else if (mResumedActivity == next && next.isState(RESUMED)
- && display.allResumedActivitiesComplete()) {
+ && display.mTaskContainers.allResumedActivitiesComplete()) {
// It is possible for the activity to be resumed when we paused back stacks above if the
// next activity doesn't have to wait for pause to complete.
// So, nothing else to-do except:
@@ -2542,7 +2544,7 @@
if (stack.isActivityTypeHome() && (top == null || !top.mVisibleRequested)) {
// If we will be focusing on the home stack next and its current top activity isn't
// visible, then use the move the home stack task to top to make the activity visible.
- stack.getDisplay().moveHomeActivityToTop(reason);
+ stack.getDisplay().mTaskContainers.moveHomeActivityToTop(reason);
return stack;
}
@@ -3304,7 +3306,7 @@
final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity;
boolean toTop = position >= getChildCount();
- boolean includingParents = toTop || getDisplay().getNextFocusableStack(this,
+ boolean includingParents = toTop || getDisplay().mTaskContainers.getNextFocusableStack(this,
true /* ignoreCurrent */) == null;
if (WindowManagerDebugConfig.DEBUG_STACK) {
Slog.i(TAG_WM, "positionChildAt: positioning task=" + task + " at " + position);
@@ -3348,7 +3350,7 @@
// always on top windows. Since the position the stack should be inserted into is calculated
// properly in {@link DisplayContent#getTopInsertPosition()} in both cases, we can just
// request that the stack is put at top here.
- display.positionStackAtTop(this, false /* includingParents */);
+ display.mTaskContainers.positionStackAtTop(this, false /* includingParents */);
}
/** NOTE: Should only be called from {@link Task#reparent}. */
@@ -3389,17 +3391,11 @@
"Can't exit pinned mode if it's not pinned already.");
}
- // give pinned stack a chance to save current bounds, this should happen before reparent.
- final ActivityRecord top = topRunningNonOverlayTaskActivity();
- if (top != null && top.isVisible()) {
- top.savePinnedStackBounds();
- }
-
mWmService.inSurfaceTransaction(() -> {
final Task task = getBottomMostTask();
setWindowingMode(WINDOWING_MODE_UNDEFINED);
- getDisplay().positionStackAtTop(this, false /* includingParents */);
+ getDisplay().mTaskContainers.positionStackAtTop(this, false /* includingParents */);
mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, this);
MetricsLoggerWrapper.logPictureInPictureFullScreen(mAtmService.mContext,
@@ -3519,7 +3515,7 @@
// If there are other focusable stacks on the display, the z-order of the display should not
// be changed just because a task was placed at the bottom. E.g. if it is moving the topmost
// task to bottom, the next focusable stack on the same display should be focused.
- final ActivityStack nextFocusableStack = getDisplay().getNextFocusableStack(
+ final ActivityStack nextFocusableStack = getDisplay().mTaskContainers.getNextFocusableStack(
child.getStack(), true /* ignoreCurrent */);
positionChildAtBottom(child, nextFocusableStack == null /* includingParents */);
child.updateTaskMovement(true);
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 4652f49..aed1d95 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -414,14 +414,15 @@
if (mToDisplay.getDisplayId() != stack.getDisplayId()) {
mToDisplay.moveStackToDisplay(stack, mOnTop);
} else if (mOnTop) {
- mToDisplay.positionStackAtTop(stack, false /* includingParents */);
+ mToDisplay.mTaskContainers.positionStackAtTop(stack,
+ false /* includingParents */);
} else {
- mToDisplay.positionStackAtBottom(stack);
+ mToDisplay.mTaskContainers.positionStackAtBottom(stack);
}
return;
}
- final ActivityStack toStack = mToDisplay.getOrCreateStack(
+ final ActivityStack toStack = mToDisplay.mTaskContainers.getOrCreateStack(
null, mTmpOptions, task, task.getActivityType(), mOnTop);
if (task == toStack) {
// The task was reused as the root task.
@@ -1458,7 +1459,7 @@
|| (focusedStack != null && focusedStack.isActivityTypeRecents())) {
// We move home stack to front when we are on a fullscreen display and caller has
// requested the home activity to move with it. Or the previous stack is recents.
- display.moveHomeStackToFront(reason);
+ display.mTaskContainers.moveHomeStackToFront(reason);
}
}
@@ -1877,7 +1878,7 @@
mStoppingActivities.remove(r);
final ActivityStack stack = r.getRootTask();
- if (stack.getDisplay().allResumedActivitiesComplete()) {
+ if (stack.getDisplay().mTaskContainers.allResumedActivitiesComplete()) {
mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
// Make sure activity & window visibility should be identical
// for all displays in this stage.
@@ -2008,6 +2009,8 @@
pw.println();
pw.println("ActivityStackSupervisor state:");
mRootWindowContainer.dump(pw, prefix);
+ getKeyguardController().dump(pw, prefix);
+ mService.getLockTaskController().dump(pw, prefix);
pw.print(prefix);
pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser);
pw.println(prefix + "mUserStackInFront=" + mRootWindowContainer.mUserStackInFront);
@@ -2018,10 +2021,8 @@
}
}
pw.print(prefix); pw.print("isHomeRecentsComponent=");
- pw.print(mRecentTasks.isRecentsComponentHomeActivity(mRootWindowContainer.mCurrentUser));
-
- getKeyguardController().dump(pw, prefix);
- mService.getLockTaskController().dump(pw, prefix);
+ pw.println(mRecentTasks.isRecentsComponentHomeActivity(mRootWindowContainer.mCurrentUser));
+ pw.println();
}
static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
@@ -2241,7 +2242,7 @@
final boolean isSecondaryDisplayPreferred =
(preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY);
final boolean inSplitScreenMode = actualStack != null
- && actualStack.getDisplay().isSplitScreenModeActivated();
+ && actualStack.getDisplay().mTaskContainers.isSplitScreenModeActivated();
if (((!inSplitScreenMode && preferredWindowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
&& !isSecondaryDisplayPreferred) || !task.isActivityTypeStandardOrUndefined()) {
return;
@@ -2289,12 +2290,12 @@
// Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
// we need to move it to top of fullscreen stack, otherwise it will be covered.
final DisplayContent display = task.getStack().getDisplay();
- if (display.isSplitScreenModeActivated()) {
+ if (display.mTaskContainers.isSplitScreenModeActivated()) {
// Display a warning toast that we tried to put an app that doesn't support
// split-screen in split-screen.
mService.getTaskChangeNotificationController()
.notifyActivityDismissingDockedStack();
- display.onSplitScreenModeDismissed();
+ display.mTaskContainers.onSplitScreenModeDismissed();
display.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS,
true /* notifyClients */);
}
@@ -2612,7 +2613,7 @@
// from whatever is started from the recents activity, so move the home stack
// forward.
// TODO (b/115289124): Multi-display supports for recents.
- mRootWindowContainer.getDefaultDisplay().moveHomeStackToFront(
+ mRootWindowContainer.getDefaultDisplay().mTaskContainers.moveHomeStackToFront(
"startActivityFromRecents");
}
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 881dc81..0a0049d 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -190,8 +190,8 @@
final ActivityStack homeStack;
try {
// Make sure home stack exist on display.
- homeStack = display.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME,
- ON_TOP);
+ homeStack = display.mTaskContainers.getOrCreateStack(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_HOME, ON_TOP);
} finally {
mSupervisor.endDeferResume();
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index bf92542..7e999c6 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2357,7 +2357,7 @@
}
// Convert some windowing-mode changes into root-task reparents for split-screen.
if (stack.inSplitScreenWindowingMode()) {
- stack.getDisplay().onSplitScreenModeDismissed();
+ stack.getDisplay().mTaskContainers.onSplitScreenModeDismissed();
} else {
stack.setWindowingMode(windowingMode);
@@ -2775,7 +2775,8 @@
}
if (toTop) {
- display.positionStackAt(POSITION_TOP, primarySplitTask, false /* includingParents */);
+ display.mTaskContainers.positionStackAt(POSITION_TOP, primarySplitTask,
+ false /* includingParents */);
}
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reparent(task.getStack().mRemoteToken, primarySplitTask.mRemoteToken, toTop);
@@ -3244,8 +3245,8 @@
}
final ActivityStack stack = r.getRootTask();
- final Task task = stack.getDisplay().createStack(stack.getWindowingMode(),
- stack.getActivityType(), !ON_TOP, ainfo, intent,
+ final Task task = stack.getDisplay().mTaskContainers.createStack(
+ stack.getWindowingMode(), stack.getActivityType(), !ON_TOP, ainfo, intent,
false /* createdByOrganizer */);
if (!mRecentTasks.addToBottom(task)) {
@@ -3308,10 +3309,10 @@
throw new IllegalArgumentException("resizeTask not allowed on task=" + task);
}
if (bounds == null && stack.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
- stack = stack.getDisplay().getOrCreateStack(
+ stack = stack.getDisplay().mTaskContainers.getOrCreateStack(
WINDOWING_MODE_FULLSCREEN, stack.getActivityType(), ON_TOP);
} else if (bounds != null && stack.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
- stack = stack.getDisplay().getOrCreateStack(
+ stack = stack.getDisplay().mTaskContainers.getOrCreateStack(
WINDOWING_MODE_FREEFORM, stack.getActivityType(), ON_TOP);
}
@@ -3986,35 +3987,6 @@
}
}
- /**
- * Dismisses Pip
- * @param animate True if the dismissal should be animated.
- * @param animationDuration The duration of the resize animation in milliseconds or -1 if the
- * default animation duration should be used.
- */
- @Override
- public void dismissPip(boolean animate, int animationDuration) {
- enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()");
- final long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mGlobalLock) {
- final ActivityStack stack =
- mRootWindowContainer.getDefaultDisplay().getRootPinnedTask();
- if (stack == null) {
- Slog.w(TAG, "dismissPip: pinned stack not found.");
- return;
- }
- if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
- throw new IllegalArgumentException("Stack: " + stack
- + " doesn't support animated resize.");
- }
- stack.dismissPip();
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
@Override
public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()");
@@ -5006,6 +4978,7 @@
}
printedAnything = true;
mStackSupervisor.dump(pw, " ");
+ mTaskOrganizerController.dump(pw, " ");
}
if (!printedAnything) {
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
index 0ec0c7b..3c083e1 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
@@ -19,8 +19,6 @@
import android.content.res.Resources;
import android.text.TextUtils;
-import com.android.server.wm.DisplayContent.TaskContainers;
-
/**
* Policy that manages DisplayAreas.
*/
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 88c9b2c..4a7edee 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -17,23 +17,17 @@
package com.android.server.wm;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-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.app.WindowConfiguration.isSplitScreenWindowingMode;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -67,7 +61,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -79,17 +72,12 @@
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
-import static android.window.WindowOrganizer.DisplayAreaOrganizer.FEATURE_TASK_CONTAINER;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
-import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
import static com.android.server.wm.DisplayContentProto.APP_TRANSITION;
import static com.android.server.wm.DisplayContentProto.CLOSING_APPS;
@@ -108,14 +96,12 @@
import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
-import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.DISPLAY_CONTENT;
@@ -155,13 +141,9 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.ActivityOptions;
-import android.app.WindowConfiguration;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
-import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
@@ -216,7 +198,6 @@
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManagerPolicyConstants.PointerEventListener;
-import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
@@ -289,7 +270,7 @@
/** The containers below are the only child containers {@link #mWindowContainers} can have. */
// Contains all window containers that are related to apps (Activities)
- private final TaskContainers mTaskContainers = new TaskContainers(mWmService);
+ final TaskContainers mTaskContainers = new TaskContainers(this, mWmService);
// Contains all IME window containers. Note that the z-ordering of the IME windows will depend
// on the IME target. We mainly have this container grouping so we can keep track of all the IME
@@ -456,8 +437,6 @@
private final Configuration mTmpConfiguration = new Configuration();
- private ArrayList<Task> mTmpTasks = new ArrayList<>();
-
/** Remove this display when animation on it has completed. */
private boolean mDeferredRemoval;
@@ -579,10 +558,6 @@
// Last systemUiVisibility we dispatched to windows.
private int mLastDispatchedSystemUiVisibility = 0;
- private final ArrayList<ActivityStack> mTmpAlwaysOnTopStacks = new ArrayList<>();
- private final ArrayList<ActivityStack> mTmpNormalStacks = new ArrayList<>();
- private final ArrayList<ActivityStack> mTmpHomeStacks = new ArrayList<>();
-
/** Corner radius that windows should have in order to match the display. */
private final float mWindowCornerRadius;
@@ -624,7 +599,7 @@
private boolean mRemoved;
/** The display can only contain one task. */
- private boolean mSingleTaskInstance;
+ boolean mSingleTaskInstance;
/**
* Non-null if the last size compatibility mode activity is using non-native screen
@@ -640,13 +615,6 @@
*/
private ActivityStack mPreferredTopFocusableStack;
- /**
- * If this is the same as {@link #getFocusedStack} then the activity on the top of the focused
- * stack has been resumed. If stacks are changing position this will hold the old stack until
- * the new stack becomes resumed after which it will be set to current focused stack.
- */
- private ActivityStack mLastFocusedStack;
-
// Used in updating the display size
private Point mTmpDisplaySize = new Point();
@@ -766,11 +734,6 @@
if (mTmpInitial) {
w.resetContentChanged();
}
- if (w.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it does stuff like hide
- // the status bar we won't get a bad transition when it goes away.
- mTmpWindow = w;
- }
w.mLayoutNeeded = false;
w.prelayout();
final boolean firstLayout = !w.isLaidOut();
@@ -824,10 +787,6 @@
+ " mContainingFrame=" + w.getContainingFrame()
+ " mDisplayFrame=" + w.getDisplayFrameLw());
}
- } else if (w.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it does stuff like hide the
- // status bar we won't get a bad transition when it goes away.
- mTmpWindow = mTmpWindow2;
}
};
@@ -911,17 +870,6 @@
// Take care of the window being ready to display.
final boolean committed = winAnimator.commitFinishDrawingLocked();
if (isDefaultDisplay && committed) {
- if (w.mAttrs.type == TYPE_DREAM) {
- // HACK: When a dream is shown, it may at that point hide the lock screen.
- // So we need to redo the layout to let the phone window manager make this
- // happen.
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS) {
- surfacePlacer.debugLayoutRepeats(
- "dream and commitFinishDrawingLocked true",
- pendingLayoutChanges);
- }
- }
if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
"First draw done in potential wallpaper target " + w);
@@ -2123,30 +2071,11 @@
return mTaskContainers.getRootHomeTask();
}
- /**
- * Returns the existing home stack or creates and returns a new one if it should exist for the
- * display.
- */
- @Nullable
- ActivityStack getOrCreateRootHomeTask() {
- ActivityStack homeTask = getRootHomeTask();
- if (homeTask == null && supportsSystemDecorations() && !isUntrustedVirtualDisplay()) {
- homeTask = createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME,
- false /* onTop */);
- }
- return homeTask;
- }
-
/** @return The primary split-screen task, and {@code null} otherwise. */
@Nullable ActivityStack getRootSplitScreenPrimaryTask() {
return mTaskContainers.getRootSplitScreenPrimaryTask();
}
- boolean isSplitScreenModeActivated() {
- Task task = getRootSplitScreenPrimaryTask();
- return task != null && task.hasChild();
- }
-
ActivityStack getRootPinnedTask() {
return mTaskContainers.getRootPinnedTask();
}
@@ -2156,14 +2085,6 @@
}
/**
- * Returns the topmost stack on the display that is compatible with the input windowing mode.
- * Null is no compatible stack on the display.
- */
- ActivityStack getTopStackInWindowingMode(int windowingMode) {
- return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED);
- }
-
- /**
* Returns the topmost stack on the display that is compatible with the input windowing mode and
* activity type. Null is no compatible stack on the display.
*/
@@ -2539,11 +2460,6 @@
positionDisplayAt(position, includingParents);
}
- void positionStackAt(int position, ActivityStack child, boolean includingParents) {
- mTaskContainers.positionChildAt(position, child, includingParents);
- layoutAndAssignWindowLayersIfNeeded();
- }
-
/**
* Returns true if the input point is within an app window.
*/
@@ -2611,7 +2527,7 @@
}
amendWindowTapExcludeRegion(mTouchExcludeRegion);
// TODO(multi-display): Support docked stacks on secondary displays.
- if (mDisplayId == DEFAULT_DISPLAY && isSplitScreenModeActivated()) {
+ if (mDisplayId == DEFAULT_DISPLAY && mTaskContainers.isSplitScreenModeActivated()) {
mDividerControllerLocked.getTouchRegion(mTmpRect);
mTmpRegion.set(mTmpRect);
mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
@@ -2875,7 +2791,8 @@
final ActivityStack focusedStack = getFocusedStack();
if (focusedStack != null) {
proto.write(FOCUSED_ROOT_TASK_ID, focusedStack.getRootTaskId());
- final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
+ final ActivityRecord focusedActivity = focusedStack.getDisplay().mTaskContainers
+ .getResumedActivity();
if (focusedActivity != null) {
focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
}
@@ -2936,8 +2853,8 @@
if (mPreferredTopFocusableStack != null) {
pw.println(prefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack);
}
- if (mLastFocusedStack != null) {
- pw.println(prefix + "mLastFocusedStack=" + mLastFocusedStack);
+ if (mTaskContainers.mLastFocusedStack != null) {
+ pw.println(prefix + "mLastFocusedStack=" + mTaskContainers.mLastFocusedStack);
}
if (mLosingFocus.size() > 0) {
pw.println();
@@ -3021,6 +2938,11 @@
if (recentsStack != null) {
pw.println(prefix + "recentsStack=" + recentsStack.getName());
}
+ final ActivityStack dreamStack =
+ getStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_DREAM);
+ if (dreamStack != null) {
+ pw.println(prefix + "dreamStack=" + dreamStack.getName());
+ }
pw.println();
mPinnedStackControllerLocked.dump(prefix, pw);
@@ -3048,7 +2970,7 @@
/** Returns true if the stack in the windowing mode is visible. */
boolean isStackVisible(int windowingMode) {
- final ActivityStack stack = getTopStackInWindowingMode(windowingMode);
+ final ActivityStack stack = mTaskContainers.getTopStackInWindowingMode(windowingMode);
return stack != null && stack.isVisible();
}
@@ -4275,531 +4197,6 @@
}
}
- /**
- * Window container class that contains all containers on this display relating to Apps.
- * I.e Activities.
- */
- final class TaskContainers extends DisplayArea<ActivityStack> {
- /**
- * A control placed at the appropriate level for transitions to occur.
- */
- SurfaceControl mAppAnimationLayer = null;
- SurfaceControl mBoostedAppAnimationLayer = null;
- SurfaceControl mHomeAppAnimationLayer = null;
-
- /**
- * Given that the split-screen divider does not have an AppWindowToken, it
- * will have to live inside of a "NonAppWindowContainer". However, in visual Z order
- * it will need to be interleaved with some of our children, appearing on top of
- * both docked stacks but underneath any assistant stacks.
- *
- * To solve this problem we have this anchor control, which will always exist so
- * we can always assign it the correct value in our {@link #assignChildLayers}.
- * Likewise since it always exists, we can always
- * assign the divider a layer relative to it. This way we prevent linking lifecycle
- * events between tasks and the divider window.
- */
- SurfaceControl mSplitScreenDividerAnchor = null;
-
- // Cached reference to some special tasks we tend to get a lot so we don't need to loop
- // through the list to find them.
- private ActivityStack mRootHomeTask = null;
- private ActivityStack mRootPinnedTask = null;
- private ActivityStack mRootSplitScreenPrimaryTask = null;
-
- TaskContainers(WindowManagerService service) {
- super(service, Type.ANY, "TaskContainers", FEATURE_TASK_CONTAINER);
- }
-
- /**
- * Returns the topmost stack on the display that is compatible with the input windowing mode
- * and activity type. Null is no compatible stack on the display.
- */
- ActivityStack getStack(int windowingMode, int activityType) {
- if (activityType == ACTIVITY_TYPE_HOME) {
- return mRootHomeTask;
- }
- if (windowingMode == WINDOWING_MODE_PINNED) {
- return mRootPinnedTask;
- } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- return mRootSplitScreenPrimaryTask;
- }
- for (int i = mTaskContainers.getChildCount() - 1; i >= 0; --i) {
- final ActivityStack stack = mTaskContainers.getChildAt(i);
- if (activityType == ACTIVITY_TYPE_UNDEFINED
- && windowingMode == stack.getWindowingMode()) {
- // Passing in undefined type means we want to match the topmost stack with the
- // windowing mode.
- return stack;
- }
- if (stack.isCompatible(windowingMode, activityType)) {
- return stack;
- }
- }
- return null;
- }
-
- @VisibleForTesting
- ActivityStack getTopStack() {
- final int count = mTaskContainers.getChildCount();
- return count > 0 ? mTaskContainers.getChildAt(count - 1) : null;
- }
-
- int getIndexOf(ActivityStack stack) {
- return mTaskContainers.mChildren.indexOf(stack);
- }
-
- ActivityStack getRootHomeTask() {
- return mRootHomeTask;
- }
-
- ActivityStack getRootPinnedTask() {
- return mRootPinnedTask;
- }
-
- ActivityStack getRootSplitScreenPrimaryTask() {
- return mRootSplitScreenPrimaryTask;
- }
-
- ArrayList<Task> getVisibleTasks() {
- final ArrayList<Task> visibleTasks = new ArrayList<>();
- forAllTasks(task -> {
- if (task.isLeafTask() && task.isVisible()) {
- visibleTasks.add(task);
- }
- });
- return visibleTasks;
- }
-
- void onStackWindowingModeChanged(ActivityStack stack) {
- removeStackReferenceIfNeeded(stack);
- addStackReferenceIfNeeded(stack);
- if (stack == mRootPinnedTask && getTopStack() != stack) {
- // Looks like this stack changed windowing mode to pinned. Move it to the top.
- positionChildAt(POSITION_TOP, stack, false /* includingParents */);
- }
- }
-
- private void addStackReferenceIfNeeded(ActivityStack stack) {
- if (stack.isActivityTypeHome()) {
- if (mRootHomeTask != null) {
- if (!stack.isDescendantOf(mRootHomeTask)) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
- + mRootHomeTask + " already exist on display=" + this
- + " stack=" + stack);
- }
- } else {
- mRootHomeTask = stack;
- }
- }
-
- if (!stack.isRootTask()) {
- return;
- }
- final int windowingMode = stack.getWindowingMode();
- if (windowingMode == WINDOWING_MODE_PINNED) {
- if (mRootPinnedTask != null) {
- throw new IllegalArgumentException(
- "addStackReferenceIfNeeded: pinned stack=" + mRootPinnedTask
- + " already exist on display=" + this + " stack=" + stack);
- }
- mRootPinnedTask = stack;
- } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- if (mRootSplitScreenPrimaryTask != null) {
- throw new IllegalArgumentException(
- "addStackReferenceIfNeeded: split screen primary stack="
- + mRootSplitScreenPrimaryTask
- + " already exist on display=" + this + " stack=" + stack);
- }
- mRootSplitScreenPrimaryTask = stack;
- }
- }
-
- void removeStackReferenceIfNeeded(ActivityStack stack) {
- if (stack == mRootHomeTask) {
- mRootHomeTask = null;
- } else if (stack == mRootPinnedTask) {
- mRootPinnedTask = null;
- } else if (stack == mRootSplitScreenPrimaryTask) {
- mRootSplitScreenPrimaryTask = null;
- }
- }
-
- @Override
- void addChild(ActivityStack stack, int position) {
- addStackReferenceIfNeeded(stack);
- position = findPositionForStack(position, stack, true /* adding */);
-
- super.addChild(stack, position);
- mAtmService.updateSleepIfNeededLocked();
-
- // The reparenting case is handled in WindowContainer.
- if (!stack.mReparenting) {
- setLayoutNeeded();
- }
- }
-
- @Override
- protected void removeChild(ActivityStack stack) {
- super.removeChild(stack);
- mDisplayContent.onStackRemoved(stack);
- mAtmService.updateSleepIfNeededLocked();
- removeStackReferenceIfNeeded(stack);
- }
-
- @Override
- boolean isOnTop() {
- // Considered always on top
- return true;
- }
-
- @Override
- void positionChildAt(int position, ActivityStack child, boolean includingParents) {
- final boolean moveToTop = (position == POSITION_TOP || position == getChildCount());
- final boolean moveToBottom = (position == POSITION_BOTTOM || position == 0);
- if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) {
- // This stack is always-on-top, override the default behavior.
- Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
-
- // Moving to its current position, as we must call super but we don't want to
- // perform any meaningful action.
- final int currentPosition = mChildren.indexOf(child);
- super.positionChildAt(currentPosition, child, false /* includingParents */);
- return;
- }
- // We don't allow untrusted display to top when task stack moves to top,
- // until user tapping this display to change display position as top intentionally.
- if (isUntrustedVirtualDisplay() && !getParent().isOnTop()) {
- includingParents = false;
- }
- final int targetPosition = findPositionForStack(position, child, false /* adding */);
- super.positionChildAt(targetPosition, child, false /* includingParents */);
-
- if (includingParents && (moveToTop || moveToBottom)) {
- // The DisplayContent children do not re-order, but we still want to move the
- // display of this stack container because the intention of positioning is to have
- // higher z-order to gain focus.
- positionDisplayAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM,
- true /* includingParents */);
- }
-
- child.updateTaskMovement(moveToTop);
-
- setLayoutNeeded();
- }
-
- /**
- * When stack is added or repositioned, find a proper position for it.
- * This will make sure that pinned stack always stays on top.
- * @param requestedPosition Position requested by caller.
- * @param stack Stack to be added or positioned.
- * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
- * @return The proper position for the stack.
- */
- private int findPositionForStack(int requestedPosition, ActivityStack stack,
- boolean adding) {
- if (stack.isActivityTypeDream()) {
- return POSITION_TOP;
- }
-
- if (stack.inPinnedWindowingMode()) {
- return POSITION_TOP;
- }
-
- final int topChildPosition = mChildren.size() - 1;
- int belowAlwaysOnTopPosition = POSITION_BOTTOM;
- for (int i = topChildPosition; i >= 0; --i) {
- // Since a stack could be repositioned while being one of the child, return
- // current index if that's the same stack we are positioning and it is always on
- // top.
- final boolean sameStack = getStacks().get(i) == stack;
- if ((sameStack && stack.isAlwaysOnTop())
- || (!sameStack && !getStacks().get(i).isAlwaysOnTop())) {
- belowAlwaysOnTopPosition = i;
- break;
- }
- }
-
- // The max possible position we can insert the stack at.
- int maxPosition = POSITION_TOP;
- // The min possible position we can insert the stack at.
- int minPosition = POSITION_BOTTOM;
-
- if (stack.isAlwaysOnTop()) {
- if (hasPinnedTask()) {
- // Always-on-top stacks go below the pinned stack.
- maxPosition = getStacks().indexOf(mRootPinnedTask) - 1;
- }
- // Always-on-top stacks need to be above all other stacks.
- minPosition = belowAlwaysOnTopPosition !=
- POSITION_BOTTOM ? belowAlwaysOnTopPosition : topChildPosition;
- } else {
- // Other stacks need to be below the always-on-top stacks.
- maxPosition = belowAlwaysOnTopPosition !=
- POSITION_BOTTOM ? belowAlwaysOnTopPosition : 0;
- }
-
- // Cap the requested position to something reasonable for the previous position check
- // below.
- if (requestedPosition == POSITION_TOP) {
- requestedPosition = mChildren.size();
- } else if (requestedPosition == POSITION_BOTTOM) {
- requestedPosition = 0;
- }
-
- int targetPosition = requestedPosition;
- targetPosition = Math.min(targetPosition, maxPosition);
- targetPosition = Math.max(targetPosition, minPosition);
-
- int prevPosition = getStacks().indexOf(stack);
- // The positions we calculated above (maxPosition, minPosition) do not take into
- // consideration the following edge cases.
- // 1) We need to adjust the position depending on the value "adding".
- // 2) When we are moving a stack to another position, we also need to adjust the
- // position depending on whether the stack is moving to a higher or lower position.
- if ((targetPosition != requestedPosition) &&
- (adding || targetPosition < prevPosition)) {
- targetPosition++;
- }
-
- return targetPosition;
- }
-
- @Override
- boolean forAllWindows(ToBooleanFunction<WindowState> callback,
- boolean traverseTopToBottom) {
- if (traverseTopToBottom) {
- if (super.forAllWindows(callback, traverseTopToBottom)) {
- return true;
- }
- if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
- return true;
- }
- } else {
- if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
- return true;
- }
- if (super.forAllWindows(callback, traverseTopToBottom)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
- boolean traverseTopToBottom) {
- // For legacy reasons we process the TaskStack.mExitingActivities first here before the
- // app tokens.
- // TODO: Investigate if we need to continue to do this or if we can just process them
- // in-order.
- if (traverseTopToBottom) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
- for (int j = activities.size() - 1; j >= 0; --j) {
- if (activities.get(j).forAllWindowsUnchecked(callback,
- traverseTopToBottom)) {
- return true;
- }
- }
- }
- } else {
- final int count = mChildren.size();
- for (int i = 0; i < count; ++i) {
- final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
- final int appTokensCount = activities.size();
- for (int j = 0; j < appTokensCount; j++) {
- if (activities.get(j).forAllWindowsUnchecked(callback,
- traverseTopToBottom)) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- void setExitingTokensHasVisible(boolean hasVisible) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
- for (int j = activities.size() - 1; j >= 0; --j) {
- activities.get(j).hasVisible = hasVisible;
- }
- }
- }
-
- void removeExistingAppTokensIfPossible() {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
- for (int j = activities.size() - 1; j >= 0; --j) {
- final ActivityRecord activity = activities.get(j);
- if (!activity.hasVisible && !mClosingApps.contains(activity)
- && (!activity.mIsExiting || activity.isEmpty())) {
- // Make sure there is no animation running on this activity, so any windows
- // associated with it will be removed as soon as their animations are
- // complete.
- cancelAnimation();
- ProtoLog.v(WM_DEBUG_ADD_REMOVE,
- "performLayout: Activity exiting now removed %s", activity);
- activity.removeIfPossible();
- }
- }
- }
- }
-
- @Override
- int getOrientation(int candidate) {
- if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
- // Apps and their containers are not allowed to specify an orientation while using
- // root tasks...except for the home stack if it is not resizable and currently
- // visible (top of) its root task.
- if (mRootHomeTask != null && mRootHomeTask.isVisible()) {
- final Task topMost = mRootHomeTask.getTopMostTask();
- final boolean resizable = topMost != null && topMost.isResizeable();
- if (!(resizable && mRootHomeTask.matchParentBounds())) {
- final int orientation = mRootHomeTask.getOrientation();
- if (orientation != SCREEN_ORIENTATION_UNSET) {
- return orientation;
- }
- }
- }
- return SCREEN_ORIENTATION_UNSPECIFIED;
- }
-
- final int orientation = super.getOrientation(candidate);
- if (orientation != SCREEN_ORIENTATION_UNSET
- && orientation != SCREEN_ORIENTATION_BEHIND) {
- ProtoLog.v(WM_DEBUG_ORIENTATION,
- "App is requesting an orientation, return %d for display id=%d",
- orientation, mDisplayId);
- return orientation;
- }
-
- ProtoLog.v(WM_DEBUG_ORIENTATION,
- "No app is requesting an orientation, return %d for display id=%d",
- getLastOrientation(), mDisplayId);
- // The next app has not been requested to be visible, so we keep the current orientation
- // to prevent freezing/unfreezing the display too early.
- return getLastOrientation();
- }
-
- @Override
- void assignChildLayers(SurfaceControl.Transaction t) {
- assignStackOrdering(t);
-
- for (int i = 0; i < mChildren.size(); i++) {
- final ActivityStack s = mChildren.get(i);
- s.assignChildLayers(t);
- }
- }
-
- void assignStackOrdering(SurfaceControl.Transaction t) {
- if (getParent() == null) {
- return;
- }
- mTmpAlwaysOnTopStacks.clear();
- mTmpHomeStacks.clear();
- mTmpNormalStacks.clear();
- for (int i = 0; i < mChildren.size(); ++i) {
- final ActivityStack s = mChildren.get(i);
- if (s.isAlwaysOnTop()) {
- mTmpAlwaysOnTopStacks.add(s);
- } else if (s.isActivityTypeHome()) {
- mTmpHomeStacks.add(s);
- } else {
- mTmpNormalStacks.add(s);
- }
- }
-
- int layer = 0;
- // Place home stacks to the bottom.
- for (int i = 0; i < mTmpHomeStacks.size(); i++) {
- mTmpHomeStacks.get(i).assignLayer(t, layer++);
- }
- // The home animation layer is between the home stacks and the normal stacks.
- final int layerForHomeAnimationLayer = layer++;
- int layerForSplitScreenDividerAnchor = layer++;
- int layerForAnimationLayer = layer++;
- for (int i = 0; i < mTmpNormalStacks.size(); i++) {
- final ActivityStack s = mTmpNormalStacks.get(i);
- s.assignLayer(t, layer++);
- if (s.inSplitScreenWindowingMode()) {
- // The split screen divider anchor is located above the split screen window.
- layerForSplitScreenDividerAnchor = layer++;
- }
- if (s.isTaskAnimating() || s.isAppTransitioning()) {
- // The animation layer is located above the highest animating stack and no
- // higher.
- layerForAnimationLayer = layer++;
- }
- }
- // The boosted animation layer is between the normal stacks and the always on top
- // stacks.
- final int layerForBoostedAnimationLayer = layer++;
- for (int i = 0; i < mTmpAlwaysOnTopStacks.size(); i++) {
- mTmpAlwaysOnTopStacks.get(i).assignLayer(t, layer++);
- }
-
- t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer);
- t.setLayer(mAppAnimationLayer, layerForAnimationLayer);
- t.setLayer(mSplitScreenDividerAnchor, layerForSplitScreenDividerAnchor);
- t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
- }
-
- @Override
- SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
- switch (animationLayer) {
- case ANIMATION_LAYER_BOOSTED:
- return mBoostedAppAnimationLayer;
- case ANIMATION_LAYER_HOME:
- return mHomeAppAnimationLayer;
- case ANIMATION_LAYER_STANDARD:
- default:
- return mAppAnimationLayer;
- }
- }
-
- SurfaceControl getSplitScreenDividerAnchor() {
- return mSplitScreenDividerAnchor;
- }
-
- @Override
- void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- if (getParent() != null) {
- super.onParentChanged(newParent, oldParent, () -> {
- mAppAnimationLayer = makeChildSurface(null)
- .setName("animationLayer")
- .build();
- mBoostedAppAnimationLayer = makeChildSurface(null)
- .setName("boostedAnimationLayer")
- .build();
- mHomeAppAnimationLayer = makeChildSurface(null)
- .setName("homeAnimationLayer")
- .build();
- mSplitScreenDividerAnchor = makeChildSurface(null)
- .setName("splitScreenDividerAnchor")
- .build();
- getPendingTransaction()
- .show(mAppAnimationLayer)
- .show(mBoostedAppAnimationLayer)
- .show(mHomeAppAnimationLayer)
- .show(mSplitScreenDividerAnchor);
- });
- } else {
- super.onParentChanged(newParent, oldParent);
- mWmService.mTransactionFactory.get()
- .remove(mAppAnimationLayer)
- .remove(mBoostedAppAnimationLayer)
- .remove(mHomeAppAnimationLayer)
- .remove(mSplitScreenDividerAnchor)
- .apply();
- mAppAnimationLayer = null;
- mBoostedAppAnimationLayer = null;
- mHomeAppAnimationLayer = null;
- mSplitScreenDividerAnchor = null;
- }
- }
- }
-
private class WindowContainers extends DisplayChildWindowContainer<WindowContainer> {
private final String mName;
@@ -4978,7 +4375,8 @@
private boolean skipImeWindowsDuringTraversal(DisplayContent dc) {
// We skip IME windows so they're processed just above their target, except
// in split-screen mode where we process the IME containers above the docked divider.
- return dc.mInputMethodTarget != null && !dc.isSplitScreenModeActivated();
+ return dc.mInputMethodTarget != null
+ && !dc.mTaskContainers.isSplitScreenModeActivated();
}
/** Like {@link #forAllWindows}, but ignores {@link #skipImeWindowsDuringTraversal} */
@@ -5628,6 +5026,10 @@
}
void onDisplayChanged() {
+ mDisplay.getRealSize(mTmpDisplaySize);
+ setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
+ updateDisplayInfo();
+
// The window policy is responsible for stopping activities on the default display.
final int displayId = mDisplay.getDisplayId();
if (displayId != DEFAULT_DISPLAY) {
@@ -5639,118 +5041,9 @@
mOffToken = null;
}
}
-
- mDisplay.getRealSize(mTmpDisplaySize);
- setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
- updateDisplayInfo();
mWmService.requestTraversal();
}
- void addStack(ActivityStack stack, int position) {
- setStackOnDisplay(stack, position);
- positionStackAt(stack, position);
- }
-
- void addStackReferenceIfNeeded(ActivityStack stack) {
- mTaskContainers.addStackReferenceIfNeeded(stack);
- }
-
- void removeStackReferenceIfNeeded(ActivityStack stack) {
- mTaskContainers.removeStackReferenceIfNeeded(stack);
- }
-
- void onStackRemoved(ActivityStack stack) {
- if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
- Slog.v(TAG_STACK, "removeStack: detaching " + stack + " from displayId=" + mDisplayId);
- }
- if (mPreferredTopFocusableStack == stack) {
- mPreferredTopFocusableStack = null;
- }
- releaseSelfIfNeeded();
- onStackOrderChanged(stack);
- }
-
- void positionStackAtTop(ActivityStack stack, boolean includingParents) {
- positionStackAtTop(stack, includingParents, null /* updateLastFocusedStackReason */);
- }
-
- void positionStackAtTop(ActivityStack stack, boolean includingParents,
- String updateLastFocusedStackReason) {
- positionStackAt(stack, getStackCount(), includingParents, updateLastFocusedStackReason);
- }
-
- void positionStackAtBottom(ActivityStack stack) {
- positionStackAtBottom(stack, null /* updateLastFocusedStackReason */);
- }
-
- void positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason) {
- positionStackAt(stack, 0, false /* includingParents */, updateLastFocusedStackReason);
- }
-
- private void positionStackAt(ActivityStack stack, int position) {
- positionStackAt(stack, position, false /* includingParents */,
- null /* updateLastFocusedStackReason */);
- }
-
- private void positionStackAt(ActivityStack stack, int position, boolean includingParents,
- String updateLastFocusedStackReason) {
- // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
- // the position internally, also update the logic here
- final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
- ? getFocusedStack() : null;
- final boolean wasContained = getIndexOf(stack) >= 0;
- if (mSingleTaskInstance && getStackCount() == 1 && !wasContained) {
- throw new IllegalStateException(
- "positionStackAt: Can only have one task on display=" + this);
- }
-
- final boolean movingToTop = wasContained && position >= getStackCount() - 1;
- // Reset mPreferredTopFocusableStack before positioning to top or {@link
- // ActivityStackSupervisor#updateTopResumedActivityIfNeeded()} won't update the top
- // resumed activity.
- if (movingToTop && stack.isFocusable()) {
- mPreferredTopFocusableStack = null;
- }
-
- // Since positionChildAt() is called during the creation process of pinned stacks,
- // ActivityStack#getStack() can be null.
- positionStackAt(position, stack, includingParents);
-
- // The insert position may be adjusted to non-top when there is always-on-top stack. Since
- // the original position is preferred to be top, the stack should have higher priority when
- // we are looking for top focusable stack. The condition {@code wasContained} restricts the
- // preferred stack is set only when moving an existing stack to top instead of adding a new
- // stack that may be too early (e.g. in the middle of launching or reparenting).
- if (movingToTop && stack.isFocusableAndVisible()) {
- mPreferredTopFocusableStack = stack;
- } else if (mPreferredTopFocusableStack == stack) {
- mPreferredTopFocusableStack = null;
- }
-
- if (updateLastFocusedStackReason != null) {
- final ActivityStack currentFocusedStack = getFocusedStack();
- if (currentFocusedStack != prevFocusedStack) {
- mLastFocusedStack = prevFocusedStack;
- EventLogTags.writeWmFocusedStack(mRootWindowContainer.mCurrentUser, mDisplayId,
- currentFocusedStack == null ? -1 : currentFocusedStack.getRootTaskId(),
- mLastFocusedStack == null ? -1 : mLastFocusedStack.getRootTaskId(),
- updateLastFocusedStackReason);
- }
- }
-
- onStackOrderChanged(stack);
- }
-
- ActivityStack getStack(int rootTaskId) {
- for (int i = getStackCount() - 1; i >= 0; --i) {
- final ActivityStack stack = getStackAt(i);
- if (stack.getRootTaskId() == rootTaskId) {
- return stack;
- }
- }
- return null;
- }
-
static boolean alwaysCreateStack(int windowingMode, int activityType) {
// Always create a stack for fullscreen, freeform, and split-screen-secondary windowing
// modes so that we can manage visual ordering and return types correctly.
@@ -5761,358 +5054,13 @@
|| windowingMode == WINDOWING_MODE_MULTI_WINDOW);
}
- /**
- * Returns an existing stack compatible with the windowing mode and activity type or creates one
- * if a compatible stack doesn't exist.
- * @see #getOrCreateStack(int, int, boolean, Intent, Task, boolean)
- */
- ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop) {
- return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,
- null /* candidateTask */, false /* createdByOrganizer */);
- }
-
- /**
- * When two level tasks are required for given windowing mode and activity type, returns an
- * existing compatible root task or creates a new one.
- * For one level task, the candidate task would be reused to also be the root task or create
- * a new root task if no candidate task.
- * @see #getStack(int, int)
- * @see #createStack(int, int, boolean)
- */
- ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop,
- Intent intent, Task candidateTask, boolean createdByOrganizer) {
- if (!alwaysCreateStack(windowingMode, activityType)) {
- ActivityStack stack = getStack(windowingMode, activityType);
- if (stack != null) {
- return stack;
- }
- } else if (candidateTask != null) {
- final ActivityStack stack = (ActivityStack) candidateTask;
- final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
- if (isSplitScreenModeActivated()) {
- final Task splitRootSecondary = getTask(t -> t.mCreatedByOrganizer && t.isRootTask()
- && t.inSplitScreenSecondaryWindowingMode());
- if (stack.getParent() == null) {
- splitRootSecondary.addChild(stack, position);
- } else if (stack.getParent() != splitRootSecondary) {
- stack.reparent(splitRootSecondary, position);
- }
- } else if (stack.getDisplay() != this || !stack.isRootTask()) {
- if (stack.getParent() == null) {
- addStack(stack, position);
- } else {
- stack.reparent(this, onTop);
- }
- }
- // Update windowing mode if necessary, e.g. moving a pinned task to fullscreen.
- if (candidateTask.getWindowingMode() != windowingMode) {
- candidateTask.setWindowingMode(windowingMode);
- }
- return stack;
- }
- return createStack(windowingMode, activityType, onTop, null /*info*/, intent,
- createdByOrganizer);
- }
-
- /**
- * Returns an existing stack compatible with the input params or creates one
- * if a compatible stack doesn't exist.
- * @see #getOrCreateStack(int, int, boolean)
- */
- ActivityStack getOrCreateStack(@Nullable ActivityRecord r,
- @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType,
- boolean onTop) {
- // First preference is the windowing mode in the activity options if set.
- int windowingMode = (options != null)
- ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
- // Validate that our desired windowingMode will work under the current conditions.
- // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
- // it's display's windowing mode.
- windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
- return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,
- candidateTask, false /* createdByOrganizer */);
- }
-
- @VisibleForTesting
- int getNextStackId() {
- return mAtmService.mStackSupervisor.getNextTaskIdForUser();
- }
-
ActivityStack createStack(int windowingMode, int activityType, boolean onTop) {
- return createStack(windowingMode, activityType, onTop, null /* info */, null /* intent */,
- false /* createdByOrganizer */);
+ return mTaskContainers.createStack(windowingMode, activityType, onTop, null /* info */,
+ null /* intent */, false /* createdByOrganizer */);
}
- /**
- * Creates a stack matching the input windowing mode and activity type on this display.
- * @param windowingMode The windowing mode the stack should be created in. If
- * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
- * inherit its parent's windowing mode.
- * @param activityType The activityType the stack should be created in. If
- * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
- * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
- * @param onTop If true the stack will be created at the top of the display, else at the bottom.
- * @param info The started activity info.
- * @param intent The intent that started this task.
- * @param createdByOrganizer @{code true} if this is created by task organizer, @{code false}
- * otherwise.
- * @return The newly created stack.
- */
- ActivityStack createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info,
- Intent intent, boolean createdByOrganizer) {
- if (mSingleTaskInstance && getStackCount() > 0) {
- // Create stack on default display instead since this display can only contain 1 stack.
- // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
- // this goes away once ActivityView is no longer using virtual displays.
- return mRootWindowContainer.getDefaultDisplay().createStack(
- windowingMode, activityType, onTop, info, intent, createdByOrganizer);
- }
-
- if (activityType == ACTIVITY_TYPE_UNDEFINED && !createdByOrganizer) {
- // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
- // anything else should be passing it in anyways...except for the task organizer.
- activityType = ACTIVITY_TYPE_STANDARD;
- }
-
- if (activityType != ACTIVITY_TYPE_STANDARD && activityType != ACTIVITY_TYPE_UNDEFINED) {
- // For now there can be only one stack of a particular non-standard activity type on a
- // display. So, get that ignoring whatever windowing mode it is currently in.
- ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
- if (stack != null) {
- throw new IllegalArgumentException("Stack=" + stack + " of activityType="
- + activityType + " already on display=" + this + ". Can't have multiple.");
- }
- }
-
- if (!isWindowingModeSupported(windowingMode, mAtmService.mSupportsMultiWindow,
- mAtmService.mSupportsSplitScreenMultiWindow,
- mAtmService.mSupportsFreeformWindowManagement,
- mAtmService.mSupportsPictureInPicture, activityType)) {
- throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
- + windowingMode);
- }
-
- final int stackId = getNextStackId();
- return createStackUnchecked(windowingMode, activityType, stackId, onTop, info, intent,
- createdByOrganizer);
- }
-
- /** @return the root task to create the next task in. */
- private Task updateLaunchRootTask(int windowingMode) {
- if (!isSplitScreenWindowingMode(windowingMode)) {
- // Only split-screen windowing modes can do this currently...
- return null;
- }
- for (int i = getStackCount() - 1; i >= 0; --i) {
- final Task t = getStackAt(i);
- if (!t.mCreatedByOrganizer || t.getRequestedOverrideWindowingMode() != windowingMode) {
- continue;
- }
- // If not already set, pick a launch root which is not the one we are launching into.
- if (mLaunchRootTask == null) {
- for (int j = 0, n = getStackCount(); j < n; ++j) {
- final Task tt = getStackAt(j);
- if (tt.mCreatedByOrganizer && tt != t) {
- mLaunchRootTask = tt;
- break;
- }
- }
- }
- return t;
- }
- return mLaunchRootTask;
- }
-
- @VisibleForTesting
- ActivityStack createStackUnchecked(int windowingMode, int activityType, int stackId,
- boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer) {
- if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
- throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
- + "activity type.");
- }
- if (info == null) {
- info = new ActivityInfo();
- info.applicationInfo = new ApplicationInfo();
- }
-
- // Task created by organizer are added as root.
- Task launchRootTask = createdByOrganizer ? null : updateLaunchRootTask(windowingMode);
- if (launchRootTask != null) {
- // Since this stack will be put into a root task, its windowingMode will be inherited.
- windowingMode = WINDOWING_MODE_UNDEFINED;
- }
-
- final ActivityStack stack = (ActivityStack) Task.create(mAtmService, stackId, activityType,
- info, intent, createdByOrganizer);
- if (launchRootTask != null) {
- launchRootTask.addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
- if (onTop) {
- positionStackAtTop((ActivityStack) launchRootTask, false /* includingParents */);
- }
- } else {
- addStack(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
- stack.setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
- false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
- true /* creating */);
- }
- return stack;
- }
-
- /**
- * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a
- * focusable and visible stack from the top of stacks in this display.
- */
ActivityStack getFocusedStack() {
- if (mPreferredTopFocusableStack != null) {
- return mPreferredTopFocusableStack;
- }
-
- for (int i = getStackCount() - 1; i >= 0; --i) {
- final ActivityStack stack = getStackAt(i);
- if (stack.isFocusableAndVisible()) {
- return stack;
- }
- }
-
- return null;
- }
-
- ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) {
- final int currentWindowingMode = currentFocus != null
- ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
-
- ActivityStack candidate = null;
- for (int i = getStackCount() - 1; i >= 0; --i) {
- final ActivityStack stack = getStackAt(i);
- if (ignoreCurrent && stack == currentFocus) {
- continue;
- }
- if (!stack.isFocusableAndVisible()) {
- continue;
- }
-
- if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
- && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
- // If the currently focused stack is in split-screen secondary we save off the
- // top primary split-screen stack as a candidate for focus because we might
- // prefer focus to move to an other stack to avoid primary split-screen stack
- // overlapping with a fullscreen stack when a fullscreen stack is higher in z
- // than the next split-screen stack. Assistant stack, I am looking at you...
- // We only move the focus to the primary-split screen stack if there isn't a
- // better alternative.
- candidate = stack;
- continue;
- }
- if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) {
- // Use the candidate stack since we are now at the secondary split-screen.
- return candidate;
- }
- return stack;
- }
- return candidate;
- }
-
- ActivityRecord getResumedActivity() {
- final ActivityStack focusedStack = getFocusedStack();
- if (focusedStack == null) {
- return null;
- }
- // TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
- // Check if the focused stack has the resumed activity
- ActivityRecord resumedActivity = focusedStack.getResumedActivity();
- if (resumedActivity == null || resumedActivity.app == null) {
- // If there is no registered resumed activity in the stack or it is not running -
- // try to use previously resumed one.
- resumedActivity = focusedStack.mPausingActivity;
- if (resumedActivity == null || resumedActivity.app == null) {
- // If previously resumed activity doesn't work either - find the topmost running
- // activity that can be focused.
- resumedActivity = focusedStack.topRunningActivity(true /* focusableOnly */);
- }
- }
- return resumedActivity;
- }
-
- ActivityStack getLastFocusedStack() {
- return mLastFocusedStack;
- }
-
- boolean allResumedActivitiesComplete() {
- for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord r = getStackAt(stackNdx).getResumedActivity();
- if (r != null && !r.isState(RESUMED)) {
- return false;
- }
- }
- final ActivityStack currentFocusedStack = getFocusedStack();
- if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
- Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from="
- + mLastFocusedStack + " to=" + currentFocusedStack);
- }
- mLastFocusedStack = currentFocusedStack;
- return true;
- }
-
- /**
- * Pause all activities in either all of the stacks or just the back stacks. This is done before
- * resuming a new activity and to make sure that previously active activities are
- * paused in stacks that are no longer visible or in pinned windowing mode. This does not
- * pause activities in visible stacks, so if an activity is launched within the same stack/task,
- * then we should explicitly pause that stack's top activity.
- * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
- * @param resuming The resuming activity.
- * @return {@code true} if any activity was paused as a result of this call.
- */
- boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) {
- boolean someActivityPaused = false;
- for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = getStackAt(stackNdx);
- final ActivityRecord resumedActivity = stack.getResumedActivity();
- if (resumedActivity != null
- && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
- || !stack.isTopActivityFocusable())) {
- if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack
- + " mResumedActivity=" + resumedActivity);
- someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
- resuming);
- }
- }
- return someActivityPaused;
- }
-
- /**
- * Find task for putting the Activity in.
- */
- void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplay,
- RootWindowContainer.FindTaskResult result) {
- mTmpFindTaskResult.clear();
- for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = getStackAt(stackNdx);
- if (!r.hasCompatibleActivityType(stack) && stack.isLeafTask()) {
- if (DEBUG_TASKS) {
- Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
- }
- continue;
- }
-
- mTmpFindTaskResult.process(r, stack);
- // It is possible to have tasks in multiple stacks with the same root affinity, so
- // we should keep looking after finding an affinity match to see if there is a
- // better match in another stack. Also, task affinity isn't a good enough reason
- // to target a display which isn't the source of the intent, so skip any affinity
- // matches not on the specified display.
- if (mTmpFindTaskResult.mRecord != null) {
- if (mTmpFindTaskResult.mIdealMatch) {
- result.setTo(mTmpFindTaskResult);
- return;
- } else if (isPreferredDisplay) {
- // Note: since the traversing through the stacks is top down, the floating
- // tasks should always have lower priority than any affinity-matching tasks
- // in the fullscreen stacks
- result.setTo(mTmpFindTaskResult);
- }
- }
- }
+ return mTaskContainers.getFocusedStack();
}
/**
@@ -6120,249 +5068,11 @@
* ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
*/
void removeStacksInWindowingModes(int... windowingModes) {
- if (windowingModes == null || windowingModes.length == 0) {
- return;
- }
-
- // Collect the stacks that are necessary to be removed instead of performing the removal
- // by looping mStacks, so that we don't miss any stacks after the stack size changed or
- // stacks reordered.
- final ArrayList<ActivityStack> stacks = new ArrayList<>();
- for (int j = windowingModes.length - 1; j >= 0; --j) {
- final int windowingMode = windowingModes[j];
- for (int i = getStackCount() - 1; i >= 0; --i) {
- final ActivityStack stack = getStackAt(i);
- if (!stack.isActivityTypeStandardOrUndefined()) {
- continue;
- }
- if (stack.getWindowingMode() != windowingMode) {
- continue;
- }
- stacks.add(stack);
- }
- }
-
- for (int i = stacks.size() - 1; i >= 0; --i) {
- mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i));
- }
+ mTaskContainers.removeStacksInWindowingModes(windowingModes);
}
void removeStacksWithActivityTypes(int... activityTypes) {
- if (activityTypes == null || activityTypes.length == 0) {
- return;
- }
-
- // Collect the stacks that are necessary to be removed instead of performing the removal
- // by looping mStacks, so that we don't miss any stacks after the stack size changed or
- // stacks reordered.
- final ArrayList<ActivityStack> stacks = new ArrayList<>();
- for (int j = activityTypes.length - 1; j >= 0; --j) {
- final int activityType = activityTypes[j];
- for (int i = getStackCount() - 1; i >= 0; --i) {
- final ActivityStack stack = getStackAt(i);
- // Collect the root tasks that are currently being organized.
- if (stack.isOrganized()) {
- for (int k = stack.getChildCount() - 1; k >= 0; --k) {
- final ActivityStack childStack = (ActivityStack) stack.getChildAt(k);
- if (childStack.getActivityType() == activityType) {
- stacks.add(childStack);
- }
- }
- } else if (stack.getActivityType() == activityType) {
- stacks.add(stack);
- }
- }
- }
-
- for (int i = stacks.size() - 1; i >= 0; --i) {
- mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i));
- }
- }
-
- void onSplitScreenModeDismissed() {
- mAtmService.deferWindowLayout();
- try {
- mLaunchRootTask = null;
- moveSplitScreenTasksToFullScreen();
- } finally {
- final ActivityStack topFullscreenStack =
- getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
- final ActivityStack homeStack = getOrCreateRootHomeTask();
- if (topFullscreenStack != null && homeStack != null && !isTopStack(homeStack)) {
- // Whenever split-screen is dismissed we want the home stack directly behind the
- // current top fullscreen stack so it shows up when the top stack is finished.
- // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
- // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
- // once we have that.
- homeStack.moveToFront("onSplitScreenModeDismissed");
- topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
- }
- mAtmService.continueWindowLayout();
- }
- }
-
- private void moveSplitScreenTasksToFullScreen() {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- mTmpTasks.clear();
- forAllTasks(task -> {
- if (task.mCreatedByOrganizer && task.inSplitScreenWindowingMode() && task.hasChild()) {
- mTmpTasks.add(task);
- }
- });
-
- for (int i = mTmpTasks.size() - 1; i >= 0; i--) {
- final Task root = mTmpTasks.get(i);
- for (int j = 0; j < root.getChildCount(); j++) {
- wct.reparent(root.getChildAt(j).mRemoteToken, null, true /* toTop */);
- }
- }
- mAtmService.mWindowOrganizerController.applyTransaction(wct);
- }
-
- /**
- * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
- * @param windowingMode The windowing mode we are checking support for.
- * @param supportsMultiWindow If we should consider support for multi-window mode in general.
- * @param supportsSplitScreen If we should consider support for split-screen multi-window.
- * @param supportsFreeform If we should consider support for freeform multi-window.
- * @param supportsPip If we should consider support for picture-in-picture mutli-window.
- * @param activityType The activity type under consideration.
- * @return true if the windowing mode is supported.
- */
- private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
- boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
- int activityType) {
-
- if (windowingMode == WINDOWING_MODE_UNDEFINED
- || windowingMode == WINDOWING_MODE_FULLSCREEN) {
- return true;
- }
- if (!supportsMultiWindow) {
- return false;
- }
-
- if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
- return true;
- }
-
- final int displayWindowingMode = getWindowingMode();
- if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
- return supportsSplitScreen
- && WindowConfiguration.supportSplitScreenWindowingMode(activityType)
- // Freeform windows and split-screen windows don't mix well, so prevent
- // split windowing modes on freeform displays.
- && displayWindowingMode != WINDOWING_MODE_FREEFORM;
- }
-
- if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
- return false;
- }
-
- if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
- return false;
- }
- return true;
- }
-
- /**
- * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
- * display with the provided parameters.
- *
- * @param r The ActivityRecord in question.
- * @param options Options to start with.
- * @param task The task within-which the activity would start.
- * @param activityType The type of activity to start.
- * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
- */
- int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
- @Nullable Task task, int activityType) {
-
- // First preference if the windowing mode in the activity options if set.
- int windowingMode = (options != null)
- ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
-
- // If windowing mode is unset, then next preference is the candidate task, then the
- // activity record.
- if (windowingMode == WINDOWING_MODE_UNDEFINED) {
- if (task != null) {
- windowingMode = task.getWindowingMode();
- }
- if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
- windowingMode = r.getWindowingMode();
- }
- if (windowingMode == WINDOWING_MODE_UNDEFINED) {
- // Use the display's windowing mode.
- windowingMode = getWindowingMode();
- }
- }
- windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
- return windowingMode != WINDOWING_MODE_UNDEFINED
- ? windowingMode : WINDOWING_MODE_FULLSCREEN;
- }
-
- /**
- * Check that the requested windowing-mode is appropriate for the specified task and/or activity
- * on this display.
- *
- * @param windowingMode The windowing-mode to validate.
- * @param r The {@link ActivityRecord} to check against.
- * @param task The {@link Task} to check against.
- * @param activityType An activity type.
- * @return The provided windowingMode or the closest valid mode which is appropriate.
- */
- int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
- int activityType) {
- // Make sure the windowing mode we are trying to use makes sense for what is supported.
- boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow;
- boolean supportsSplitScreen = mAtmService.mSupportsSplitScreenMultiWindow;
- boolean supportsFreeform = mAtmService.mSupportsFreeformWindowManagement;
- boolean supportsPip = mAtmService.mSupportsPictureInPicture;
- if (supportsMultiWindow) {
- if (task != null) {
- supportsMultiWindow = task.isResizeable();
- supportsSplitScreen = task.supportsSplitScreenWindowingMode();
- // TODO: Do we need to check for freeform and Pip support here?
- } else if (r != null) {
- supportsMultiWindow = r.isResizeable();
- supportsSplitScreen = r.supportsSplitScreenWindowingMode();
- supportsFreeform = r.supportsFreeform();
- supportsPip = r.supportsPictureInPicture();
- }
- }
-
- final boolean inSplitScreenMode = isSplitScreenModeActivated();
- if (!inSplitScreenMode
- && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
- // Switch to the display's windowing mode if we are not in split-screen mode and we are
- // trying to launch in split-screen secondary.
- windowingMode = WINDOWING_MODE_UNDEFINED;
- } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN
- || windowingMode == WINDOWING_MODE_UNDEFINED)
- && supportsSplitScreen) {
- windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
- }
-
- if (windowingMode != WINDOWING_MODE_UNDEFINED
- && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
- supportsFreeform, supportsPip, activityType)) {
- return windowingMode;
- }
- return WINDOWING_MODE_UNDEFINED;
- }
-
- boolean isTopStack(ActivityStack stack) {
- return stack == getTopStack();
- }
-
- boolean isTopNotPinnedStack(ActivityStack stack) {
- for (int i = getStackCount() - 1; i >= 0; --i) {
- final ActivityStack current = getStackAt(i);
- if (!current.inPinnedWindowingMode()) {
- return current == stack;
- }
- }
- return false;
+ mTaskContainers.removeStacksWithActivityTypes(activityTypes);
}
ActivityRecord topRunningActivity() {
@@ -6379,37 +5089,7 @@
* @return The top running activity. {@code null} if none is available.
*/
ActivityRecord topRunningActivity(boolean considerKeyguardState) {
- ActivityRecord topRunning = null;
- final ActivityStack focusedStack = getFocusedStack();
- if (focusedStack != null) {
- topRunning = focusedStack.topRunningActivity();
- }
-
- // Look in other focusable stacks.
- if (topRunning == null) {
- for (int i = getStackCount() - 1; i >= 0; --i) {
- final ActivityStack stack = getStackAt(i);
- // Only consider focusable stacks other than the current focused one.
- if (stack == focusedStack || !stack.isTopActivityFocusable()) {
- continue;
- }
- topRunning = stack.topRunningActivity();
- if (topRunning != null) {
- break;
- }
- }
- }
-
- // This activity can be considered the top running activity if we are not considering
- // the locked state, the keyguard isn't locked, or we can show when locked.
- if (topRunning != null && considerKeyguardState
- && mRootWindowContainer.mStackSupervisor.getKeyguardController()
- .isKeyguardLocked()
- && !topRunning.canShowWhenLocked()) {
- return null;
- }
-
- return topRunning;
+ return mTaskContainers.topRunningActivity(considerKeyguardState);
}
boolean updateDisplayOverrideConfigurationLocked() {
@@ -6582,7 +5262,7 @@
// If default display is in split-window mode, set windowing mode of the stack
// to split-screen secondary. Otherwise, set the windowing mode to undefined by
// default to let stack inherited the windowing mode from the new display.
- final int windowingMode = toDisplay.isSplitScreenModeActivated()
+ final int windowingMode = toDisplay.mTaskContainers.isSplitScreenModeActivated()
? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
: WINDOWING_MODE_UNDEFINED;
stack.reparent(toDisplay, true /* onTop */);
@@ -6614,7 +5294,7 @@
}
}
- private void releaseSelfIfNeeded() {
+ void releaseSelfIfNeeded() {
if (!mRemoved) {
return;
}
@@ -6691,80 +5371,6 @@
return (index < wc.mChildren.size()) ? (ActivityStack) wc.mChildren.get(index) : null;
}
- /**
- * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
- * Generally used in conjunction with {@link #moveStackBehindStack}.
- */
- // TODO(b/151575894): Remove special stack movement methods.
- void moveStackBehindBottomMostVisibleStack(ActivityStack stack) {
- if (stack.shouldBeVisible(null)) {
- // Skip if the stack is already visible
- return;
- }
-
- final boolean isRootTask = stack.isRootTask();
- if (isRootTask) {
- // Move the stack to the bottom to not affect the following visibility checks
- positionStackAtBottom(stack);
- } else {
- stack.getParent().positionChildAt(POSITION_BOTTOM, stack, false /* includingParents */);
- }
-
- // Find the next position where the stack should be placed
- final int numStacks = isRootTask ? getStackCount() : stack.getParent().getChildCount();
- for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
- final ActivityStack s = isRootTask ? getStackAt(stackNdx)
- : (ActivityStack) stack.getParent().getChildAt(stackNdx);
- if (s == stack) {
- continue;
- }
- final int winMode = s.getWindowingMode();
- final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN
- || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
- if (s.shouldBeVisible(null) && isValidWindowingMode) {
- // Move the provided stack to behind this stack
- final int position = Math.max(0, stackNdx - 1);
- if (isRootTask) {
- positionStackAt(stack, position);
- } else {
- stack.getParent().positionChildAt(position, stack, false /*includingParents */);
- }
- break;
- }
- }
- }
-
- /**
- * Moves the {@param stack} behind the given {@param behindStack} if possible. If
- * {@param behindStack} is not currently in the display, then then the stack is moved to the
- * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}.
- */
- void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) {
- if (behindStack == null || behindStack == stack) {
- return;
- }
-
- final WindowContainer parent = stack.getParent();
- if (parent == null || parent != behindStack.getParent()) {
- return;
- }
-
- // Note that positionChildAt will first remove the given stack before inserting into the
- // list, so we need to adjust the insertion index to account for the removed index
- // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
- // position internally
- final int stackIndex = parent.mChildren.indexOf(stack);
- final int behindStackIndex = parent.mChildren.indexOf(behindStack);
- final int insertIndex = stackIndex <= behindStackIndex
- ? behindStackIndex - 1 : behindStackIndex;
- final int position = Math.max(0, insertIndex);
- if (stack.isRootTask()) {
- positionStackAt(stack, position);
- } else {
- parent.positionChildAt(position, stack, false /* includingParents */);
- }
- }
-
void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
@@ -6774,50 +5380,6 @@
}
}
- void moveHomeStackToFront(String reason) {
- final ActivityStack homeStack = getOrCreateRootHomeTask();
- if (homeStack != null) {
- homeStack.moveToFront(reason);
- }
- }
-
- /**
- * Moves the focusable home activity to top. If there is no such activity, the home stack will
- * still move to top.
- */
- void moveHomeActivityToTop(String reason) {
- final ActivityRecord top = getHomeActivity();
- if (top == null) {
- moveHomeStackToFront(reason);
- return;
- }
- top.moveFocusableActivityToTop(reason);
- }
-
- @Nullable
- ActivityRecord getHomeActivity() {
- return getHomeActivityForUser(mRootWindowContainer.mCurrentUser);
- }
-
- @Nullable
- ActivityRecord getHomeActivityForUser(int userId) {
- final ActivityStack homeStack = getRootHomeTask();
- if (homeStack == null) {
- return null;
- }
-
- final PooledPredicate p = PooledLambda.obtainPredicate(
- DisplayContent::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class),
- userId);
- final ActivityRecord r = homeStack.getActivity(p);
- p.recycle();
- return r;
- }
-
- private static boolean isHomeActivityForUser(ActivityRecord r, int userId) {
- return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId);
- }
-
boolean isSleeping() {
return mSleeping;
}
@@ -6848,7 +5410,7 @@
* Notifies of a stack order change
* @param stack The stack which triggered the order change
*/
- private void onStackOrderChanged(ActivityStack stack) {
+ void onStackOrderChanged(ActivityStack stack) {
for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack);
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index f593393..367151c 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -78,7 +78,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
@@ -850,7 +849,6 @@
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
break;
- case TYPE_DREAM:
case TYPE_WALLPAPER:
// Dreams and wallpapers don't have an app window token and can thus not be
// letterboxed. Hence always let them extend under the cutout.
@@ -1225,13 +1223,6 @@
if (DEBUG_ANIM) Slog.i(TAG, "**** STARTING EXIT");
return R.anim.app_starting_exit;
}
- } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
- && transit == TRANSIT_ENTER) {
- // Special case: we are animating in a dream, while the keyguard
- // is shown. We don't want an animation on the dream, because
- // we need it shown immediately with the keyguard animating away
- // to reveal it.
- return ANIMATION_NONE;
}
return ANIMATION_STYLEABLE;
@@ -2528,7 +2519,7 @@
if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
mForceStatusBar = true;
}
- if (attrs.type == TYPE_DREAM) {
+ if (win.isDreamWindow()) {
// If the lockscreen was showing when the dream started then wait
// for the dream to draw before hiding the lockscreen.
if (!mDreamingLockscreen
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 18332b9..88cdd17 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -62,7 +62,7 @@
// When true, need to call updateInputWindowsLw().
private boolean mUpdateInputWindowsNeeded = true;
private boolean mUpdateInputWindowsPending;
- private boolean mUpdateInputWindowsImmediately;
+ private boolean mApplyImmediately;
// Currently focused input window handle.
private InputWindowHandle mFocusedInputWindowHandle;
@@ -347,20 +347,14 @@
}
}
- /**
- * Immediately update the input transaction and merge into the passing Transaction that could be
- * collected and applied later.
- */
- void updateInputWindowsImmediately(SurfaceControl.Transaction t) {
+ void updateInputWindowsImmediately() {
mHandler.removeCallbacks(mUpdateInputWindows);
- mUpdateInputWindowsImmediately = true;
+ mApplyImmediately = true;
mUpdateInputWindows.run();
- mUpdateInputWindowsImmediately = false;
- t.merge(mInputTransaction);
+ mApplyImmediately = false;
}
- /**
- * Called when the current input focus changes.
+ /* Called when the current input focus changes.
* Layer assignment is assumed to be complete by the time this is called.
*/
public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
@@ -471,7 +465,10 @@
if (mAddWallpaperInputConsumerHandle) {
mWallpaperInputConsumer.show(mInputTransaction, 0);
}
- if (!mUpdateInputWindowsImmediately) {
+
+ if (mApplyImmediately) {
+ mInputTransaction.apply();
+ } else {
mDisplayContent.getPendingTransaction().merge(mInputTransaction);
mDisplayContent.scheduleAnimation();
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index fda70d1..b2f5988 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -77,6 +77,9 @@
/** Updates the target which can control system bars. */
void updateBarControlTarget(@Nullable WindowState focusedWin) {
+ if (mFocusedWin != focusedWin){
+ abortTransient();
+ }
mFocusedWin = focusedWin;
mStateController.onBarControlTargetChanged(getStatusControlTarget(focusedWin),
getFakeStatusControlTarget(focusedWin),
@@ -123,11 +126,13 @@
mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(),
mShowingTransientTypes.toArray());
updateBarControlTarget(mFocusedWin);
+ InsetsState state = new InsetsState(mStateController.getRawInsetsState());
startAnimation(true /* show */, () -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
mStateController.notifyInsetsChanged();
}
- });
+ }, state);
+ mStateController.onInsetsModified(mDummyControlTarget, state);
}
}
@@ -135,13 +140,15 @@
if (mShowingTransientTypes.size() == 0) {
return;
}
+ InsetsState state = new InsetsState(mStateController.getRawInsetsState());
startAnimation(false /* show */, () -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
mShowingTransientTypes.clear();
mStateController.notifyInsetsChanged();
updateBarControlTarget(mFocusedWin);
}
- });
+ }, state);
+ mStateController.onInsetsModified(mDummyControlTarget, state);
}
boolean isTransient(@InternalInsetsType int type) {
@@ -152,14 +159,22 @@
* @see InsetsStateController#getInsetsForDispatch
*/
InsetsState getInsetsForDispatch(WindowState target) {
- InsetsState state = mStateController.getInsetsForDispatch(target);
+ InsetsState originalState = mStateController.getInsetsForDispatch(target);
+ InsetsState state = originalState;
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+ state = new InsetsState(state);
state.setSourceVisible(mShowingTransientTypes.get(i), false);
}
if (mFocusedWin != null && getStatusControlTarget(mFocusedWin) == mDummyControlTarget) {
+ if (state == originalState) {
+ state = new InsetsState(state);
+ }
state.setSourceVisible(ITYPE_STATUS_BAR, mFocusedWin.getRequestedInsetsState());
}
if (mFocusedWin != null && getNavControlTarget(mFocusedWin) == mDummyControlTarget) {
+ if (state == originalState) {
+ state = new InsetsState(state);
+ }
state.setSourceVisible(ITYPE_NAVIGATION_BAR, mFocusedWin.getRequestedInsetsState());
}
return state;
@@ -206,6 +221,13 @@
}
}
+ private void abortTransient() {
+ mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(),
+ mShowingTransientTypes.toArray());
+ mShowingTransientTypes.clear();
+ updateBarControlTarget(mFocusedWin);
+ }
+
private @Nullable InsetsControlTarget getFakeStatusControlTarget(
@Nullable WindowState focused) {
return getStatusControlTarget(focused) == mDummyControlTarget ? focused : null;
@@ -286,19 +308,20 @@
}
@VisibleForTesting
- void startAnimation(boolean show, Runnable callback) {
+ void startAnimation(boolean show, Runnable callback, InsetsState state) {
int typesReady = 0;
final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
final IntArray showingTransientTypes = mShowingTransientTypes;
for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
- InsetsSourceProvider provider =
- mStateController.getSourceProvider(showingTransientTypes.get(i));
+ int type = showingTransientTypes.get(i);
+ InsetsSourceProvider provider = mStateController.getSourceProvider(type);
InsetsSourceControl control = provider.getControl(mDummyControlTarget);
if (control == null || control.getLeash() == null) {
continue;
}
- typesReady |= InsetsState.toPublicType(showingTransientTypes.get(i));
+ typesReady |= InsetsState.toPublicType(type);
controls.put(control.getType(), new InsetsSourceControl(control));
+ state.setSourceVisible(type, show);
}
controlAnimationUnchecked(typesReady, controls, show, callback);
}
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index ada6d47..cb0d853 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -259,10 +259,13 @@
if (target == null) {
// Cancelling the animation will invoke onAnimationCancelled, resetting all the fields.
mWin.cancelAnimation();
+ setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
return;
}
mAdapter = new ControlAdapter();
- setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
+ if (getSource().getType() == ITYPE_IME) {
+ setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
+ }
final Transaction t = mDisplayContent.getPendingTransaction();
mWin.startAnimation(t, mAdapter, !mClientVisible /* hidden */,
ANIMATION_TYPE_INSETS_CONTROL, null /* animationFinishedCallback */);
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 6b39fd2..a936e74 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -407,10 +407,10 @@
// stack since it will be complicated/risky to try to put the activity on top
// of the lock screen in the right fullscreen configuration.
final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
- if (!display.isSplitScreenModeActivated()) {
+ if (!display.mTaskContainers.isSplitScreenModeActivated()) {
return;
}
- display.onSplitScreenModeDismissed();
+ display.mTaskContainers.onSplitScreenModeDismissed();
}
}
@@ -565,6 +565,7 @@
dumpDisplayStates(pw, prefix);
pw.println(prefix + " mDismissalRequested=" + mDismissalRequested);
pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
+ pw.println();
}
void dumpDebug(ProtoOutputStream proto, long fieldId) {
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 3b25b74..337a68e 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -917,7 +917,7 @@
}
public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "LockTaskController");
+ pw.println(prefix + "LockTaskController:");
prefix = prefix + " ";
pw.println(prefix + "mLockTaskModeState=" + lockTaskModeToString());
pw.println(prefix + "mLockTaskModeTasks=");
@@ -929,6 +929,7 @@
pw.println(prefix + " u" + mLockTaskPackages.keyAt(i)
+ ":" + Arrays.toString(mLockTaskPackages.valueAt(i)));
}
+ pw.println();
}
private String lockTaskModeToString() {
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index 0ab1a3e..4be4c89 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -10,3 +10,4 @@
erosky@google.com
riddlehsu@google.com
louischang@google.com
+winsonc@google.com
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index e14b8ae..66dbfd5 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -163,24 +163,13 @@
}
/**
- * Saves the current snap fraction for re-entry of the current activity into PiP.
+ * Activity is hidden (either stopped or removed), resets the last saved snap fraction
+ * so that the default bounds will be returned for the next session.
*/
- void saveReentryBounds(final ComponentName componentName, final Rect stackBounds) {
+ void onActivityHidden(ComponentName componentName) {
if (mPinnedStackListener == null) return;
try {
- mPinnedStackListener.onSaveReentryBounds(componentName, stackBounds);
- } catch (RemoteException e) {
- Slog.e(TAG_WM, "Error delivering save reentry fraction event.", e);
- }
- }
-
- /**
- * Resets the last saved snap fraction so that the default bounds will be returned.
- */
- void resetReentryBounds(ComponentName componentName) {
- if (mPinnedStackListener == null) return;
- try {
- mPinnedStackListener.onResetReentryBounds(componentName);
+ mPinnedStackListener.onActivityHidden(componentName);
} catch (RemoteException e) {
Slog.e(TAG_WM, "Error delivering reset reentry fraction event.", e);
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 057592c..26b263e 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -208,7 +208,7 @@
try {
if (hasExistingActivity) {
// Move the recents activity into place for the animation if it is not top most
- mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
+ mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(targetStack);
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
targetStack, mDefaultDisplay.getStackAbove(targetStack));
@@ -227,7 +227,7 @@
targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
mTargetActivityType);
targetActivity = getTargetActivity(targetStack);
- mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
+ mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(targetStack);
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
targetStack, mDefaultDisplay.getStackAbove(targetStack));
@@ -352,7 +352,8 @@
} else if (reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION){
// Restore the target stack to its previous position
final DisplayContent display = targetActivity.getDisplay();
- display.moveStackBehindStack(targetStack, mRestoreTargetBehindStack);
+ display.mTaskContainers.moveStackBehindStack(targetStack,
+ mRestoreTargetBehindStack);
if (WM_DEBUG_RECENTS_ANIMATIONS.isLogToAny()) {
final ActivityStack aboveTargetStack =
mDefaultDisplay.getStackAbove(targetStack);
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
index 420997a..770c088 100644
--- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -257,8 +257,8 @@
}
if (targetTask == null) {
if (alwaysCreateTask) {
- targetTask = display.getOrCreateStack(windowingMode, activityType,
- false /* onTop */);
+ targetTask = display.mTaskContainers.getOrCreateStack(windowingMode,
+ activityType, false /* onTop */);
} else {
targetTask = mTargetStack.reuseOrCreateTask(r.info, null /*intent*/,
false /*toTop*/);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index ff17427..26eb36f 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -36,7 +36,6 @@
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
@@ -1138,7 +1137,7 @@
// While a dream or keyguard is showing, obscure ordinary application content on
// secondary displays (by forcibly enabling mirroring unless there is other content
// we want to show) but still allow opaque keyguard dialogs to be shown.
- if (type == TYPE_DREAM || mWmService.mPolicy.isKeyguardShowing()) {
+ if (w.isDreamWindow() || mWmService.mPolicy.isKeyguardShowing()) {
mObscureApplicationContentOnSecondaryDisplays = true;
}
displayHasContent = true;
@@ -1372,7 +1371,8 @@
final DisplayContent defaultDisplay = getDefaultDisplay();
- defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+ defaultDisplay.mTaskContainers.getOrCreateStack(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_HOME, ON_TOP);
positionChildAt(POSITION_TOP, defaultDisplay, false /* includingParents */);
}
@@ -1441,7 +1441,7 @@
}
ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) {
- return getDisplayContent(DEFAULT_DISPLAY).getHomeActivityForUser(userId);
+ return getDisplayContent(DEFAULT_DISPLAY).mTaskContainers.getHomeActivityForUser(userId);
}
boolean startHomeOnAllDisplays(int userId, String reason) {
@@ -1637,7 +1637,7 @@
displayId = DEFAULT_DISPLAY;
}
- final ActivityRecord r = getDisplayContent(displayId).getHomeActivity();
+ final ActivityRecord r = getDisplayContent(displayId).mTaskContainers.getHomeActivity();
final String myReason = reason + " resumeHomeActivity";
// Only resume home activity if isn't finishing.
@@ -1838,7 +1838,8 @@
// focus order.
for (int i = getChildCount() - 1; i >= 0; --i) {
final DisplayContent display = getChildAt(i);
- final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity();
+ final ActivityRecord resumedActivityOnDisplay = display.mTaskContainers
+ .getResumedActivity();
if (resumedActivityOnDisplay != null) {
return resumedActivityOnDisplay;
}
@@ -1971,8 +1972,8 @@
final int focusStackId = topFocusedStack != null
? topFocusedStack.getRootTaskId() : INVALID_TASK_ID;
// We dismiss the docked stack whenever we switch users.
- if (getDefaultDisplay().isSplitScreenModeActivated()) {
- getDefaultDisplay().onSplitScreenModeDismissed();
+ if (getDefaultDisplay().mTaskContainers.isSplitScreenModeActivated()) {
+ getDefaultDisplay().mTaskContainers.onSplitScreenModeDismissed();
}
// Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
// also cause all tasks to be moved to the fullscreen stack at a position that is
@@ -1994,7 +1995,7 @@
final int restoreStackId = mUserStackInFront.get(userId);
ActivityStack stack = getStack(restoreStackId);
if (stack == null) {
- stack = getDefaultDisplay().getOrCreateRootHomeTask();
+ stack = getDefaultDisplay().mTaskContainers.getOrCreateRootHomeTask();
}
final boolean homeInFront = stack.isActivityTypeHome();
if (stack.isOnHomeDisplay()) {
@@ -2017,7 +2018,7 @@
void updateUserStack(int userId, ActivityStack stack) {
if (userId != mCurrentUser) {
if (stack == null) {
- stack = getDefaultDisplay().getOrCreateRootHomeTask();
+ stack = getDefaultDisplay().mTaskContainers.getOrCreateRootHomeTask();
}
mUserStackInFront.put(userId, stack.getRootTaskId());
@@ -2114,8 +2115,9 @@
} else {
// In the case of multiple activities, we will create a new task for it and then
// move the PIP activity into the task.
- stack = display.createStack(WINDOWING_MODE_PINNED, r.getActivityType(), ON_TOP,
- r.info, r.intent, false /* createdByOrganizer */);
+ stack = display.mTaskContainers.createStack(WINDOWING_MODE_PINNED,
+ r.getActivityType(), ON_TOP, r.info, r.intent,
+ false /* createdByOrganizer */);
// There are multiple activities in the task and moving the top activity should
// reveal/leave the other activities in their original task.
@@ -2154,7 +2156,8 @@
// Looking up task on preferred display first
final DisplayContent preferredDisplay = getDisplayContent(preferredDisplayId);
if (preferredDisplay != null) {
- preferredDisplay.findTaskLocked(r, true /* isPreferredDisplay */, mTmpFindTaskResult);
+ preferredDisplay.mTaskContainers.findTaskLocked(r, true /* isPreferredDisplay */,
+ mTmpFindTaskResult);
if (mTmpFindTaskResult.mIdealMatch) {
return mTmpFindTaskResult.mRecord;
}
@@ -2166,7 +2169,8 @@
continue;
}
- display.findTaskLocked(r, false /* isPreferredDisplay */, mTmpFindTaskResult);
+ display.mTaskContainers.findTaskLocked(r, false /* isPreferredDisplay */,
+ mTmpFindTaskResult);
if (mTmpFindTaskResult.mIdealMatch) {
return mTmpFindTaskResult.mRecord;
}
@@ -2233,7 +2237,8 @@
resumedOnDisplay |= result;
continue;
}
- if (display.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
+ if (display.mTaskContainers.isTopStack(stack)
+ && topRunningActivity.isState(RESUMED)) {
// Kick off any lingering app transitions form the MoveTaskToFront operation,
// but only consider the top task and stack on that display.
stack.executeAppTransition(targetOptions);
@@ -2289,6 +2294,9 @@
TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false);
}
stack.awakeFromSleepingLocked();
+ if (display.isSingleTaskInstance()) {
+ display.executeAppTransition();
+ }
if (stack.isFocusedStackOnDisplay()
&& !mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(display.mDisplayId)) {
@@ -2305,7 +2313,7 @@
protected ActivityStack getStack(int stackId) {
for (int i = getChildCount() - 1; i >= 0; --i) {
- final ActivityStack stack = getChildAt(i).getStack(stackId);
+ final ActivityStack stack = getChildAt(i).mTaskContainers.getStack(stackId);
if (stack != null) {
return stack;
}
@@ -2781,7 +2789,8 @@
}
final DisplayContent display = getDisplayContentOrCreate(displayId);
if (display != null) {
- stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
+ stack = display.mTaskContainers.getOrCreateStack(r, options, candidateTask,
+ activityType, onTop);
if (stack != null) {
return stack;
}
@@ -2803,8 +2812,8 @@
display = stack.getDisplay();
if (display != null && canLaunchOnDisplay(r, display.mDisplayId)) {
if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
- windowingMode = display.resolveWindowingMode(r, options, candidateTask,
- activityType);
+ windowingMode = display.mTaskContainers.resolveWindowingMode(r, options,
+ candidateTask, activityType);
}
// Always allow organized tasks that created by organizer since the activity type
// of an organized task is decided by the activity type of its top child, which
@@ -2828,12 +2837,13 @@
if (display == null || !canLaunchOnDisplay(r, display.mDisplayId)) {
display = getDefaultDisplay();
if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
- windowingMode = display.resolveWindowingMode(r, options, candidateTask,
- activityType);
+ windowingMode = display.mTaskContainers.resolveWindowingMode(r, options,
+ candidateTask, activityType);
}
}
- return display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
+ return display.mTaskContainers.getOrCreateStack(r, options, candidateTask, activityType,
+ onTop);
}
/** @return true if activity record is null or can be launched on provided display. */
@@ -2893,8 +2903,8 @@
windowingMode = options != null ? options.getLaunchWindowingMode()
: r.getWindowingMode();
}
- windowingMode = displayContent.validateWindowingMode(windowingMode, r, candidateTask,
- r.getActivityType());
+ windowingMode = displayContent.mTaskContainers.validateWindowingMode(windowingMode, r,
+ candidateTask, r.getActivityType());
// Return the topmost valid stack on the display.
for (int i = displayContent.getStackCount() - 1; i >= 0; --i) {
@@ -2982,8 +2992,8 @@
// was on.
preferredDisplay = getDisplayContent(currentFocus.mPrevDisplayId);
}
- final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack(
- currentFocus, ignoreCurrent);
+ final ActivityStack preferredFocusableStack = preferredDisplay.mTaskContainers
+ .getNextFocusableStack(currentFocus, ignoreCurrent);
if (preferredFocusableStack != null) {
return preferredFocusableStack;
}
@@ -3001,8 +3011,8 @@
// We've already checked this one
continue;
}
- final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus,
- ignoreCurrent);
+ final ActivityStack nextFocusableStack = display.mTaskContainers
+ .getNextFocusableStack(currentFocus, ignoreCurrent);
if (nextFocusableStack != null) {
return nextFocusableStack;
}
@@ -3414,7 +3424,8 @@
boolean allFocusedProcessesDiffer = true;
for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
final DisplayContent displayContent = getChildAt(displayNdx);
- final ActivityRecord resumedActivity = displayContent.getResumedActivity();
+ final ActivityRecord resumedActivity = displayContent.mTaskContainers
+ .getResumedActivity();
final WindowProcessController resumedActivityProcess =
resumedActivity == null ? null : resumedActivity.app;
@@ -3485,6 +3496,7 @@
final DisplayContent display = getChildAt(i);
display.dump(pw, prefix, true /* dumpAll */);
}
+ pw.println();
}
/**
@@ -3515,8 +3527,8 @@
printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
needSep = printed;
}
- printThisActivity(pw, displayContent.getResumedActivity(), dumpPackage, needSep,
- " ResumedActivity:");
+ printThisActivity(pw, displayContent.mTaskContainers.getResumedActivity(), dumpPackage,
+ needSep, " ResumedActivity:");
}
printed |= dumpHistoryList(fd, pw, mStackSupervisor.mFinishingActivities, " ",
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7a41ea5..10be11a 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -258,7 +258,7 @@
boolean autoRemoveRecents; // If true, we should automatically remove the task from
// recents when activity finishes
boolean askedCompatMode;// Have asked the user about compat mode for this task.
- boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.
+ private boolean mHasBeenVisible; // Set if any activities in the task have been visible
String stringName; // caching of toString() result.
boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
@@ -483,6 +483,10 @@
*/
ITaskOrganizer mTaskOrganizer;
private int mLastTaskOrganizerWindowingMode = -1;
+ /**
+ * Prevent duplicate calls to onTaskAppeared.
+ */
+ boolean mTaskAppearedSent;
/**
* Last Picture-in-Picture params applicable to the task. Updated when the app
@@ -1382,7 +1386,7 @@
// A rootable task that is now being added to be the child of an organized task. Making
// sure the stack references is keep updated.
if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) {
- mDisplayContent.addStackReferenceIfNeeded((ActivityStack) child);
+ mDisplayContent.mTaskContainers.addStackReferenceIfNeeded((ActivityStack) child);
}
// Make sure the list of display UID whitelists is updated
@@ -1428,7 +1432,7 @@
// A rootable child task that is now being removed from an organized task. Making sure
// the stack references is keep updated.
if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) {
- mDisplayContent.removeStackReferenceIfNeeded((ActivityStack) child);
+ mDisplayContent.mTaskContainers.removeStackReferenceIfNeeded((ActivityStack) child);
}
removeChild(child, "removeChild");
}
@@ -1517,7 +1521,7 @@
// We will automatically remove the task either if it has explicitly asked for
// this, or it is empty and has never contained an activity that got shown to
// the user.
- return autoRemoveRecents || (!hasChild() && !hasBeenVisible);
+ return autoRemoveRecents || (!hasChild() && !getHasBeenVisible());
}
/**
@@ -2030,7 +2034,7 @@
}
private void saveLaunchingStateIfNeeded(DisplayContent display) {
- if (!hasBeenVisible) {
+ if (!getHasBeenVisible()) {
// Not ever visible to user.
return;
}
@@ -3558,7 +3562,7 @@
pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
}
pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId());
- pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
+ pw.print(prefix + "mHasBeenVisible=" + getHasBeenVisible());
pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
pw.print(" isResizeable=" + isResizeable());
@@ -4087,14 +4091,42 @@
super.reparentSurfaceControl(t, newParent);
}
+ void setHasBeenVisible(boolean hasBeenVisible) {
+ mHasBeenVisible = hasBeenVisible;
+ if (hasBeenVisible) {
+ sendTaskAppeared();
+ if (!isRootTask()) {
+ getRootTask().setHasBeenVisible(true);
+ }
+ }
+ }
+
+ boolean getHasBeenVisible() {
+ return mHasBeenVisible;
+ }
+
+ /** In the case that these three conditions are true, we want to send the Task to
+ * the organizer:
+ * 1. We have a SurfaceControl
+ * 2. An organizer has been set
+ * 3. We have finished drawing
+ * Any time any of these conditions are updated, the updating code should call
+ * sendTaskAppeared.
+ */
+ private boolean taskAppearedReady() {
+ return mSurfaceControl != null && mTaskOrganizer != null && getHasBeenVisible();
+ }
+
private void sendTaskAppeared() {
- if (mSurfaceControl != null && mTaskOrganizer != null) {
+ if (taskAppearedReady() && !mTaskAppearedSent) {
+ mTaskAppearedSent = true;
mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this);
}
}
private void sendTaskVanished() {
- if (mTaskOrganizer != null) {
+ if (mTaskOrganizer != null && mTaskAppearedSent) {
+ mTaskAppearedSent = false;
mAtmService.mTaskOrganizerController.onTaskVanished(mTaskOrganizer, this);
}
}
@@ -4113,6 +4145,7 @@
void taskOrganizerUnregistered() {
mTaskOrganizer = null;
+ mTaskAppearedSent = false;
mLastTaskOrganizerWindowingMode = -1;
onTaskOrganizerChanged();
if (mCreatedByOrganizer) {
diff --git a/services/core/java/com/android/server/wm/TaskContainers.java b/services/core/java/com/android/server/wm/TaskContainers.java
new file mode 100644
index 0000000..540bc9b
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TaskContainers.java
@@ -0,0 +1,1533 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+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;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+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.app.WindowConfiguration.isSplitScreenWindowingMode;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.window.WindowOrganizer.DisplayAreaOrganizer.FEATURE_TASK_CONTAINER;
+
+import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
+import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
+import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
+import static com.android.server.wm.DisplayContent.alwaysCreateStack;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.server.wm.RootWindowContainer.TAG_STATES;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.annotation.Nullable;
+import android.app.ActivityOptions;
+import android.app.WindowConfiguration;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.os.UserHandle;
+import android.util.Slog;
+import android.view.SurfaceControl;
+import android.window.WindowContainerTransaction;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ToBooleanFunction;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.internal.util.function.pooled.PooledPredicate;
+import com.android.server.protolog.common.ProtoLog;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Window container class that contains all containers on this display relating to Apps.
+ * I.e Activities.
+ */
+final class TaskContainers extends DisplayArea<ActivityStack> {
+ private DisplayContent mDisplayContent;
+ /**
+ * A control placed at the appropriate level for transitions to occur.
+ */
+ private SurfaceControl mAppAnimationLayer;
+ private SurfaceControl mBoostedAppAnimationLayer;
+ private SurfaceControl mHomeAppAnimationLayer;
+
+ /**
+ * Given that the split-screen divider does not have an AppWindowToken, it
+ * will have to live inside of a "NonAppWindowContainer". However, in visual Z order
+ * it will need to be interleaved with some of our children, appearing on top of
+ * both docked stacks but underneath any assistant stacks.
+ *
+ * To solve this problem we have this anchor control, which will always exist so
+ * we can always assign it the correct value in our {@link #assignChildLayers}.
+ * Likewise since it always exists, we can always
+ * assign the divider a layer relative to it. This way we prevent linking lifecycle
+ * events between tasks and the divider window.
+ */
+ private SurfaceControl mSplitScreenDividerAnchor;
+
+ // Cached reference to some special tasks we tend to get a lot so we don't need to loop
+ // through the list to find them.
+ private ActivityStack mRootHomeTask;
+ private ActivityStack mRootPinnedTask;
+ private ActivityStack mRootSplitScreenPrimaryTask;
+
+ private final ArrayList<ActivityStack> mTmpAlwaysOnTopStacks = new ArrayList<>();
+ private final ArrayList<ActivityStack> mTmpNormalStacks = new ArrayList<>();
+ private final ArrayList<ActivityStack> mTmpHomeStacks = new ArrayList<>();
+
+ private ArrayList<Task> mTmpTasks = new ArrayList<>();
+
+ private ActivityTaskManagerService mAtmService;
+
+ private RootWindowContainer mRootWindowContainer;
+
+ // When non-null, new tasks get put into this root task.
+ private Task mLaunchRootTask = null;
+
+ /**
+ * A focusable stack that is purposely to be positioned at the top. Although the stack may not
+ * have the topmost index, it is used as a preferred candidate to prevent being unable to resume
+ * target stack properly when there are other focusable always-on-top stacks.
+ */
+ private ActivityStack mPreferredTopFocusableStack;
+
+ private final RootWindowContainer.FindTaskResult
+ mTmpFindTaskResult = new RootWindowContainer.FindTaskResult();
+
+ /**
+ * If this is the same as {@link #getFocusedStack} then the activity on the top of the focused
+ * stack has been resumed. If stacks are changing position this will hold the old stack until
+ * the new stack becomes resumed after which it will be set to current focused stack.
+ */
+ ActivityStack mLastFocusedStack;
+
+ TaskContainers(DisplayContent displayContent, WindowManagerService service) {
+ super(service, Type.ANY, "TaskContainers", FEATURE_TASK_CONTAINER);
+ mDisplayContent = displayContent;
+ mRootWindowContainer = service.mRoot;
+ mAtmService = service.mAtmService;
+ }
+
+ /**
+ * Returns the topmost stack on the display that is compatible with the input windowing mode
+ * and activity type. Null is no compatible stack on the display.
+ */
+ ActivityStack getStack(int windowingMode, int activityType) {
+ if (activityType == ACTIVITY_TYPE_HOME) {
+ return mRootHomeTask;
+ }
+ if (windowingMode == WINDOWING_MODE_PINNED) {
+ return mRootPinnedTask;
+ } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ return mRootSplitScreenPrimaryTask;
+ }
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getChildAt(i);
+ if (activityType == ACTIVITY_TYPE_UNDEFINED
+ && windowingMode == stack.getWindowingMode()) {
+ // Passing in undefined type means we want to match the topmost stack with the
+ // windowing mode.
+ return stack;
+ }
+ if (stack.isCompatible(windowingMode, activityType)) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
+ @VisibleForTesting
+ ActivityStack getTopStack() {
+ final int count = getChildCount();
+ return count > 0 ? getChildAt(count - 1) : null;
+ }
+
+ int getIndexOf(ActivityStack stack) {
+ return mChildren.indexOf(stack);
+ }
+
+ ActivityStack getRootHomeTask() {
+ return mRootHomeTask;
+ }
+
+ ActivityStack getRootPinnedTask() {
+ return mRootPinnedTask;
+ }
+
+ ActivityStack getRootSplitScreenPrimaryTask() {
+ return mRootSplitScreenPrimaryTask;
+ }
+
+ ArrayList<Task> getVisibleTasks() {
+ final ArrayList<Task> visibleTasks = new ArrayList<>();
+ forAllTasks(task -> {
+ if (task.isLeafTask() && task.isVisible()) {
+ visibleTasks.add(task);
+ }
+ });
+ return visibleTasks;
+ }
+
+ void onStackWindowingModeChanged(ActivityStack stack) {
+ removeStackReferenceIfNeeded(stack);
+ addStackReferenceIfNeeded(stack);
+ if (stack == mRootPinnedTask && getTopStack() != stack) {
+ // Looks like this stack changed windowing mode to pinned. Move it to the top.
+ positionChildAt(POSITION_TOP, stack, false /* includingParents */);
+ }
+ }
+
+ void addStackReferenceIfNeeded(ActivityStack stack) {
+ if (stack.isActivityTypeHome()) {
+ if (mRootHomeTask != null) {
+ if (!stack.isDescendantOf(mRootHomeTask)) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+ + mRootHomeTask + " already exist on display=" + this
+ + " stack=" + stack);
+ }
+ } else {
+ mRootHomeTask = stack;
+ }
+ }
+
+ if (!stack.isRootTask()) {
+ return;
+ }
+ final int windowingMode = stack.getWindowingMode();
+ if (windowingMode == WINDOWING_MODE_PINNED) {
+ if (mRootPinnedTask != null) {
+ throw new IllegalArgumentException(
+ "addStackReferenceIfNeeded: pinned stack=" + mRootPinnedTask
+ + " already exist on display=" + this + " stack=" + stack);
+ }
+ mRootPinnedTask = stack;
+ } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ if (mRootSplitScreenPrimaryTask != null) {
+ throw new IllegalArgumentException(
+ "addStackReferenceIfNeeded: split screen primary stack="
+ + mRootSplitScreenPrimaryTask
+ + " already exist on display=" + this + " stack=" + stack);
+ }
+ mRootSplitScreenPrimaryTask = stack;
+ }
+ }
+
+ void removeStackReferenceIfNeeded(ActivityStack stack) {
+ if (stack == mRootHomeTask) {
+ mRootHomeTask = null;
+ } else if (stack == mRootPinnedTask) {
+ mRootPinnedTask = null;
+ } else if (stack == mRootSplitScreenPrimaryTask) {
+ mRootSplitScreenPrimaryTask = null;
+ }
+ }
+
+ @Override
+ void addChild(ActivityStack stack, int position) {
+ addStackReferenceIfNeeded(stack);
+ position = findPositionForStack(position, stack, true /* adding */);
+
+ super.addChild(stack, position);
+ mAtmService.updateSleepIfNeededLocked();
+
+ // The reparenting case is handled in WindowContainer.
+ if (!stack.mReparenting) {
+ mDisplayContent.setLayoutNeeded();
+ }
+ }
+
+ @Override
+ protected void removeChild(ActivityStack stack) {
+ super.removeChild(stack);
+ onStackRemoved(stack);
+ mAtmService.updateSleepIfNeededLocked();
+ removeStackReferenceIfNeeded(stack);
+ }
+
+ @Override
+ boolean isOnTop() {
+ // Considered always on top
+ return true;
+ }
+
+ @Override
+ void positionChildAt(int position, ActivityStack child, boolean includingParents) {
+ final boolean moveToTop = (position == POSITION_TOP || position == getChildCount());
+ final boolean moveToBottom = (position == POSITION_BOTTOM || position == 0);
+ if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) {
+ // This stack is always-on-top, override the default behavior.
+ Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
+
+ // Moving to its current position, as we must call super but we don't want to
+ // perform any meaningful action.
+ final int currentPosition = mChildren.indexOf(child);
+ super.positionChildAt(currentPosition, child, false /* includingParents */);
+ return;
+ }
+ // We don't allow untrusted display to top when task stack moves to top,
+ // until user tapping this display to change display position as top intentionally.
+ if (mDisplayContent.isUntrustedVirtualDisplay() && !getParent().isOnTop()) {
+ includingParents = false;
+ }
+ final int targetPosition = findPositionForStack(position, child, false /* adding */);
+ super.positionChildAt(targetPosition, child, false /* includingParents */);
+
+ if (includingParents && (moveToTop || moveToBottom)) {
+ // The DisplayContent children do not re-order, but we still want to move the
+ // display of this stack container because the intention of positioning is to have
+ // higher z-order to gain focus.
+ mDisplayContent.positionDisplayAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM,
+ true /* includingParents */);
+ }
+
+ child.updateTaskMovement(moveToTop);
+
+ mDisplayContent.setLayoutNeeded();
+ }
+
+ /**
+ * When stack is added or repositioned, find a proper position for it.
+ * This will make sure that pinned stack always stays on top.
+ * @param requestedPosition Position requested by caller.
+ * @param stack Stack to be added or positioned.
+ * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
+ * @return The proper position for the stack.
+ */
+ private int findPositionForStack(int requestedPosition, ActivityStack stack,
+ boolean adding) {
+ if (stack.isActivityTypeDream()) {
+ return POSITION_TOP;
+ }
+
+ if (stack.inPinnedWindowingMode()) {
+ return POSITION_TOP;
+ }
+
+ final int topChildPosition = mChildren.size() - 1;
+ int belowAlwaysOnTopPosition = POSITION_BOTTOM;
+ for (int i = topChildPosition; i >= 0; --i) {
+ // Since a stack could be repositioned while being one of the child, return
+ // current index if that's the same stack we are positioning and it is always on
+ // top.
+ final boolean sameStack = mDisplayContent.getStacks().get(i) == stack;
+ if ((sameStack && stack.isAlwaysOnTop())
+ || (!sameStack && !mDisplayContent.getStacks().get(i).isAlwaysOnTop())) {
+ belowAlwaysOnTopPosition = i;
+ break;
+ }
+ }
+
+ // The max possible position we can insert the stack at.
+ int maxPosition = POSITION_TOP;
+ // The min possible position we can insert the stack at.
+ int minPosition = POSITION_BOTTOM;
+
+ if (stack.isAlwaysOnTop()) {
+ if (mDisplayContent.hasPinnedTask()) {
+ // Always-on-top stacks go below the pinned stack.
+ maxPosition = mDisplayContent.getStacks().indexOf(mRootPinnedTask) - 1;
+ }
+ // Always-on-top stacks need to be above all other stacks.
+ minPosition = belowAlwaysOnTopPosition
+ != POSITION_BOTTOM ? belowAlwaysOnTopPosition : topChildPosition;
+ } else {
+ // Other stacks need to be below the always-on-top stacks.
+ maxPosition = belowAlwaysOnTopPosition
+ != POSITION_BOTTOM ? belowAlwaysOnTopPosition : 0;
+ }
+
+ // Cap the requested position to something reasonable for the previous position check
+ // below.
+ if (requestedPosition == POSITION_TOP) {
+ requestedPosition = mChildren.size();
+ } else if (requestedPosition == POSITION_BOTTOM) {
+ requestedPosition = 0;
+ }
+
+ int targetPosition = requestedPosition;
+ targetPosition = Math.min(targetPosition, maxPosition);
+ targetPosition = Math.max(targetPosition, minPosition);
+
+ int prevPosition = mDisplayContent.getStacks().indexOf(stack);
+ // The positions we calculated above (maxPosition, minPosition) do not take into
+ // consideration the following edge cases.
+ // 1) We need to adjust the position depending on the value "adding".
+ // 2) When we are moving a stack to another position, we also need to adjust the
+ // position depending on whether the stack is moving to a higher or lower position.
+ if ((targetPosition != requestedPosition) && (adding || targetPosition < prevPosition)) {
+ targetPosition++;
+ }
+
+ return targetPosition;
+ }
+
+ @Override
+ boolean forAllWindows(ToBooleanFunction<WindowState> callback,
+ boolean traverseTopToBottom) {
+ if (traverseTopToBottom) {
+ if (super.forAllWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ } else {
+ if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ if (super.forAllWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
+ boolean traverseTopToBottom) {
+ // For legacy reasons we process the TaskStack.mExitingActivities first here before the
+ // app tokens.
+ // TODO: Investigate if we need to continue to do this or if we can just process them
+ // in-order.
+ if (traverseTopToBottom) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+ for (int j = activities.size() - 1; j >= 0; --j) {
+ if (activities.get(j).forAllWindowsUnchecked(callback,
+ traverseTopToBottom)) {
+ return true;
+ }
+ }
+ }
+ } else {
+ final int count = mChildren.size();
+ for (int i = 0; i < count; ++i) {
+ final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+ final int appTokensCount = activities.size();
+ for (int j = 0; j < appTokensCount; j++) {
+ if (activities.get(j).forAllWindowsUnchecked(callback,
+ traverseTopToBottom)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ void setExitingTokensHasVisible(boolean hasVisible) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+ for (int j = activities.size() - 1; j >= 0; --j) {
+ activities.get(j).hasVisible = hasVisible;
+ }
+ }
+ }
+
+ void removeExistingAppTokensIfPossible() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+ for (int j = activities.size() - 1; j >= 0; --j) {
+ final ActivityRecord activity = activities.get(j);
+ if (!activity.hasVisible && !mDisplayContent.mClosingApps.contains(activity)
+ && (!activity.mIsExiting || activity.isEmpty())) {
+ // Make sure there is no animation running on this activity, so any windows
+ // associated with it will be removed as soon as their animations are
+ // complete.
+ cancelAnimation();
+ ProtoLog.v(WM_DEBUG_ADD_REMOVE,
+ "performLayout: Activity exiting now removed %s", activity);
+ activity.removeIfPossible();
+ }
+ }
+ }
+ }
+
+ @Override
+ int getOrientation(int candidate) {
+ if (mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
+ // Apps and their containers are not allowed to specify an orientation while using
+ // root tasks...except for the home stack if it is not resizable and currently
+ // visible (top of) its root task.
+ if (mRootHomeTask != null && mRootHomeTask.isVisible()) {
+ final Task topMost = mRootHomeTask.getTopMostTask();
+ final boolean resizable = topMost != null && topMost.isResizeable();
+ if (!(resizable && mRootHomeTask.matchParentBounds())) {
+ final int orientation = mRootHomeTask.getOrientation();
+ if (orientation != SCREEN_ORIENTATION_UNSET) {
+ return orientation;
+ }
+ }
+ }
+ return SCREEN_ORIENTATION_UNSPECIFIED;
+ }
+
+ final int orientation = super.getOrientation(candidate);
+ if (orientation != SCREEN_ORIENTATION_UNSET
+ && orientation != SCREEN_ORIENTATION_BEHIND) {
+ ProtoLog.v(WM_DEBUG_ORIENTATION,
+ "App is requesting an orientation, return %d for display id=%d",
+ orientation, mDisplayContent.mDisplayId);
+ return orientation;
+ }
+
+ ProtoLog.v(WM_DEBUG_ORIENTATION,
+ "No app is requesting an orientation, return %d for display id=%d",
+ mDisplayContent.getLastOrientation(), mDisplayContent.mDisplayId);
+ // The next app has not been requested to be visible, so we keep the current orientation
+ // to prevent freezing/unfreezing the display too early.
+ return mDisplayContent.getLastOrientation();
+ }
+
+ @Override
+ void assignChildLayers(SurfaceControl.Transaction t) {
+ assignStackOrdering(t);
+
+ for (int i = 0; i < mChildren.size(); i++) {
+ final ActivityStack s = mChildren.get(i);
+ s.assignChildLayers(t);
+ }
+ }
+
+ void assignStackOrdering(SurfaceControl.Transaction t) {
+ if (getParent() == null) {
+ return;
+ }
+ mTmpAlwaysOnTopStacks.clear();
+ mTmpHomeStacks.clear();
+ mTmpNormalStacks.clear();
+ for (int i = 0; i < mChildren.size(); ++i) {
+ final ActivityStack s = mChildren.get(i);
+ if (s.isAlwaysOnTop()) {
+ mTmpAlwaysOnTopStacks.add(s);
+ } else if (s.isActivityTypeHome()) {
+ mTmpHomeStacks.add(s);
+ } else {
+ mTmpNormalStacks.add(s);
+ }
+ }
+
+ int layer = 0;
+ // Place home stacks to the bottom.
+ for (int i = 0; i < mTmpHomeStacks.size(); i++) {
+ mTmpHomeStacks.get(i).assignLayer(t, layer++);
+ }
+ // The home animation layer is between the home stacks and the normal stacks.
+ final int layerForHomeAnimationLayer = layer++;
+ int layerForSplitScreenDividerAnchor = layer++;
+ int layerForAnimationLayer = layer++;
+ for (int i = 0; i < mTmpNormalStacks.size(); i++) {
+ final ActivityStack s = mTmpNormalStacks.get(i);
+ s.assignLayer(t, layer++);
+ if (s.inSplitScreenWindowingMode()) {
+ // The split screen divider anchor is located above the split screen window.
+ layerForSplitScreenDividerAnchor = layer++;
+ }
+ if (s.isTaskAnimating() || s.isAppTransitioning()) {
+ // The animation layer is located above the highest animating stack and no
+ // higher.
+ layerForAnimationLayer = layer++;
+ }
+ }
+ // The boosted animation layer is between the normal stacks and the always on top
+ // stacks.
+ final int layerForBoostedAnimationLayer = layer++;
+ for (int i = 0; i < mTmpAlwaysOnTopStacks.size(); i++) {
+ mTmpAlwaysOnTopStacks.get(i).assignLayer(t, layer++);
+ }
+
+ t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer);
+ t.setLayer(mAppAnimationLayer, layerForAnimationLayer);
+ t.setLayer(mSplitScreenDividerAnchor, layerForSplitScreenDividerAnchor);
+ t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
+ }
+
+ @Override
+ SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
+ switch (animationLayer) {
+ case ANIMATION_LAYER_BOOSTED:
+ return mBoostedAppAnimationLayer;
+ case ANIMATION_LAYER_HOME:
+ return mHomeAppAnimationLayer;
+ case ANIMATION_LAYER_STANDARD:
+ default:
+ return mAppAnimationLayer;
+ }
+ }
+
+ SurfaceControl getSplitScreenDividerAnchor() {
+ return mSplitScreenDividerAnchor;
+ }
+
+ @Override
+ void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
+ if (getParent() != null) {
+ super.onParentChanged(newParent, oldParent, () -> {
+ mAppAnimationLayer = makeChildSurface(null)
+ .setName("animationLayer")
+ .build();
+ mBoostedAppAnimationLayer = makeChildSurface(null)
+ .setName("boostedAnimationLayer")
+ .build();
+ mHomeAppAnimationLayer = makeChildSurface(null)
+ .setName("homeAnimationLayer")
+ .build();
+ mSplitScreenDividerAnchor = makeChildSurface(null)
+ .setName("splitScreenDividerAnchor")
+ .build();
+ getPendingTransaction()
+ .show(mAppAnimationLayer)
+ .show(mBoostedAppAnimationLayer)
+ .show(mHomeAppAnimationLayer)
+ .show(mSplitScreenDividerAnchor);
+ });
+ } else {
+ super.onParentChanged(newParent, oldParent);
+ mWmService.mTransactionFactory.get()
+ .remove(mAppAnimationLayer)
+ .remove(mBoostedAppAnimationLayer)
+ .remove(mHomeAppAnimationLayer)
+ .remove(mSplitScreenDividerAnchor)
+ .apply();
+ mAppAnimationLayer = null;
+ mBoostedAppAnimationLayer = null;
+ mHomeAppAnimationLayer = null;
+ mSplitScreenDividerAnchor = null;
+ }
+ }
+
+ void addStack(ActivityStack stack, int position) {
+ mDisplayContent.setStackOnDisplay(stack, position);
+ positionStackAt(stack, position);
+ }
+
+ void onStackRemoved(ActivityStack stack) {
+ if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
+ Slog.v(TAG_STACK, "removeStack: detaching " + stack + " from displayId="
+ + mDisplayContent.mDisplayId);
+ }
+ if (mPreferredTopFocusableStack == stack) {
+ mPreferredTopFocusableStack = null;
+ }
+ mDisplayContent.releaseSelfIfNeeded();
+ mDisplayContent.onStackOrderChanged(stack);
+ }
+
+ void positionStackAt(int position, ActivityStack child, boolean includingParents) {
+ positionChildAt(position, child, includingParents);
+ mDisplayContent.layoutAndAssignWindowLayersIfNeeded();
+ }
+
+ void positionStackAtTop(ActivityStack stack, boolean includingParents) {
+ positionStackAtTop(stack, includingParents, null /* updateLastFocusedStackReason */);
+ }
+
+ void positionStackAtTop(ActivityStack stack, boolean includingParents,
+ String updateLastFocusedStackReason) {
+ positionStackAt(stack, getStackCount(), includingParents,
+ updateLastFocusedStackReason);
+ }
+
+ void positionStackAtBottom(ActivityStack stack) {
+ positionStackAtBottom(stack, null /* updateLastFocusedStackReason */);
+ }
+
+ void positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason) {
+ positionStackAt(stack, 0, false /* includingParents */,
+ updateLastFocusedStackReason);
+ }
+
+ void positionStackAt(ActivityStack stack, int position) {
+ positionStackAt(stack, position, false /* includingParents */,
+ null /* updateLastFocusedStackReason */);
+ }
+
+ void positionStackAt(ActivityStack stack, int position, boolean includingParents,
+ String updateLastFocusedStackReason) {
+ // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
+ // the position internally, also update the logic here
+ final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
+ ? getFocusedStack() : null;
+ final boolean wasContained = getIndexOf(stack) >= 0;
+ if (mDisplayContent.mSingleTaskInstance && getStackCount() == 1 && !wasContained) {
+ throw new IllegalStateException(
+ "positionStackAt: Can only have one task on display=" + this);
+ }
+
+ final boolean movingToTop = wasContained && position >= getStackCount() - 1;
+ // Reset mPreferredTopFocusableStack before positioning to top or {@link
+ // ActivityStackSupervisor#updateTopResumedActivityIfNeeded()} won't update the top
+ // resumed activity.
+ if (movingToTop && stack.isFocusable()) {
+ mPreferredTopFocusableStack = null;
+ }
+
+ // Since positionChildAt() is called during the creation process of pinned stacks,
+ // ActivityStack#getStack() can be null.
+ positionStackAt(position, stack, includingParents);
+
+ // The insert position may be adjusted to non-top when there is always-on-top stack. Since
+ // the original position is preferred to be top, the stack should have higher priority when
+ // we are looking for top focusable stack. The condition {@code wasContained} restricts the
+ // preferred stack is set only when moving an existing stack to top instead of adding a new
+ // stack that may be too early (e.g. in the middle of launching or reparenting).
+ if (movingToTop && stack.isFocusableAndVisible()) {
+ mPreferredTopFocusableStack = stack;
+ } else if (mPreferredTopFocusableStack == stack) {
+ mPreferredTopFocusableStack = null;
+ }
+
+ if (updateLastFocusedStackReason != null) {
+ final ActivityStack currentFocusedStack = getFocusedStack();
+ if (currentFocusedStack != prevFocusedStack) {
+ mLastFocusedStack = prevFocusedStack;
+ EventLogTags.writeWmFocusedStack(mRootWindowContainer.mCurrentUser,
+ mDisplayContent.mDisplayId,
+ currentFocusedStack == null ? -1 : currentFocusedStack.getRootTaskId(),
+ mLastFocusedStack == null ? -1 : mLastFocusedStack.getRootTaskId(),
+ updateLastFocusedStackReason);
+ }
+ }
+
+ mDisplayContent.onStackOrderChanged(stack);
+ }
+
+ ActivityStack getStack(int rootTaskId) {
+ for (int i = getStackCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getStackAt(i);
+ if (stack.getRootTaskId() == rootTaskId) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns an existing stack compatible with the windowing mode and activity type or creates one
+ * if a compatible stack doesn't exist.
+ * @see #getOrCreateStack(int, int, boolean, Intent, Task, boolean)
+ */
+ ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop) {
+ return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,
+ null /* candidateTask */, false /* createdByOrganizer */);
+ }
+
+ /**
+ * When two level tasks are required for given windowing mode and activity type, returns an
+ * existing compatible root task or creates a new one.
+ * For one level task, the candidate task would be reused to also be the root task or create
+ * a new root task if no candidate task.
+ * @see #getStack(int, int)
+ * @see #createStack(int, int, boolean)
+ */
+ ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop,
+ Intent intent, Task candidateTask, boolean createdByOrganizer) {
+ if (!alwaysCreateStack(windowingMode, activityType)) {
+ ActivityStack stack = getStack(windowingMode, activityType);
+ if (stack != null) {
+ return stack;
+ }
+ } else if (candidateTask != null) {
+ final ActivityStack stack = (ActivityStack) candidateTask;
+ final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
+ if (isSplitScreenModeActivated()) {
+ final Task splitRootSecondary = getTask(t -> t.mCreatedByOrganizer && t.isRootTask()
+ && t.inSplitScreenSecondaryWindowingMode());
+ if (stack.getParent() == null) {
+ splitRootSecondary.addChild(stack, position);
+ } else if (stack.getParent() != splitRootSecondary) {
+ stack.reparent(splitRootSecondary, position);
+ }
+ } else if (stack.getDisplay() != mDisplayContent || !stack.isRootTask()) {
+ if (stack.getParent() == null) {
+ addStack(stack, position);
+ } else {
+ stack.reparent(mDisplayContent, onTop);
+ }
+ }
+ // Update windowing mode if necessary, e.g. moving a pinned task to fullscreen.
+ if (candidateTask.getWindowingMode() != windowingMode) {
+ candidateTask.setWindowingMode(windowingMode);
+ }
+ return stack;
+ }
+ return createStack(windowingMode, activityType, onTop, null /*info*/, intent,
+ createdByOrganizer);
+ }
+
+ /**
+ * Returns an existing stack compatible with the input params or creates one
+ * if a compatible stack doesn't exist.
+ * @see #getOrCreateStack(int, int, boolean)
+ */
+ ActivityStack getOrCreateStack(@Nullable ActivityRecord r,
+ @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType,
+ boolean onTop) {
+ // First preference is the windowing mode in the activity options if set.
+ int windowingMode = (options != null)
+ ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
+ // Validate that our desired windowingMode will work under the current conditions.
+ // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
+ // it's display's windowing mode.
+ windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
+ return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,
+ candidateTask, false /* createdByOrganizer */);
+ }
+
+ @VisibleForTesting
+ int getNextStackId() {
+ return mAtmService.mStackSupervisor.getNextTaskIdForUser();
+ }
+
+ ActivityStack createStack(int windowingMode, int activityType, boolean onTop) {
+ return createStack(windowingMode, activityType, onTop, null /* info */, null /* intent */,
+ false /* createdByOrganizer */);
+ }
+
+ /**
+ * Creates a stack matching the input windowing mode and activity type on this display.
+ * @param windowingMode The windowing mode the stack should be created in. If
+ * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
+ * inherit its parent's windowing mode.
+ * @param activityType The activityType the stack should be created in. If
+ * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
+ * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
+ * @param onTop If true the stack will be created at the top of the display, else at the bottom.
+ * @param info The started activity info.
+ * @param intent The intent that started this task.
+ * @param createdByOrganizer @{code true} if this is created by task organizer, @{code false}
+ * otherwise.
+ * @return The newly created stack.
+ */
+ ActivityStack createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info,
+ Intent intent, boolean createdByOrganizer) {
+ if (mDisplayContent.mSingleTaskInstance && getStackCount() > 0) {
+ // Create stack on default display instead since this display can only contain 1 stack.
+ // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
+ // this goes away once ActivityView is no longer using virtual displays.
+ return mRootWindowContainer.getDefaultDisplay().mTaskContainers.createStack(
+ windowingMode, activityType, onTop, info, intent, createdByOrganizer);
+ }
+
+ if (activityType == ACTIVITY_TYPE_UNDEFINED && !createdByOrganizer) {
+ // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
+ // anything else should be passing it in anyways...except for the task organizer.
+ activityType = ACTIVITY_TYPE_STANDARD;
+ }
+
+ if (activityType != ACTIVITY_TYPE_STANDARD && activityType != ACTIVITY_TYPE_UNDEFINED) {
+ // For now there can be only one stack of a particular non-standard activity type on a
+ // display. So, get that ignoring whatever windowing mode it is currently in.
+ ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
+ if (stack != null) {
+ throw new IllegalArgumentException("Stack=" + stack + " of activityType="
+ + activityType + " already on display=" + this + ". Can't have multiple.");
+ }
+ }
+
+ if (!isWindowingModeSupported(windowingMode, mAtmService.mSupportsMultiWindow,
+ mAtmService.mSupportsSplitScreenMultiWindow,
+ mAtmService.mSupportsFreeformWindowManagement,
+ mAtmService.mSupportsPictureInPicture, activityType)) {
+ throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
+ + windowingMode);
+ }
+
+ final int stackId = getNextStackId();
+ return createStackUnchecked(windowingMode, activityType, stackId, onTop, info, intent,
+ createdByOrganizer);
+ }
+
+ /** @return the root task to create the next task in. */
+ private Task updateLaunchRootTask(int windowingMode) {
+ if (!isSplitScreenWindowingMode(windowingMode)) {
+ // Only split-screen windowing modes can do this currently...
+ return null;
+ }
+ for (int i = getStackCount() - 1; i >= 0; --i) {
+ final Task t = getStackAt(i);
+ if (!t.mCreatedByOrganizer || t.getRequestedOverrideWindowingMode() != windowingMode) {
+ continue;
+ }
+ // If not already set, pick a launch root which is not the one we are launching into.
+ if (mLaunchRootTask == null) {
+ for (int j = 0, n = getStackCount(); j < n; ++j) {
+ final Task tt = getStackAt(j);
+ if (tt.mCreatedByOrganizer && tt != t) {
+ mLaunchRootTask = tt;
+ break;
+ }
+ }
+ }
+ return t;
+ }
+ return mLaunchRootTask;
+ }
+
+ @VisibleForTesting
+ ActivityStack createStackUnchecked(int windowingMode, int activityType, int stackId,
+ boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer) {
+ if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
+ throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
+ + "activity type.");
+ }
+ if (info == null) {
+ info = new ActivityInfo();
+ info.applicationInfo = new ApplicationInfo();
+ }
+
+ // Task created by organizer are added as root.
+ Task launchRootTask = createdByOrganizer ? null : updateLaunchRootTask(windowingMode);
+ if (launchRootTask != null) {
+ // Since this stack will be put into a root task, its windowingMode will be inherited.
+ windowingMode = WINDOWING_MODE_UNDEFINED;
+ }
+
+ final ActivityStack stack = (ActivityStack) Task.create(mAtmService, stackId, activityType,
+ info, intent, createdByOrganizer);
+ if (launchRootTask != null) {
+ launchRootTask.addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
+ if (onTop) {
+ positionStackAtTop((ActivityStack) launchRootTask, false /* includingParents */);
+ }
+ } else {
+ addStack(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
+ stack.setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
+ false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
+ true /* creating */);
+ }
+ return stack;
+ }
+
+ /**
+ * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a
+ * focusable and visible stack from the top of stacks in this display.
+ */
+ ActivityStack getFocusedStack() {
+ if (mPreferredTopFocusableStack != null) {
+ return mPreferredTopFocusableStack;
+ }
+
+ for (int i = getStackCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getStackAt(i);
+ if (stack.isFocusableAndVisible()) {
+ return stack;
+ }
+ }
+
+ return null;
+ }
+
+ ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) {
+ final int currentWindowingMode = currentFocus != null
+ ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
+
+ ActivityStack candidate = null;
+ for (int i = getStackCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getStackAt(i);
+ if (ignoreCurrent && stack == currentFocus) {
+ continue;
+ }
+ if (!stack.isFocusableAndVisible()) {
+ continue;
+ }
+
+ if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+ && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
+ // If the currently focused stack is in split-screen secondary we save off the
+ // top primary split-screen stack as a candidate for focus because we might
+ // prefer focus to move to an other stack to avoid primary split-screen stack
+ // overlapping with a fullscreen stack when a fullscreen stack is higher in z
+ // than the next split-screen stack. Assistant stack, I am looking at you...
+ // We only move the focus to the primary-split screen stack if there isn't a
+ // better alternative.
+ candidate = stack;
+ continue;
+ }
+ if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) {
+ // Use the candidate stack since we are now at the secondary split-screen.
+ return candidate;
+ }
+ return stack;
+ }
+ return candidate;
+ }
+
+ ActivityRecord getResumedActivity() {
+ final ActivityStack focusedStack = getFocusedStack();
+ if (focusedStack == null) {
+ return null;
+ }
+ // TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
+ // Check if the focused stack has the resumed activity
+ ActivityRecord resumedActivity = focusedStack.getResumedActivity();
+ if (resumedActivity == null || resumedActivity.app == null) {
+ // If there is no registered resumed activity in the stack or it is not running -
+ // try to use previously resumed one.
+ resumedActivity = focusedStack.mPausingActivity;
+ if (resumedActivity == null || resumedActivity.app == null) {
+ // If previously resumed activity doesn't work either - find the topmost running
+ // activity that can be focused.
+ resumedActivity = focusedStack.topRunningActivity(true /* focusableOnly */);
+ }
+ }
+ return resumedActivity;
+ }
+
+ ActivityStack getLastFocusedStack() {
+ return mLastFocusedStack;
+ }
+
+ boolean allResumedActivitiesComplete() {
+ for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityRecord r = getStackAt(stackNdx).getResumedActivity();
+ if (r != null && !r.isState(RESUMED)) {
+ return false;
+ }
+ }
+ final ActivityStack currentFocusedStack = getFocusedStack();
+ if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
+ Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from="
+ + mLastFocusedStack + " to=" + currentFocusedStack);
+ }
+ mLastFocusedStack = currentFocusedStack;
+ return true;
+ }
+
+ /**
+ * Pause all activities in either all of the stacks or just the back stacks. This is done before
+ * resuming a new activity and to make sure that previously active activities are
+ * paused in stacks that are no longer visible or in pinned windowing mode. This does not
+ * pause activities in visible stacks, so if an activity is launched within the same stack/task,
+ * then we should explicitly pause that stack's top activity.
+ * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
+ * @param resuming The resuming activity.
+ * @return {@code true} if any activity was paused as a result of this call.
+ */
+ boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) {
+ boolean someActivityPaused = false;
+ for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = getStackAt(stackNdx);
+ final ActivityRecord resumedActivity = stack.getResumedActivity();
+ if (resumedActivity != null
+ && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
+ || !stack.isTopActivityFocusable())) {
+ if (DEBUG_STATES) {
+ Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack
+ + " mResumedActivity=" + resumedActivity);
+ }
+ someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
+ resuming);
+ }
+ }
+ return someActivityPaused;
+ }
+
+ /**
+ * Find task for putting the Activity in.
+ */
+ void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplay,
+ RootWindowContainer.FindTaskResult result) {
+ mTmpFindTaskResult.clear();
+ for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = getStackAt(stackNdx);
+ if (!r.hasCompatibleActivityType(stack) && stack.isLeafTask()) {
+ if (DEBUG_TASKS) {
+ Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
+ }
+ continue;
+ }
+
+ mTmpFindTaskResult.process(r, stack);
+ // It is possible to have tasks in multiple stacks with the same root affinity, so
+ // we should keep looking after finding an affinity match to see if there is a
+ // better match in another stack. Also, task affinity isn't a good enough reason
+ // to target a display which isn't the source of the intent, so skip any affinity
+ // matches not on the specified display.
+ if (mTmpFindTaskResult.mRecord != null) {
+ if (mTmpFindTaskResult.mIdealMatch) {
+ result.setTo(mTmpFindTaskResult);
+ return;
+ } else if (isPreferredDisplay) {
+ // Note: since the traversing through the stacks is top down, the floating
+ // tasks should always have lower priority than any affinity-matching tasks
+ // in the fullscreen stacks
+ result.setTo(mTmpFindTaskResult);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes stacks in the input windowing modes from the system if they are of activity type
+ * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
+ */
+ void removeStacksInWindowingModes(int... windowingModes) {
+ if (windowingModes == null || windowingModes.length == 0) {
+ return;
+ }
+
+ // Collect the stacks that are necessary to be removed instead of performing the removal
+ // by looping mStacks, so that we don't miss any stacks after the stack size changed or
+ // stacks reordered.
+ final ArrayList<ActivityStack> stacks = new ArrayList<>();
+ for (int j = windowingModes.length - 1; j >= 0; --j) {
+ final int windowingMode = windowingModes[j];
+ for (int i = getStackCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getStackAt(i);
+ if (!stack.isActivityTypeStandardOrUndefined()) {
+ continue;
+ }
+ if (stack.getWindowingMode() != windowingMode) {
+ continue;
+ }
+ stacks.add(stack);
+ }
+ }
+
+ for (int i = stacks.size() - 1; i >= 0; --i) {
+ mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i));
+ }
+ }
+
+ void removeStacksWithActivityTypes(int... activityTypes) {
+ if (activityTypes == null || activityTypes.length == 0) {
+ return;
+ }
+
+ // Collect the stacks that are necessary to be removed instead of performing the removal
+ // by looping mStacks, so that we don't miss any stacks after the stack size changed or
+ // stacks reordered.
+ final ArrayList<ActivityStack> stacks = new ArrayList<>();
+ for (int j = activityTypes.length - 1; j >= 0; --j) {
+ final int activityType = activityTypes[j];
+ for (int i = getStackCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getStackAt(i);
+ // Collect the root tasks that are currently being organized.
+ if (stack.isOrganized()) {
+ for (int k = stack.getChildCount() - 1; k >= 0; --k) {
+ final ActivityStack childStack = (ActivityStack) stack.getChildAt(k);
+ if (childStack.getActivityType() == activityType) {
+ stacks.add(childStack);
+ }
+ }
+ } else if (stack.getActivityType() == activityType) {
+ stacks.add(stack);
+ }
+ }
+ }
+
+ for (int i = stacks.size() - 1; i >= 0; --i) {
+ mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i));
+ }
+ }
+
+ void onSplitScreenModeDismissed() {
+ mAtmService.deferWindowLayout();
+ try {
+ mLaunchRootTask = null;
+ moveSplitScreenTasksToFullScreen();
+ } finally {
+ final ActivityStack topFullscreenStack =
+ getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ final ActivityStack homeStack = getOrCreateRootHomeTask();
+ if (topFullscreenStack != null && homeStack != null && !isTopStack(homeStack)) {
+ // Whenever split-screen is dismissed we want the home stack directly behind the
+ // current top fullscreen stack so it shows up when the top stack is finished.
+ // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
+ // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
+ // once we have that.
+ homeStack.moveToFront("onSplitScreenModeDismissed");
+ topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
+ }
+ mAtmService.continueWindowLayout();
+ }
+ }
+
+ private void moveSplitScreenTasksToFullScreen() {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mTmpTasks.clear();
+ forAllTasks(task -> {
+ if (task.mCreatedByOrganizer && task.inSplitScreenWindowingMode() && task.hasChild()) {
+ mTmpTasks.add(task);
+ }
+ });
+
+ for (int i = mTmpTasks.size() - 1; i >= 0; i--) {
+ final Task root = mTmpTasks.get(i);
+ for (int j = 0; j < root.getChildCount(); j++) {
+ wct.reparent(root.getChildAt(j).mRemoteToken, null, true /* toTop */);
+ }
+ }
+ mAtmService.mWindowOrganizerController.applyTransaction(wct);
+ }
+
+ /**
+ * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
+ * @param windowingMode The windowing mode we are checking support for.
+ * @param supportsMultiWindow If we should consider support for multi-window mode in general.
+ * @param supportsSplitScreen If we should consider support for split-screen multi-window.
+ * @param supportsFreeform If we should consider support for freeform multi-window.
+ * @param supportsPip If we should consider support for picture-in-picture mutli-window.
+ * @param activityType The activity type under consideration.
+ * @return true if the windowing mode is supported.
+ */
+ private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
+ boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
+ int activityType) {
+
+ if (windowingMode == WINDOWING_MODE_UNDEFINED
+ || windowingMode == WINDOWING_MODE_FULLSCREEN) {
+ return true;
+ }
+ if (!supportsMultiWindow) {
+ return false;
+ }
+
+ if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
+ return true;
+ }
+
+ final int displayWindowingMode = getWindowingMode();
+ if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+ return supportsSplitScreen
+ && WindowConfiguration.supportSplitScreenWindowingMode(activityType)
+ // Freeform windows and split-screen windows don't mix well, so prevent
+ // split windowing modes on freeform displays.
+ && displayWindowingMode != WINDOWING_MODE_FREEFORM;
+ }
+
+ if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
+ return false;
+ }
+
+ if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
+ * display with the provided parameters.
+ *
+ * @param r The ActivityRecord in question.
+ * @param options Options to start with.
+ * @param task The task within-which the activity would start.
+ * @param activityType The type of activity to start.
+ * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
+ */
+ int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable Task task, int activityType) {
+
+ // First preference if the windowing mode in the activity options if set.
+ int windowingMode = (options != null)
+ ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
+
+ // If windowing mode is unset, then next preference is the candidate task, then the
+ // activity record.
+ if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+ if (task != null) {
+ windowingMode = task.getWindowingMode();
+ }
+ if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
+ windowingMode = r.getWindowingMode();
+ }
+ if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+ // Use the display's windowing mode.
+ windowingMode = getWindowingMode();
+ }
+ }
+ windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
+ return windowingMode != WINDOWING_MODE_UNDEFINED
+ ? windowingMode : WINDOWING_MODE_FULLSCREEN;
+ }
+
+ /**
+ * Check that the requested windowing-mode is appropriate for the specified task and/or activity
+ * on this display.
+ *
+ * @param windowingMode The windowing-mode to validate.
+ * @param r The {@link ActivityRecord} to check against.
+ * @param task The {@link Task} to check against.
+ * @param activityType An activity type.
+ * @return The provided windowingMode or the closest valid mode which is appropriate.
+ */
+ int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
+ int activityType) {
+ // Make sure the windowing mode we are trying to use makes sense for what is supported.
+ boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow;
+ boolean supportsSplitScreen = mAtmService.mSupportsSplitScreenMultiWindow;
+ boolean supportsFreeform = mAtmService.mSupportsFreeformWindowManagement;
+ boolean supportsPip = mAtmService.mSupportsPictureInPicture;
+ if (supportsMultiWindow) {
+ if (task != null) {
+ supportsMultiWindow = task.isResizeable();
+ supportsSplitScreen = task.supportsSplitScreenWindowingMode();
+ // TODO: Do we need to check for freeform and Pip support here?
+ } else if (r != null) {
+ supportsMultiWindow = r.isResizeable();
+ supportsSplitScreen = r.supportsSplitScreenWindowingMode();
+ supportsFreeform = r.supportsFreeform();
+ supportsPip = r.supportsPictureInPicture();
+ }
+ }
+
+ final boolean inSplitScreenMode = isSplitScreenModeActivated();
+ if (!inSplitScreenMode
+ && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
+ // Switch to the display's windowing mode if we are not in split-screen mode and we are
+ // trying to launch in split-screen secondary.
+ windowingMode = WINDOWING_MODE_UNDEFINED;
+ } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN
+ || windowingMode == WINDOWING_MODE_UNDEFINED)
+ && supportsSplitScreen) {
+ windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+ }
+
+ if (windowingMode != WINDOWING_MODE_UNDEFINED
+ && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
+ supportsFreeform, supportsPip, activityType)) {
+ return windowingMode;
+ }
+ return WINDOWING_MODE_UNDEFINED;
+ }
+
+ boolean isTopStack(ActivityStack stack) {
+ return stack == getTopStack();
+ }
+
+ boolean isTopNotPinnedStack(ActivityStack stack) {
+ for (int i = getStackCount() - 1; i >= 0; --i) {
+ final ActivityStack current = getStackAt(i);
+ if (!current.inPinnedWindowingMode()) {
+ return current == stack;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the top running activity in the focused stack. In the case the focused stack has no
+ * such activity, the next focusable stack on this display is returned.
+ *
+ * @param considerKeyguardState Indicates whether the locked state should be considered. if
+ * {@code true} and the keyguard is locked, only activities that
+ * can be shown on top of the keyguard will be considered.
+ * @return The top running activity. {@code null} if none is available.
+ */
+ ActivityRecord topRunningActivity(boolean considerKeyguardState) {
+ ActivityRecord topRunning = null;
+ final ActivityStack focusedStack = getFocusedStack();
+ if (focusedStack != null) {
+ topRunning = focusedStack.topRunningActivity();
+ }
+
+ // Look in other focusable stacks.
+ if (topRunning == null) {
+ for (int i = getStackCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getStackAt(i);
+ // Only consider focusable stacks other than the current focused one.
+ if (stack == focusedStack || !stack.isTopActivityFocusable()) {
+ continue;
+ }
+ topRunning = stack.topRunningActivity();
+ if (topRunning != null) {
+ break;
+ }
+ }
+ }
+
+ // This activity can be considered the top running activity if we are not considering
+ // the locked state, the keyguard isn't locked, or we can show when locked.
+ if (topRunning != null && considerKeyguardState
+ && mRootWindowContainer.mStackSupervisor.getKeyguardController()
+ .isKeyguardLocked()
+ && !topRunning.canShowWhenLocked()) {
+ return null;
+ }
+
+ return topRunning;
+ }
+
+ protected int getStackCount() {
+ return mChildren.size();
+ }
+
+ protected ActivityStack getStackAt(int index) {
+ return mChildren.get(index);
+ }
+
+ /**
+ * Returns the existing home stack or creates and returns a new one if it should exist for the
+ * display.
+ */
+ @Nullable
+ ActivityStack getOrCreateRootHomeTask() {
+ ActivityStack homeTask = getRootHomeTask();
+ if (homeTask == null && mDisplayContent.supportsSystemDecorations()
+ && !mDisplayContent.isUntrustedVirtualDisplay()) {
+ homeTask = createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME,
+ false /* onTop */);
+ }
+ return homeTask;
+ }
+
+ boolean isSplitScreenModeActivated() {
+ Task task = getRootSplitScreenPrimaryTask();
+ return task != null && task.hasChild();
+ }
+
+ /**
+ * Returns the topmost stack on the display that is compatible with the input windowing mode.
+ * Null is no compatible stack on the display.
+ */
+ ActivityStack getTopStackInWindowingMode(int windowingMode) {
+ return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED);
+ }
+
+ void moveHomeStackToFront(String reason) {
+ final ActivityStack homeStack = getOrCreateRootHomeTask();
+ if (homeStack != null) {
+ homeStack.moveToFront(reason);
+ }
+ }
+
+ /**
+ * Moves the focusable home activity to top. If there is no such activity, the home stack will
+ * still move to top.
+ */
+ void moveHomeActivityToTop(String reason) {
+ final ActivityRecord top = getHomeActivity();
+ if (top == null) {
+ moveHomeStackToFront(reason);
+ return;
+ }
+ top.moveFocusableActivityToTop(reason);
+ }
+
+ @Nullable
+ ActivityRecord getHomeActivity() {
+ return getHomeActivityForUser(mRootWindowContainer.mCurrentUser);
+ }
+
+ @Nullable
+ ActivityRecord getHomeActivityForUser(int userId) {
+ final ActivityStack homeStack = getRootHomeTask();
+ if (homeStack == null) {
+ return null;
+ }
+
+ final PooledPredicate p = PooledLambda.obtainPredicate(
+ TaskContainers::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class),
+ userId);
+ final ActivityRecord r = homeStack.getActivity(p);
+ p.recycle();
+ return r;
+ }
+
+ private static boolean isHomeActivityForUser(ActivityRecord r, int userId) {
+ return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId);
+ }
+
+ /**
+ * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
+ * Generally used in conjunction with {@link #moveStackBehindStack}.
+ */
+ // TODO(b/151575894): Remove special stack movement methods.
+ void moveStackBehindBottomMostVisibleStack(ActivityStack stack) {
+ if (stack.shouldBeVisible(null)) {
+ // Skip if the stack is already visible
+ return;
+ }
+
+ final boolean isRootTask = stack.isRootTask();
+ if (isRootTask) {
+ // Move the stack to the bottom to not affect the following visibility checks
+ positionStackAtBottom(stack);
+ } else {
+ stack.getParent().positionChildAt(POSITION_BOTTOM, stack, false /* includingParents */);
+ }
+
+ // Find the next position where the stack should be placed
+ final int numStacks = isRootTask ? getStackCount() : stack.getParent().getChildCount();
+ for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
+ final ActivityStack s = isRootTask ? getStackAt(stackNdx)
+ : (ActivityStack) stack.getParent().getChildAt(stackNdx);
+ if (s == stack) {
+ continue;
+ }
+ final int winMode = s.getWindowingMode();
+ final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN
+ || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+ if (s.shouldBeVisible(null) && isValidWindowingMode) {
+ // Move the provided stack to behind this stack
+ final int position = Math.max(0, stackNdx - 1);
+ if (isRootTask) {
+ positionStackAt(stack, position);
+ } else {
+ stack.getParent().positionChildAt(position, stack, false /*includingParents */);
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Moves the {@param stack} behind the given {@param behindStack} if possible. If
+ * {@param behindStack} is not currently in the display, then then the stack is moved to the
+ * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}.
+ */
+ void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) {
+ if (behindStack == null || behindStack == stack) {
+ return;
+ }
+
+ final WindowContainer parent = stack.getParent();
+ if (parent == null || parent != behindStack.getParent()) {
+ return;
+ }
+
+ // Note that positionChildAt will first remove the given stack before inserting into the
+ // list, so we need to adjust the insertion index to account for the removed index
+ // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
+ // position internally
+ final int stackIndex = parent.mChildren.indexOf(stack);
+ final int behindStackIndex = parent.mChildren.indexOf(behindStack);
+ final int insertIndex = stackIndex <= behindStackIndex
+ ? behindStackIndex - 1 : behindStackIndex;
+ final int position = Math.max(0, insertIndex);
+ if (stack.isRootTask()) {
+ positionStackAt(stack, position);
+ } else {
+ parent.positionChildAt(position, stack, false /* includingParents */);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 4382e9d..8edcd2f 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -20,19 +20,19 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS;
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS;
import android.annotation.Nullable;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.WindowConfiguration;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Slog;
import android.util.SparseArray;
import android.window.ITaskOrganizer;
@@ -41,10 +41,12 @@
import com.android.internal.util.ArrayUtils;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
import java.util.WeakHashMap;
/**
@@ -53,7 +55,7 @@
*/
class TaskOrganizerController extends ITaskOrganizerController.Stub {
private static final String TAG = "TaskOrganizerController";
- private static final LinkedList<TaskOrganizerState> EMPTY_LIST = new LinkedList<>();
+ private static final LinkedList<IBinder> EMPTY_LIST = new LinkedList<>();
/**
* Masks specifying which configurations are important to report back to an organizer when
@@ -65,12 +67,10 @@
private final WindowManagerGlobalLock mGlobalLock;
private class DeathRecipient implements IBinder.DeathRecipient {
- int mWindowingMode;
ITaskOrganizer mTaskOrganizer;
- DeathRecipient(ITaskOrganizer organizer, int windowingMode) {
+ DeathRecipient(ITaskOrganizer organizer) {
mTaskOrganizer = organizer;
- mWindowingMode = windowingMode;
}
@Override
@@ -86,18 +86,18 @@
private class TaskOrganizerState {
private final ITaskOrganizer mOrganizer;
private final DeathRecipient mDeathRecipient;
- private final int mWindowingMode;
private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
+ private final int mUid;
- TaskOrganizerState(ITaskOrganizer organizer, int windowingMode) {
+ TaskOrganizerState(ITaskOrganizer organizer, int uid) {
mOrganizer = organizer;
- mDeathRecipient = new DeathRecipient(organizer, windowingMode);
+ mDeathRecipient = new DeathRecipient(organizer);
try {
organizer.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
Slog.e(TAG, "TaskOrganizer failed to register death recipient");
}
- mWindowingMode = windowingMode;
+ mUid = uid;
}
void addTask(Task t) {
@@ -120,7 +120,9 @@
void dispose() {
releaseTasks();
- mTaskOrganizersForWindowingMode.get(mWindowingMode).remove(this);
+ for (int i = mTaskOrganizersForWindowingMode.size() - 1; i >= 0; --i) {
+ mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.asBinder());
+ }
}
private void releaseTasks() {
@@ -136,7 +138,7 @@
}
}
- private final SparseArray<LinkedList<TaskOrganizerState>> mTaskOrganizersForWindowingMode =
+ private final SparseArray<LinkedList<IBinder>> mTaskOrganizersForWindowingMode =
new SparseArray<>();
private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>();
private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
@@ -162,14 +164,27 @@
*/
@Override
public void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) {
- if (windowingMode != WINDOWING_MODE_PINNED
- && windowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- && windowingMode != WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
- && windowingMode != WINDOWING_MODE_MULTI_WINDOW) {
+ if (windowingMode == WINDOWING_MODE_PINNED) {
+ if (!mService.mSupportsPictureInPicture) {
+ throw new UnsupportedOperationException("Picture in picture is not supported on "
+ + "this device");
+ }
+ } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
+ if (!mService.mSupportsSplitScreenMultiWindow) {
+ throw new UnsupportedOperationException("Split-screen is not supported on this "
+ + "device");
+ }
+ } else if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
+ if (!mService.mSupportsMultiWindow) {
+ throw new UnsupportedOperationException("Multi-window is not supported on this "
+ + "device");
+ }
+ } else {
throw new UnsupportedOperationException("As of now only Pinned/Split/Multiwindow"
+ " windowing modes are supported for registerTaskOrganizer");
}
enforceStackPermission("registerTaskOrganizer()");
+ final int uid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -178,19 +193,18 @@
+ windowingMode);
}
- LinkedList<TaskOrganizerState> states;
- if (mTaskOrganizersForWindowingMode.contains(windowingMode)) {
- states = mTaskOrganizersForWindowingMode.get(windowingMode);
- } else {
- states = new LinkedList<>();
- mTaskOrganizersForWindowingMode.put(windowingMode, states);
+ LinkedList<IBinder> orgs = mTaskOrganizersForWindowingMode.get(windowingMode);
+ if (orgs == null) {
+ orgs = new LinkedList<>();
+ mTaskOrganizersForWindowingMode.put(windowingMode, orgs);
}
- final TaskOrganizerState previousState = states.peekLast();
- final TaskOrganizerState state = new TaskOrganizerState(organizer, windowingMode);
- states.add(state);
- mTaskOrganizerStates.put(organizer.asBinder(), state);
+ orgs.add(organizer.asBinder());
+ if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
+ mTaskOrganizerStates.put(organizer.asBinder(),
+ new TaskOrganizerState(organizer, uid));
+ }
- if (previousState == null) {
+ if (orgs.size() == 1) {
// Only in the case where this is the root task organizer for the given
// windowing mode, we add report all existing tasks in that mode to the new
// task organizer.
@@ -214,8 +228,12 @@
}
ITaskOrganizer getTaskOrganizer(int windowingMode) {
- final TaskOrganizerState state = mTaskOrganizersForWindowingMode.get(windowingMode,
- EMPTY_LIST).peekLast();
+ final IBinder organizer =
+ mTaskOrganizersForWindowingMode.get(windowingMode, EMPTY_LIST).peekLast();
+ if (organizer == null) {
+ return null;
+ }
+ final TaskOrganizerState state = mTaskOrganizerStates.get(organizer);
if (state == null) {
return null;
}
@@ -243,9 +261,9 @@
return null;
}
- final Task task = display.getOrCreateStack(windowingMode, ACTIVITY_TYPE_UNDEFINED,
- false /* onTop */, new Intent(), null /* candidateTask */,
- true /* createdByOrganizer */);
+ final Task task = display.mTaskContainers.getOrCreateStack(windowingMode,
+ ACTIVITY_TYPE_UNDEFINED, false /* onTop */, new Intent(),
+ null /* candidateTask */, true /* createdByOrganizer */);
RunningTaskInfo out = task.getTaskInfo();
mLastSentTaskInfos.put(task, out);
return out;
@@ -454,4 +472,27 @@
Binder.restoreCallingIdentity(ident);
}
}
+
+ public void dump(PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ pw.print(prefix); pw.println("TaskOrganizerController:");
+ pw.print(innerPrefix); pw.println("Per windowing mode:");
+ for (int i = 0; i < mTaskOrganizersForWindowingMode.size(); i++) {
+ final int windowingMode = mTaskOrganizersForWindowingMode.keyAt(i);
+ final List<IBinder> taskOrgs = mTaskOrganizersForWindowingMode.valueAt(i);
+ pw.println(innerPrefix + " "
+ + WindowConfiguration.windowingModeToString(windowingMode) + ":");
+ for (int j = 0; j < taskOrgs.size(); j++) {
+ final TaskOrganizerState state = mTaskOrganizerStates.get(taskOrgs.get(j));
+ final ArrayList<Task> tasks = state.mOrganizedTasks;
+ pw.print(innerPrefix + " ");
+ pw.println(state.mOrganizer + " uid=" + state.mUid + ":");
+ for (int k = 0; k < tasks.size(); k++) {
+ pw.println(innerPrefix + " " + tasks.get(k));
+ }
+ }
+
+ }
+ pw.println();
+ }
}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index be0d6f8..f046e8a 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -268,9 +268,8 @@
mDisplayContent.getDisplayRotation().pause();
// Notify InputMonitor to take mDragWindowHandle.
- final SurfaceControl.Transaction t = mService.mTransactionFactory.get();
- mDisplayContent.getInputMonitor().updateInputWindowsImmediately(t);
- t.syncInputWindows().apply();
+ mDisplayContent.getInputMonitor().updateInputWindowsImmediately();
+ new SurfaceControl.Transaction().syncInputWindows().apply(true);
final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0757725..b1f22f8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -58,7 +58,6 @@
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -1482,12 +1481,6 @@
+ "%s. Aborting.", attrs.token);
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
- } else if (rootType == TYPE_DREAM) {
- if (token.windowType != TYPE_DREAM) {
- ProtoLog.w(WM_ERROR, "Attempted to add Dream window with bad token "
- + "%s. Aborting.", attrs.token);
- return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
- }
} else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
ProtoLog.w(WM_ERROR,
@@ -1723,11 +1716,6 @@
+ "%s. Aborting.", tokenForLog);
return false;
}
- if (rootType == TYPE_DREAM) {
- ProtoLog.w(WM_ERROR, "Attempted to add Dream window with unknown token "
- + "%s. Aborting.", tokenForLog);
- return false;
- }
if (rootType == TYPE_QS_DIALOG) {
ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with unknown token "
+ "%s. Aborting.", tokenForLog);
@@ -7746,23 +7734,19 @@
public void syncInputTransactions() {
waitForAnimationsToComplete();
- // Collect all input transactions from all displays to make sure we could sync all input
- // windows at same time.
- final SurfaceControl.Transaction t = mTransactionFactory.get();
synchronized (mGlobalLock) {
mWindowPlacerLocked.performSurfacePlacementIfScheduled();
mRoot.forAllDisplays(displayContent ->
- displayContent.getInputMonitor().updateInputWindowsImmediately(t));
+ displayContent.getInputMonitor().updateInputWindowsImmediately());
}
- t.syncInputWindows().apply();
+ mTransactionFactory.get().syncInputWindows().apply(true);
}
private void waitForAnimationsToComplete() {
synchronized (mGlobalLock) {
long timeoutRemaining = ANIMATION_COMPLETED_TIMEOUT_MS;
- while ((mAnimator.isAnimationScheduled()
- || mRoot.isAnimating(TRANSITION | CHILDREN)) && timeoutRemaining > 0) {
+ while (mRoot.isAnimating(TRANSITION | CHILDREN) && timeoutRemaining > 0) {
long startTime = System.currentTimeMillis();
try {
mGlobalLock.wait(timeoutRemaining);
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 5f21e17..7eccf08 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -252,9 +252,10 @@
final ActivityStack rootTask =
(ActivityStack) (newParent != null ? newParent : task.getRootTask());
if (hop.getToTop()) {
- as.getDisplay().positionStackAtTop(rootTask, false /* includingParents */);
+ as.getDisplay().mTaskContainers.positionStackAtTop(rootTask,
+ false /* includingParents */);
} else {
- as.getDisplay().positionStackAtBottom(rootTask);
+ as.getDisplay().mTaskContainers.positionStackAtBottom(rootTask);
}
}
} else {
@@ -264,9 +265,9 @@
// Ugh, of course ActivityStack has its own special reorder logic...
if (task.isRootTask()) {
if (hop.getToTop()) {
- dc.positionStackAtTop(as, false /* includingParents */);
+ dc.mTaskContainers.positionStackAtTop(as, false /* includingParents */);
} else {
- dc.positionStackAtBottom(as);
+ dc.mTaskContainers.positionStackAtBottom(as);
}
} else {
task.getParent().positionChildAt(
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c4d700c..8013a6c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -20,6 +20,7 @@
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_NONE;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.os.PowerManager.DRAW_WAKE_LOCK;
@@ -1694,6 +1695,11 @@
return !isParentWindowHidden() || isAnimating(TRANSITION | PARENTS);
}
+ boolean isDreamWindow() {
+ return mActivityRecord != null
+ && mActivityRecord.getActivityType() == ACTIVITY_TYPE_DREAM;
+ }
+
/**
* Whether this window's drawn state might affect the drawn states of the app token.
*
@@ -3968,7 +3974,12 @@
}
pw.println(prefix + "isOnScreen=" + isOnScreen());
pw.println(prefix + "isVisible=" + isVisible());
- pw.println(prefix + "mEmbeddedDisplayContents=" + mEmbeddedDisplayContents);
+ if (!mEmbeddedDisplayContents.isEmpty()) {
+ pw.println(prefix + "mEmbeddedDisplayContents=" + mEmbeddedDisplayContents);
+ }
+ if (dumpAll) {
+ pw.println(prefix + "mRequestedInsetsState: " + mRequestedInsetsState);
+ }
}
@Override
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 9bc5d34..e3f9ae8 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -206,7 +206,7 @@
status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
status_t pilferPointers(const sp<IBinder>& token);
- void displayRemoved(JNIEnv* env, int32_t displayId);
+ void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId);
void setFocusedApplication(JNIEnv* env, int32_t displayId, jobject applicationHandleObj);
void setFocusedDisplay(JNIEnv* env, int32_t displayId);
void setInputDispatchMode(bool enabled, bool frozen);
@@ -771,10 +771,55 @@
}
}
-void NativeInputManager::displayRemoved(JNIEnv* env, int32_t displayId) {
- // Set an empty list to remove all handles from the specific display.
- std::vector<sp<InputWindowHandle>> windowHandles;
- mInputManager->getDispatcher()->setInputWindows({{displayId, windowHandles}});
+void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray,
+ int32_t displayId) {
+ std::vector<sp<InputWindowHandle> > windowHandles;
+
+ if (windowHandleObjArray) {
+ jsize length = env->GetArrayLength(windowHandleObjArray);
+ for (jsize i = 0; i < length; i++) {
+ jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i);
+ if (! windowHandleObj) {
+ break; // found null element indicating end of used portion of the array
+ }
+
+ sp<InputWindowHandle> windowHandle =
+ android_view_InputWindowHandle_getHandle(env, windowHandleObj);
+ if (windowHandle != nullptr) {
+ windowHandles.push_back(windowHandle);
+ }
+ env->DeleteLocalRef(windowHandleObj);
+ }
+ }
+
+ mInputManager->getDispatcher()->setInputWindows(windowHandles, displayId);
+
+ // Do this after the dispatcher has updated the window handle state.
+ bool newPointerGesturesEnabled = true;
+ size_t numWindows = windowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ const sp<InputWindowHandle>& windowHandle = windowHandles[i];
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures
+ & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) {
+ newPointerGesturesEnabled = false;
+ }
+ }
+
+ bool pointerGesturesEnabledChanged = false;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ if (mLocked.pointerGesturesEnabled != newPointerGesturesEnabled) {
+ mLocked.pointerGesturesEnabled = newPointerGesturesEnabled;
+ pointerGesturesEnabledChanged = true;
+ }
+ } // release lock
+
+ if (pointerGesturesEnabledChanged) {
+ mInputManager->getReader()->requestRefreshConfiguration(
+ InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT);
+ }
}
void NativeInputManager::setFocusedApplication(JNIEnv* env, int32_t displayId,
@@ -1522,10 +1567,11 @@
im->getInputManager()->getReader()->toggleCapsLockState(deviceId);
}
-static void nativeDisplayRemoved(JNIEnv* env, jclass /* clazz */, jlong ptr, jint displayId) {
+static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */,
+ jlong ptr, jobjectArray windowHandleObjArray, jint displayId) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
- im->displayRemoved(env, displayId);
+ im->setInputWindows(env, windowHandleObjArray, displayId);
}
static void nativeSetFocusedApplication(JNIEnv* env, jclass /* clazz */,
@@ -1769,7 +1815,8 @@
{"nativeVerifyInputEvent", "(JLandroid/view/InputEvent;)Landroid/view/VerifiedInputEvent;",
(void*)nativeVerifyInputEvent},
{"nativeToggleCapsLock", "(JI)V", (void*)nativeToggleCapsLock},
- {"nativeDisplayRemoved", "(JI)V", (void*)nativeDisplayRemoved},
+ {"nativeSetInputWindows", "(J[Landroid/view/InputWindowHandle;I)V",
+ (void*)nativeSetInputWindows},
{"nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V",
(void*)nativeSetFocusedApplication},
{"nativeSetFocusedDisplay", "(JI)V", (void*)nativeSetFocusedDisplay},
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 725036c..e9a5e58 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -227,56 +227,40 @@
return result;
}
+enum MetadataMode : int8_t {
+ STDIN = 0,
+ LOCAL_FILE = 1,
+ DATA_ONLY_STREAMING = 2,
+ STREAMING = 3,
+};
+
struct InputDesc {
unique_fd fd;
IncFsSize size;
IncFsBlockKind kind = INCFS_BLOCK_KIND_DATA;
bool waitOnEof = false;
bool streaming = false;
+ MetadataMode mode = STDIN;
};
using InputDescs = std::vector<InputDesc>;
-static inline InputDescs openInputs(JNIEnv* env, const JniIds& jni, jobject shellCommand,
- IncFsSize size, IncFsSpan metadata) {
+template <class T>
+std::optional<T> read(IncFsSpan& data) {
+ if (data.size < (int32_t)sizeof(T)) {
+ return {};
+ }
+ T res;
+ memcpy(&res, data.data, sizeof(res));
+ data.data += sizeof(res);
+ data.size -= sizeof(res);
+ return res;
+}
+
+static inline InputDescs openLocalFile(JNIEnv* env, const JniIds& jni, jobject shellCommand,
+ IncFsSize size, const std::string& filePath) {
InputDescs result;
result.reserve(2);
- if (metadata.size == 0 || *metadata.data == '-') {
- // stdin
- auto fd = convertPfdToFdAndDup(
- env, jni,
- env->CallStaticObjectMethod(jni.packageManagerShellCommandDataLoader,
- jni.pmscdGetStdInPFD, shellCommand));
- if (fd.ok()) {
- result.push_back(InputDesc{
- .fd = std::move(fd),
- .size = size,
- .waitOnEof = true,
- });
- }
- return result;
- }
- if (*metadata.data == '+') {
- // verity tree from stdin, rest is streaming
- auto fd = convertPfdToFdAndDup(
- env, jni,
- env->CallStaticObjectMethod(jni.packageManagerShellCommandDataLoader,
- jni.pmscdGetStdInPFD, shellCommand));
- if (fd.ok()) {
- auto treeSize = verityTreeSizeForFile(size);
- result.push_back(InputDesc{
- .fd = std::move(fd),
- .size = treeSize,
- .kind = INCFS_BLOCK_KIND_HASH,
- .waitOnEof = true,
- .streaming = true,
- });
- }
- return result;
- }
-
- // local file and possibly signature
- const std::string filePath(metadata.data, metadata.size);
const std::string idsigPath = filePath + ".idsig";
auto idsigFd = convertPfdToFdAndDup(
@@ -314,6 +298,59 @@
return result;
}
+static inline InputDescs openInputs(JNIEnv* env, const JniIds& jni, jobject shellCommand,
+ IncFsSize size, IncFsSpan metadata) {
+ auto mode = read<int8_t>(metadata).value_or(STDIN);
+ if (mode == LOCAL_FILE) {
+ // local file and possibly signature
+ return openLocalFile(env, jni, shellCommand, size,
+ std::string(metadata.data, metadata.size));
+ }
+
+ auto fd = convertPfdToFdAndDup(
+ env, jni,
+ env->CallStaticObjectMethod(jni.packageManagerShellCommandDataLoader,
+ jni.pmscdGetStdInPFD, shellCommand));
+ if (!fd.ok()) {
+ return {};
+ }
+
+ InputDescs result;
+ switch (mode) {
+ case STDIN: {
+ result.push_back(InputDesc{
+ .fd = std::move(fd),
+ .size = size,
+ .waitOnEof = true,
+ });
+ break;
+ }
+ case DATA_ONLY_STREAMING: {
+ // verity tree from stdin, rest is streaming
+ auto treeSize = verityTreeSizeForFile(size);
+ result.push_back(InputDesc{
+ .fd = std::move(fd),
+ .size = treeSize,
+ .kind = INCFS_BLOCK_KIND_HASH,
+ .waitOnEof = true,
+ .streaming = true,
+ .mode = DATA_ONLY_STREAMING,
+ });
+ break;
+ }
+ case STREAMING: {
+ result.push_back(InputDesc{
+ .fd = std::move(fd),
+ .size = 0,
+ .streaming = true,
+ .mode = STREAMING,
+ });
+ break;
+ }
+ }
+ return result;
+}
+
static inline JNIEnv* GetJNIEnvironment(JavaVM* vm) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
@@ -390,6 +427,7 @@
blocks.reserve(BLOCKS_COUNT);
unique_fd streamingFd;
+ MetadataMode streamingMode;
for (auto&& file : addedFiles) {
auto inputs = openInputs(env, jni, shellCommand, file.size, file.metadata);
if (inputs.empty()) {
@@ -411,6 +449,7 @@
for (auto&& input : inputs) {
if (input.streaming && !streamingFd.ok()) {
streamingFd.reset(dup(input.fd));
+ streamingMode = input.mode;
}
if (!copyToIncFs(incfsFd, input.size, input.kind, input.fd, input.waitOnEof,
&buffer, &blocks)) {
@@ -425,7 +464,7 @@
if (streamingFd.ok()) {
ALOGE("onPrepareImage: done, proceeding to streaming.");
- return initStreaming(std::move(streamingFd));
+ return initStreaming(std::move(streamingFd), streamingMode);
}
ALOGE("onPrepareImage: done.");
@@ -564,7 +603,7 @@
}
// Streaming.
- bool initStreaming(unique_fd inout) {
+ bool initStreaming(unique_fd inout, MetadataMode mode) {
mEventFd.reset(eventfd(0, EFD_CLOEXEC));
if (mEventFd < 0) {
ALOGE("Failed to create eventfd.");
@@ -591,8 +630,8 @@
}
}
- mReceiverThread =
- std::thread([this, io = std::move(inout)]() mutable { receiver(std::move(io)); });
+ mReceiverThread = std::thread(
+ [this, io = std::move(inout), mode]() mutable { receiver(std::move(io), mode); });
ALOGI("Started streaming...");
return true;
}
@@ -624,7 +663,7 @@
}
}
- void receiver(unique_fd inout) {
+ void receiver(unique_fd inout, MetadataMode mode) {
std::vector<uint8_t> data;
std::vector<IncFsDataBlock> instructions;
std::unordered_map<FileIdx, unique_fd> writeFds;
@@ -667,7 +706,7 @@
break;
}
const FileIdx fileIdx = header.fileIdx;
- const android::dataloader::FileId fileId = convertFileIndexToFileId(fileIdx);
+ const android::dataloader::FileId fileId = convertFileIndexToFileId(mode, fileIdx);
if (!android::incfs::isValidFileId(fileId)) {
ALOGE("Unknown data destination for file ID %d. "
"Ignore.",
@@ -679,7 +718,7 @@
if (writeFd < 0) {
writeFd.reset(this->mIfs->openWrite(fileId));
if (writeFd < 0) {
- ALOGE("Failed to open file %d for writing (%d). Aboring.", header.fileIdx,
+ ALOGE("Failed to open file %d for writing (%d). Aborting.", header.fileIdx,
-writeFd);
break;
}
@@ -716,9 +755,11 @@
}
FileIdx convertFileIdToFileIndex(android::dataloader::FileId fileId) {
- // FileId is a string in format '+FileIdx\0'.
+ // FileId has format '\2FileIdx'.
const char* meta = (const char*)&fileId;
- if (*meta != '+') {
+
+ int8_t mode = *meta;
+ if (mode != DATA_ONLY_STREAMING && mode != STREAMING) {
return -1;
}
@@ -732,10 +773,10 @@
return FileIdx(fileIdx);
}
- android::dataloader::FileId convertFileIndexToFileId(FileIdx fileIdx) {
+ android::dataloader::FileId convertFileIndexToFileId(MetadataMode mode, FileIdx fileIdx) {
IncFsFileId fileId = {};
char* meta = (char*)&fileId;
- *meta = '+';
+ *meta = mode;
if (auto [p, ec] = std::to_chars(meta + 1, meta + sizeof(fileId), fileIdx);
ec != std::errc()) {
return {};
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 5c7f305..bbd8de2 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -25,7 +25,10 @@
<xs:element name="displayConfiguration">
<xs:complexType>
<xs:sequence>
- <xs:element type="nitsMap" name="screenBrightnessMap"/>
+ <xs:element type="nitsMap" name="screenBrightnessMap">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
@@ -34,15 +37,23 @@
<xs:complexType name="nitsMap">
<xs:sequence>
- <xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2"/>
- <xs:element name="highBrightnessStart" minOccurs="0" type="nonNegativeDecimal"/>
+ <xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="point">
<xs:sequence>
- <xs:element type="nonNegativeDecimal" name="value"/>
- <xs:element type="nonNegativeDecimal" name="nits"/>
+ <xs:element type="nonNegativeDecimal" name="value">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ <xs:element type="nonNegativeDecimal" name="nits">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
</xs:sequence>
</xs:complexType>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 5a9c945..7a35642 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -3,23 +3,21 @@
public class DisplayConfiguration {
ctor public DisplayConfiguration();
- method public com.android.server.display.config.NitsMap getScreenBrightnessMap();
- method public void setScreenBrightnessMap(com.android.server.display.config.NitsMap);
+ method @NonNull public final com.android.server.display.config.NitsMap getScreenBrightnessMap();
+ method public final void setScreenBrightnessMap(@NonNull com.android.server.display.config.NitsMap);
}
public class NitsMap {
ctor public NitsMap();
- method public java.math.BigDecimal getHighBrightnessStart();
- method public java.util.List<com.android.server.display.config.Point> getPoint();
- method public void setHighBrightnessStart(java.math.BigDecimal);
+ method @NonNull public final java.util.List<com.android.server.display.config.Point> getPoint();
}
public class Point {
ctor public Point();
- method public java.math.BigDecimal getNits();
- method public java.math.BigDecimal getValue();
- method public void setNits(java.math.BigDecimal);
- method public void setValue(java.math.BigDecimal);
+ method @NonNull public final java.math.BigDecimal getNits();
+ method @NonNull public final java.math.BigDecimal getValue();
+ method public final void setNits(@NonNull java.math.BigDecimal);
+ method public final void setValue(@NonNull java.math.BigDecimal);
}
public class XmlParser {
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
index cdbe77a..2f6592b 100644
--- a/services/devicepolicy/Android.bp
+++ b/services/devicepolicy/Android.bp
@@ -13,8 +13,4 @@
"services.core",
"app-compat-annotations",
],
-
- plugins: [
- "compat-changeid-annotation-processor",
- ],
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 3ddee29..1544ff1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2079,7 +2079,8 @@
Owners newOwners() {
return new Owners(getUserManager(), getUserManagerInternal(),
- getPackageManagerInternal(), getActivityTaskManagerInternal());
+ getPackageManagerInternal(), getActivityTaskManagerInternal(),
+ getActivityManagerInternal());
}
UserManager getUserManager() {
@@ -9184,8 +9185,6 @@
return true;
}
- Log.w(LOG_TAG, String.format("Package %s (uid=%d, pid=%d) cannot access Device IDs",
- packageName, uid, pid));
return false;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index f70fe90..3cdd482 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -17,6 +17,7 @@
package com.android.server.devicepolicy;
import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
import android.app.AppOpsManagerInternal;
import android.app.admin.SystemUpdateInfo;
import android.app.admin.SystemUpdatePolicy;
@@ -112,6 +113,7 @@
private final UserManagerInternal mUserManagerInternal;
private final PackageManagerInternal mPackageManagerInternal;
private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
+ private final ActivityManagerInternal mActivityManagerInternal;
private boolean mSystemReady;
@@ -138,9 +140,10 @@
public Owners(UserManager userManager,
UserManagerInternal userManagerInternal,
PackageManagerInternal packageManagerInternal,
- ActivityTaskManagerInternal activityTaskManagerInternal) {
+ ActivityTaskManagerInternal activityTaskManagerInternal,
+ ActivityManagerInternal activitykManagerInternal) {
this(userManager, userManagerInternal, packageManagerInternal,
- activityTaskManagerInternal, new Injector());
+ activityTaskManagerInternal, activitykManagerInternal, new Injector());
}
@VisibleForTesting
@@ -148,11 +151,13 @@
UserManagerInternal userManagerInternal,
PackageManagerInternal packageManagerInternal,
ActivityTaskManagerInternal activityTaskManagerInternal,
+ ActivityManagerInternal activityManagerInternal,
Injector injector) {
mUserManager = userManager;
mUserManagerInternal = userManagerInternal;
mPackageManagerInternal = packageManagerInternal;
mActivityTaskManagerInternal = activityTaskManagerInternal;
+ mActivityManagerInternal = activityManagerInternal;
mInjector = injector;
}
@@ -220,6 +225,7 @@
PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES, mDeviceOwnerUserId)
: Process.INVALID_UID;
mActivityTaskManagerInternal.setDeviceOwnerUid(uid);
+ mActivityManagerInternal.setDeviceOwnerUid(uid);
}
String getDeviceOwnerPackageName() {
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index ae27c7a..25da8fe 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -157,7 +157,6 @@
IncrementalService::IncFsMount::~IncFsMount() {
incrementalService.mDataLoaderManager->destroyDataLoader(mountId);
- control.reset();
LOG(INFO) << "Unmounting and cleaning up mount " << mountId << " with root '" << root << '\'';
for (auto&& [target, _] : bindPoints) {
LOG(INFO) << "\tbind: " << target;
@@ -424,9 +423,10 @@
LOG(ERROR) << "Vold::mountIncFs() returned invalid control parcel.";
return kInvalidStorageId;
}
- control.cmd = controlParcel.cmd.release().release();
- control.pendingReads = controlParcel.pendingReads.release().release();
- control.logs = controlParcel.log.release().release();
+ int cmd = controlParcel.cmd.release().release();
+ int pendingReads = controlParcel.pendingReads.release().release();
+ int logs = controlParcel.log.release().release();
+ control = mIncFs->createControl(cmd, pendingReads, logs);
}
std::unique_lock l(mLock);
@@ -965,16 +965,17 @@
auto mountTarget = path::join(root, constants().mount);
const auto backing = path::join(root, constants().backing);
- IncFsMount::Control control;
IncrementalFileSystemControlParcel controlParcel;
auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
if (!status.isOk()) {
LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
return false;
}
- control.cmd = controlParcel.cmd.release().release();
- control.pendingReads = controlParcel.pendingReads.release().release();
- control.logs = controlParcel.log.release().release();
+
+ int cmd = controlParcel.cmd.release().release();
+ int pendingReads = controlParcel.pendingReads.release().release();
+ int logs = controlParcel.log.release().release();
+ IncFsMount::Control control = mIncFs->createControl(cmd, pendingReads, logs);
auto ifs = std::make_shared<IncFsMount>(std::string(root), -1, std::move(control), *this);
@@ -1084,10 +1085,10 @@
}
FileSystemControlParcel fsControlParcel;
fsControlParcel.incremental = aidl::make_nullable<IncrementalFileSystemControlParcel>();
- fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd)));
+ fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd())));
fsControlParcel.incremental->pendingReads.reset(
- base::unique_fd(::dup(ifs.control.pendingReads)));
- fsControlParcel.incremental->log.reset(base::unique_fd(::dup(ifs.control.logs)));
+ base::unique_fd(::dup(ifs.control.pendingReads())));
+ fsControlParcel.incremental->log.reset(base::unique_fd(::dup(ifs.control.logs())));
sp<IncrementalDataLoaderListener> listener =
new IncrementalDataLoaderListener(*this,
externalListener ? *externalListener
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index 5349ebf..c70a47d 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -66,15 +66,17 @@
class IncFsWrapper {
public:
virtual ~IncFsWrapper() = default;
- virtual ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+ virtual Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs) const = 0;
+ virtual ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
NewFileParams params) const = 0;
- virtual ErrorCode makeDir(Control control, std::string_view path, int mode) const = 0;
- virtual RawMetadata getMetadata(Control control, FileId fileid) const = 0;
- virtual RawMetadata getMetadata(Control control, std::string_view path) const = 0;
- virtual FileId getFileId(Control control, std::string_view path) const = 0;
- virtual ErrorCode link(Control control, std::string_view from, std::string_view to) const = 0;
- virtual ErrorCode unlink(Control control, std::string_view path) const = 0;
- virtual base::unique_fd openWrite(Control control, FileId id) const = 0;
+ virtual ErrorCode makeDir(const Control& control, std::string_view path, int mode) const = 0;
+ virtual RawMetadata getMetadata(const Control& control, FileId fileid) const = 0;
+ virtual RawMetadata getMetadata(const Control& control, std::string_view path) const = 0;
+ virtual FileId getFileId(const Control& control, std::string_view path) const = 0;
+ virtual ErrorCode link(const Control& control, std::string_view from,
+ std::string_view to) const = 0;
+ virtual ErrorCode unlink(const Control& control, std::string_view path) const = 0;
+ virtual base::unique_fd openWrite(const Control& control, FileId id) const = 0;
virtual ErrorCode writeBlocks(Span<const DataBlock> blocks) const = 0;
};
@@ -149,29 +151,33 @@
public:
RealIncFs() = default;
~RealIncFs() = default;
- ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+ Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs) const override {
+ return incfs::createControl(cmd, pendingReads, logs);
+ }
+ ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
NewFileParams params) const override {
return incfs::makeFile(control, path, mode, id, params);
}
- ErrorCode makeDir(Control control, std::string_view path, int mode) const override {
+ ErrorCode makeDir(const Control& control, std::string_view path, int mode) const override {
return incfs::makeDir(control, path, mode);
}
- RawMetadata getMetadata(Control control, FileId fileid) const override {
+ RawMetadata getMetadata(const Control& control, FileId fileid) const override {
return incfs::getMetadata(control, fileid);
}
- RawMetadata getMetadata(Control control, std::string_view path) const override {
+ RawMetadata getMetadata(const Control& control, std::string_view path) const override {
return incfs::getMetadata(control, path);
}
- FileId getFileId(Control control, std::string_view path) const override {
+ FileId getFileId(const Control& control, std::string_view path) const override {
return incfs::getFileId(control, path);
}
- ErrorCode link(Control control, std::string_view from, std::string_view to) const override {
+ ErrorCode link(const Control& control, std::string_view from,
+ std::string_view to) const override {
return incfs::link(control, from, to);
}
- ErrorCode unlink(Control control, std::string_view path) const override {
+ ErrorCode unlink(const Control& control, std::string_view path) const override {
return incfs::unlink(control, path);
}
- base::unique_fd openWrite(Control control, FileId id) const override {
+ base::unique_fd openWrite(const Control& control, FileId id) const override {
return base::unique_fd{incfs::openWrite(control, id)};
}
ErrorCode writeBlocks(Span<const DataBlock> blocks) const override {
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index f5b88d9..c4b4d17 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -164,22 +164,23 @@
class MockIncFs : public IncFsWrapper {
public:
+ MOCK_CONST_METHOD3(createControl, Control(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs));
MOCK_CONST_METHOD5(makeFile,
- ErrorCode(Control control, std::string_view path, int mode, FileId id,
+ ErrorCode(const Control& control, std::string_view path, int mode, FileId id,
NewFileParams params));
- MOCK_CONST_METHOD3(makeDir, ErrorCode(Control control, std::string_view path, int mode));
- MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, FileId fileid));
- MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, std::string_view path));
- MOCK_CONST_METHOD2(getFileId, FileId(Control control, std::string_view path));
+ MOCK_CONST_METHOD3(makeDir, ErrorCode(const Control& control, std::string_view path, int mode));
+ MOCK_CONST_METHOD2(getMetadata, RawMetadata(const Control& control, FileId fileid));
+ MOCK_CONST_METHOD2(getMetadata, RawMetadata(const Control& control, std::string_view path));
+ MOCK_CONST_METHOD2(getFileId, FileId(const Control& control, std::string_view path));
MOCK_CONST_METHOD3(link,
- ErrorCode(Control control, std::string_view from, std::string_view to));
- MOCK_CONST_METHOD2(unlink, ErrorCode(Control control, std::string_view path));
- MOCK_CONST_METHOD2(openWrite, base::unique_fd(Control control, FileId id));
+ ErrorCode(const Control& control, std::string_view from, std::string_view to));
+ MOCK_CONST_METHOD2(unlink, ErrorCode(const Control& control, std::string_view path));
+ MOCK_CONST_METHOD2(openWrite, base::unique_fd(const Control& control, FileId id));
MOCK_CONST_METHOD1(writeBlocks, ErrorCode(Span<const DataBlock> blocks));
void makeFileFails() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(-1)); }
void makeFileSuccess() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(0)); }
- RawMetadata getMountInfoMetadata(Control control, std::string_view path) {
+ RawMetadata getMountInfoMetadata(const Control& control, std::string_view path) {
metadata::Mount m;
m.mutable_storage()->set_id(100);
m.mutable_loader()->set_package_name("com.test");
@@ -189,13 +190,13 @@
m.mutable_loader()->release_package_name();
return {metadata.begin(), metadata.end()};
}
- RawMetadata getStorageMetadata(Control control, std::string_view path) {
+ RawMetadata getStorageMetadata(const Control& control, std::string_view path) {
metadata::Storage st;
st.set_id(100);
auto metadata = st.SerializeAsString();
return {metadata.begin(), metadata.end()};
}
- RawMetadata getBindPointMetadata(Control control, std::string_view path) {
+ RawMetadata getBindPointMetadata(const Control& control, std::string_view path) {
metadata::BindPoint bp;
std::string destPath = "dest";
std::string srcPath = "src";
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c631eeb..d041869 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1069,7 +1069,8 @@
t.traceEnd();
t.traceBegin("StartTelephonyRegistry");
- telephonyRegistry = new TelephonyRegistry(context);
+ telephonyRegistry = new TelephonyRegistry(
+ context, new TelephonyRegistry.ConfigurationProvider());
ServiceManager.addService("telephony.registry", telephonyRegistry);
t.traceEnd();
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java
new file mode 100644
index 0000000..7fc10b1
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/location/AppOpsHelperTest.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.location;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.app.AppOpsManager.OP_COARSE_LOCATION;
+import static android.app.AppOpsManager.OP_FINE_LOCATION;
+import static android.app.AppOpsManager.OP_MOCK_LOCATION;
+import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
+import static android.app.AppOpsManager.OP_MONITOR_LOCATION;
+
+import static com.android.server.location.CallerIdentity.PERMISSION_COARSE;
+import static com.android.server.location.CallerIdentity.PERMISSION_FINE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AppOpsHelperTest {
+
+ private static final long TIMEOUT_MS = 5000;
+
+ @Mock private Context mContext;
+ @Mock private AppOpsManager mAppOps;
+
+ private List<AppOpsManager.OnOpChangedInternalListener> mListeners = new ArrayList<>();
+
+ private AppOpsHelper mHelper;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+
+ doReturn(mAppOps).when(mContext).getSystemService(AppOpsManager.class);
+ doAnswer(invocation -> mListeners.add(invocation.getArgument(3))).when(mAppOps)
+ .startWatchingMode(
+ eq(AppOpsManager.OP_COARSE_LOCATION),
+ isNull(),
+ eq(AppOpsManager.WATCH_FOREGROUND_CHANGES),
+ any(AppOpsManager.OnOpChangedInternalListener.class));
+
+ mHelper = new AppOpsHelper(mContext);
+ mHelper.onSystemReady();
+ }
+
+ private void sendAppOp(String packageName) {
+ for (AppOpsManager.OnOpChangedInternalListener listener : mListeners) {
+ listener.onOpChanged(AppOpsManager.OP_COARSE_LOCATION, packageName);
+ }
+ }
+
+ @Test
+ public void testListener() {
+ AppOpsHelper.LocationAppOpListener listener = mock(
+ AppOpsHelper.LocationAppOpListener.class);
+ mHelper.addListener(listener);
+
+ sendAppOp("mypackage1");
+ verify(listener, timeout(TIMEOUT_MS)).onAppOpsChanged("mypackage1");
+
+ sendAppOp("mypackage2");
+ verify(listener, timeout(TIMEOUT_MS)).onAppOpsChanged("mypackage2");
+ }
+
+ @Test
+ public void testCheckLocationAccess() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).checkOpNoThrow(eq(OP_FINE_LOCATION), eq(1000), eq("mypackage"));
+ assertThat(mHelper.checkLocationAccess(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).checkOpNoThrow(eq(OP_FINE_LOCATION), eq(1000), eq("mypackage"));
+ assertThat(mHelper.checkLocationAccess(identity)).isFalse();
+
+ identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_COARSE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).checkOpNoThrow(eq(OP_COARSE_LOCATION), eq(1000), eq("mypackage"));
+ assertThat(mHelper.checkLocationAccess(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).checkOpNoThrow(eq(OP_COARSE_LOCATION), eq(1000), eq("mypackage"));
+ assertThat(mHelper.checkLocationAccess(identity)).isFalse();
+ }
+
+ @Test
+ public void testNoteLocationAccess() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).noteOpNoThrow(eq(OP_FINE_LOCATION), eq(1000), eq("mypackage"),
+ eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.noteLocationAccess(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).noteOpNoThrow(eq(OP_FINE_LOCATION), eq(1000), eq("mypackage"),
+ eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.noteLocationAccess(identity)).isFalse();
+
+
+ identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_COARSE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).noteOpNoThrow(eq(OP_COARSE_LOCATION), eq(1000), eq("mypackage"),
+ eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.noteLocationAccess(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).noteOpNoThrow(eq(OP_COARSE_LOCATION), eq(1000), eq("mypackage"),
+ eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.noteLocationAccess(identity)).isFalse();
+ }
+
+ @Test
+ public void testStartLocationMonitoring() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).startOpNoThrow(eq(OP_MONITOR_LOCATION), eq(1000), eq("mypackage"),
+ eq(false), eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.startLocationMonitoring(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).startOpNoThrow(eq(OP_MONITOR_LOCATION), eq(1000), eq("mypackage"),
+ eq(false), eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.startLocationMonitoring(identity)).isFalse();
+ }
+
+ @Test
+ public void testStartHighPowerLocationMonitoring() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).startOpNoThrow(eq(OP_MONITOR_HIGH_POWER_LOCATION), eq(1000),
+ eq("mypackage"),
+ eq(false), eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.startHighPowerLocationMonitoring(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).startOpNoThrow(eq(OP_MONITOR_HIGH_POWER_LOCATION), eq(1000),
+ eq("mypackage"),
+ eq(false), eq("myfeature"), nullable(String.class));
+ assertThat(mHelper.startHighPowerLocationMonitoring(identity)).isFalse();
+ }
+
+ @Test
+ public void testStopLocationMonitoring() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ mHelper.stopLocationMonitoring(identity);
+ verify(mAppOps).finishOp(OP_MONITOR_LOCATION, 1000, "mypackage", "myfeature");
+ }
+
+ @Test
+ public void testStopHighPowerLocationMonitoring() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ mHelper.stopHighPowerLocationMonitoring(identity);
+ verify(mAppOps).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, 1000, "mypackage", "myfeature");
+ }
+
+ @Test
+ public void testNoteMockLocationAccess() {
+ CallerIdentity identity = new CallerIdentity(1000, 1000, 1000, "mypackage", "myfeature",
+ PERMISSION_FINE);
+
+ doReturn(MODE_ALLOWED).when(
+ mAppOps).noteOp(eq(OP_MOCK_LOCATION), eq(1000), eq("mypackage"), eq("myfeature"),
+ nullable(String.class));
+ assertThat(mHelper.noteMockLocationAccess(identity)).isTrue();
+
+ doReturn(MODE_IGNORED).when(
+ mAppOps).noteOp(eq(OP_MOCK_LOCATION), eq(1000), eq("mypackage"), eq("myfeature"),
+ nullable(String.class));
+ assertThat(mHelper.noteMockLocationAccess(identity)).isFalse();
+ }
+}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 449e75c..e58e911 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -91,7 +91,15 @@
enabled: false,
},
- data: [":JobTestApp"],
+ data: [
+ ":JobTestApp",
+ ],
+
+ java_resources: [
+ ":PackageParserTestApp1",
+ ":PackageParserTestApp2",
+ ":PackageParserTestApp3",
+ ],
resource_zips: [":FrameworksServicesTests_apks_as_resources"],
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index c1bcf1f..3e5c21c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -68,7 +68,7 @@
public OwnersTestable(MockSystemServices services) {
super(services.userManager, services.userManagerInternal,
services.packageManagerInternal, services.activityTaskManagerInternal,
- new MockInjector(services));
+ services.activityManagerInternal, new MockInjector(services));
}
static class MockInjector extends Injector {
diff --git a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
index be2a5c5..36ab1b3 100644
--- a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
@@ -61,11 +61,12 @@
import com.android.server.LocalServices;
import com.android.server.location.AppForegroundHelper;
+import com.android.server.location.AppOpsHelper;
+import com.android.server.location.LocationUsageLogger;
+import com.android.server.location.SettingsHelper;
import com.android.server.location.gnss.GnssAntennaInfoProvider.GnssAntennaInfoProviderNative;
import com.android.server.location.gnss.GnssMeasurementsProvider.GnssMeasurementProviderNative;
import com.android.server.location.gnss.GnssNavigationMessageProvider.GnssNavigationMessageProviderNative;
-import com.android.server.location.LocationUsageLogger;
-import com.android.server.location.SettingsHelper;
import org.junit.After;
import org.junit.Before;
@@ -77,7 +78,7 @@
import org.mockito.invocation.InvocationOnMock;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -103,7 +104,8 @@
private GnssNavigationMessageProvider mTestGnssNavigationMessageProvider;
private GnssAntennaInfoProvider mTestGnssAntennaInfoProvider;
- // Managers and services
+ @Mock
+ private PackageManager mPackageManager;
@Mock
private AppOpsManager mAppOpsManager;
@Mock
@@ -131,6 +133,9 @@
Context.APP_OPS_SERVICE);
when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(
mAppOpsManager);
+ when(mMockContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(
+ new String[]{"com.android.server"});
enableLocationPermissions();
when(mAppForegroundHelper.isAppForeground(anyInt())).thenReturn(true);
@@ -179,8 +184,11 @@
when(mMockGnssBatchingProvider.start(anyLong(), anyBoolean())).thenReturn(true);
when(mMockGnssBatchingProvider.stop()).thenReturn(true);
+ // Managers and services
+ AppOpsHelper appOpsHelper = new AppOpsHelper(mMockContext);
+
// Create GnssManagerService
- mGnssManagerService = new GnssManagerService(mMockContext, mSettingsHelper,
+ mGnssManagerService = new GnssManagerService(mMockContext, appOpsHelper, mSettingsHelper,
mAppForegroundHelper, new LocationUsageLogger(),
mMockGnssLocationProvider);
mGnssManagerService.onSystemReady();
@@ -232,7 +240,7 @@
new GnssSingleSatCorrection.Builder().build();
return
new GnssMeasurementCorrections.Builder().setSingleSatelliteCorrectionList(
- Arrays.asList(gnssSingleSatCorrection)).build();
+ Collections.singletonList(gnssSingleSatCorrection)).build();
}
private static List<GnssAntennaInfo> createDummyGnssAntennaInfos() {
@@ -262,7 +270,7 @@
signalGainCorrectionsDbi,
signalGainCorrectionsUncertaintyDbi);
- List<GnssAntennaInfo> gnssAntennaInfos = new ArrayList();
+ List<GnssAntennaInfo> gnssAntennaInfos = new ArrayList<>();
gnssAntennaInfos.add(new GnssAntennaInfo.Builder()
.setCarrierFrequencyMHz(carrierFrequencyMHz)
.setPhaseCenterOffset(phaseCenterOffset)
@@ -284,7 +292,7 @@
PackageManager.PERMISSION_GRANTED);
// AppOpsManager will return true if OP_FINE_LOCATION is checked
- when(mAppOpsManager.checkOp(anyInt(), anyInt(), anyString())).thenAnswer(
+ when(mAppOpsManager.checkOpNoThrow(anyInt(), anyInt(), anyString())).thenAnswer(
(InvocationOnMock invocation) -> {
int code = (int) (invocation.getArguments()[0]);
if (code == AppOpsManager.OP_FINE_LOCATION) {
@@ -303,7 +311,7 @@
Mockito.doThrow(new SecurityException()).when(
mMockContext).checkPermission(anyString(), anyInt(), anyInt());
- when(mAppOpsManager.checkOp(anyInt(), anyInt(),
+ when(mAppOpsManager.checkOpNoThrow(anyInt(), anyInt(),
anyString())).thenReturn(AppOpsManager.MODE_ERRORED);
when(mLocationManagerInternal.isProviderEnabledForUser(eq(GPS_PROVIDER), anyInt()))
@@ -390,8 +398,7 @@
when(mMockGnssCapabilitiesProvider.getGnssCapabilities()).thenReturn(mGnssCapabilities);
enableLocationPermissions();
- assertThat(mGnssManagerService.getGnssCapabilities("com.android.server")).isEqualTo(
- mGnssCapabilities);
+ assertThat(mGnssManagerService.getGnssCapabilities()).isEqualTo(mGnssCapabilities);
}
@Test
@@ -421,7 +428,7 @@
assertThrows(SecurityException.class,
() -> mGnssManagerService.startGnssBatch(periodNanos, wakeOnFifoFull,
- "com.android.server"));
+ "com.android.server", null));
verify(mMockGnssBatchingProvider, times(0)).start(periodNanos, wakeOnFifoFull);
}
@@ -433,7 +440,7 @@
enableLocationPermissions();
assertThat(mGnssManagerService.startGnssBatch(periodNanos, wakeOnFifoFull,
- "com.android.server"))
+ "com.android.server", null))
.isEqualTo(
true);
verify(mMockGnssBatchingProvider, times(1)).start(100L, true);
@@ -447,8 +454,7 @@
disableLocationPermissions();
assertThrows(SecurityException.class, () -> mGnssManagerService.addGnssBatchingCallback(
- mockBatchedLocationCallback, "com.android.server", "abcd123",
- "TestBatchedLocationCallback"));
+ mockBatchedLocationCallback, "com.android.server", null));
mGnssManagerService.onReportLocation(mockLocationList);
@@ -463,8 +469,8 @@
enableLocationPermissions();
assertThat(mGnssManagerService.addGnssBatchingCallback(
- mockBatchedLocationCallback, "com.android.server",
- "abcd123", "TestBatchedLocationCallback")).isEqualTo(true);
+ mockBatchedLocationCallback, "com.android.server", null))
+ .isEqualTo(true);
mGnssManagerService.onReportLocation(mockLocationList);
@@ -480,11 +486,11 @@
enableLocationPermissions();
assertThat(mGnssManagerService.addGnssBatchingCallback(
- mockBatchedLocationCallback1, "com.android.server",
- "abcd123", "TestBatchedLocationCallback")).isEqualTo(true);
+ mockBatchedLocationCallback1, "com.android.server", null))
+ .isEqualTo(true);
assertThat(mGnssManagerService.addGnssBatchingCallback(
- mockBatchedLocationCallback2, "com.android.server",
- "abcd123", "TestBatchedLocationCallback")).isEqualTo(true);
+ mockBatchedLocationCallback2, "com.android.server", null))
+ .isEqualTo(true);
mGnssManagerService.onReportLocation(mockLocationList);
@@ -517,7 +523,7 @@
enableLocationPermissions();
mGnssManagerService.addGnssBatchingCallback(mockBatchedLocationCallback,
- "com.android.server", "abcd123", "TestBatchedLocationCallback");
+ "com.android.server", null);
disableLocationPermissions();
@@ -538,7 +544,7 @@
enableLocationPermissions();
mGnssManagerService.addGnssBatchingCallback(mockBatchedLocationCallback,
- "com.android.server", "abcd123", "TestBatchedLocationCallback");
+ "com.android.server", null);
mGnssManagerService.removeGnssBatchingCallback();
@@ -623,7 +629,7 @@
assertThrows(SecurityException.class,
() -> mGnssManagerService.addGnssMeasurementsListener(
new GnssRequest.Builder().build(), mockGnssMeasurementsListener,
- "com.android.server", "abcd123", "TestGnssMeasurementsListener"));
+ "com.android.server", null));
mTestGnssMeasurementsProvider.onMeasurementsAvailable(gnssMeasurementsEvent);
verify(mockGnssMeasurementsListener, times(0)).onGnssMeasurementsReceived(
@@ -642,8 +648,7 @@
assertThat(mGnssManagerService.addGnssMeasurementsListener(
new GnssRequest.Builder().build(),
mockGnssMeasurementsListener,
- "com.android.server", "abcd123",
- "TestGnssMeasurementsListener")).isEqualTo(true);
+ "com.android.server", null)).isEqualTo(true);
mTestGnssMeasurementsProvider.onMeasurementsAvailable(gnssMeasurementsEvent);
verify(mockGnssMeasurementsListener, times(1)).onGnssMeasurementsReceived(
@@ -690,8 +695,7 @@
mGnssManagerService.addGnssMeasurementsListener(new GnssRequest.Builder().build(),
mockGnssMeasurementsListener,
- "com.android.server", "abcd123",
- "TestGnssMeasurementsListener");
+ "com.android.server", null);
disableLocationPermissions();
@@ -714,8 +718,7 @@
mGnssManagerService.addGnssMeasurementsListener(new GnssRequest.Builder().build(),
mockGnssMeasurementsListener,
- "com.android.server", "abcd123",
- "TestGnssMeasurementsListener");
+ "com.android.server", null);
disableLocationPermissions();
@@ -738,7 +741,7 @@
assertThrows(SecurityException.class,
() -> mGnssManagerService.addGnssAntennaInfoListener(
mockGnssAntennaInfoListener,
- "com.android.server", "abcd123", "TestGnssAntennaInfoListener"));
+ "com.android.server", null));
mTestGnssAntennaInfoProvider.onGnssAntennaInfoAvailable(gnssAntennaInfos);
verify(mockGnssAntennaInfoListener, times(0))
@@ -754,7 +757,7 @@
enableLocationPermissions();
assertThat(mGnssManagerService.addGnssAntennaInfoListener(mockGnssAntennaInfoListener,
- "com.android.server", "abcd123", "TestGnssAntennaInfoListener")).isEqualTo(true);
+ "com.android.server", null)).isEqualTo(true);
mTestGnssAntennaInfoProvider.onGnssAntennaInfoAvailable(gnssAntennaInfos);
verify(mockGnssAntennaInfoListener, times(1))
@@ -771,7 +774,7 @@
mGnssManagerService.addGnssAntennaInfoListener(
mockGnssAntennaInfoListener,
- "com.android.server", "abcd123", "TestGnssAntennaInfoListener");
+ "com.android.server", null);
disableLocationPermissions();
@@ -793,7 +796,7 @@
mGnssManagerService.addGnssAntennaInfoListener(
mockGnssAntennaInfoListener,
- "com.android.server", "abcd123", "TestGnssAntennaInfoListener");
+ "com.android.server", null);
mGnssManagerService.removeGnssAntennaInfoListener(
mockGnssAntennaInfoListener);
@@ -813,8 +816,7 @@
assertThrows(SecurityException.class,
() -> mGnssManagerService.addGnssNavigationMessageListener(
- mockGnssNavigationMessageListener, "com.android.server",
- "abcd123", "TestGnssNavigationMessageListener"));
+ mockGnssNavigationMessageListener, "com.android.server", null));
mTestGnssNavigationMessageProvider.onNavigationMessageAvailable(gnssNavigationMessage);
@@ -831,8 +833,8 @@
enableLocationPermissions();
assertThat(mGnssManagerService.addGnssNavigationMessageListener(
- mockGnssNavigationMessageListener, "com.android.server",
- "abcd123", "TestGnssNavigationMessageListener")).isEqualTo(true);
+ mockGnssNavigationMessageListener, "com.android.server", null))
+ .isEqualTo(true);
mTestGnssNavigationMessageProvider.onNavigationMessageAvailable(gnssNavigationMessage);
@@ -849,8 +851,7 @@
enableLocationPermissions();
mGnssManagerService.addGnssNavigationMessageListener(
- mockGnssNavigationMessageListener, "com.android.server",
- "abcd123", "TestGnssNavigationMessageListener");
+ mockGnssNavigationMessageListener, "com.android.server", null);
disableLocationPermissions();
@@ -872,8 +873,7 @@
enableLocationPermissions();
mGnssManagerService.addGnssNavigationMessageListener(
- mockGnssNavigationMessageListener, "com.android.server",
- "abcd123", "TestGnssNavigationMessageListener");
+ mockGnssNavigationMessageListener, "com.android.server", null);
mGnssManagerService.removeGnssNavigationMessageListener(
mockGnssNavigationMessageListener);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java b/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java
index c5e924b..2bcd653 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java
@@ -23,6 +23,7 @@
private int mDeviceProvisioned;
private int mSecureFrpMode;
+ private int mUserSetupComplete;
public void setDeviceProvisioned(boolean provisioned) {
mDeviceProvisioned = provisioned ? 1 : 0;
@@ -32,6 +33,10 @@
mSecureFrpMode = secure ? 1 : 0;
}
+ public void setUserSetupComplete(boolean complete) {
+ mUserSetupComplete = complete ? 1 : 0;
+ }
+
public int globalGetInt(String keyName) {
switch (keyName) {
case Settings.Global.DEVICE_PROVISIONED:
@@ -46,6 +51,10 @@
if (Settings.Secure.SECURE_FRP_MODE.equals(keyName) && userId == UserHandle.USER_SYSTEM) {
return mSecureFrpMode;
}
+ if (Settings.Secure.USER_SETUP_COMPLETE.equals(keyName)
+ && userId == UserHandle.USER_SYSTEM) {
+ return mUserSetupComplete;
+ }
return defaultValue;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
index 661ce11..07d7830 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -417,7 +417,8 @@
}
@Test
- public void testCredentialChangeNotPossibleInSecureFrpMode() {
+ public void testCredentialChangeNotPossibleInSecureFrpModeDuringSuw() {
+ mSettings.setUserSetupComplete(false);
mSettings.setSecureFrpMode(true);
try {
mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID);
@@ -425,6 +426,14 @@
} catch (SecurityException e) { }
}
+ @Test
+ public void testCredentialChangePossibleInSecureFrpModeAfterSuw() {
+ mSettings.setUserSetupComplete(true);
+ mSettings.setSecureFrpMode(true);
+ assertTrue(mService.setLockCredential(newPassword("1234"), nonePassword(),
+ PRIMARY_USER_ID));
+ }
+
private void testCreateCredential(int userId, LockscreenCredential credential)
throws RemoteException {
assertTrue(mService.setLockCredential(credential, nonePassword(), userId));
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 8982925..ba85199 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -53,6 +53,7 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import java.io.File;
import java.util.ArrayList;
@@ -104,7 +105,7 @@
protected void initializeCredentialUnderSP(LockscreenCredential password, int userId)
throws RemoteException {
enableSyntheticPassword();
- mService.setLockCredential(password, nonePassword(), userId);
+ assertTrue(mService.setLockCredential(password, nonePassword(), userId));
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(userId));
assertTrue(mService.isSyntheticPasswordBasedCredential(userId));
}
@@ -492,6 +493,44 @@
verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
}
+ @Test
+ public void testUnlockUserWithToken() throws Exception {
+ LockscreenCredential password = newPassword("password");
+ byte[] token = "some-high-entropy-secure-token".getBytes();
+ initializeCredentialUnderSP(password, PRIMARY_USER_ID);
+ // Disregard any reportPasswordChanged() invocations as part of credential setup.
+ flushHandlerTasks();
+ reset(mDevicePolicyManager);
+
+ long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
+ mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
+ assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
+
+ mService.onCleanupUser(PRIMARY_USER_ID);
+ assertNull(mLocalService.getUserPasswordMetrics(PRIMARY_USER_ID));
+
+ assertTrue(mLocalService.unlockUserWithToken(handle, token, PRIMARY_USER_ID));
+ assertEquals(PasswordMetrics.computeForCredential(password),
+ mLocalService.getUserPasswordMetrics(PRIMARY_USER_ID));
+ }
+
+ @Test
+ public void testPasswordChange_NoOrphanedFilesLeft() throws Exception {
+ LockscreenCredential password = newPassword("password");
+ initializeCredentialUnderSP(password, PRIMARY_USER_ID);
+ assertTrue(mService.setLockCredential(password, password, PRIMARY_USER_ID));
+
+ String handleString = String.format("%016x",
+ mService.getSyntheticPasswordHandleLocked(PRIMARY_USER_ID));
+ File directory = mStorage.getSyntheticPasswordDirectoryForUser(PRIMARY_USER_ID);
+ for (File file : directory.listFiles()) {
+ String[] parts = file.getName().split("\\.");
+ if (!parts[0].equals(handleString) && !parts[0].equals("0000000000000000")) {
+ fail("Orphaned state left: " + file.getName());
+ }
+ }
+ }
+
// b/62213311
//TODO: add non-migration work profile case, and unify/un-unify transition.
//TODO: test token after user resets password
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 22591c6..5109de5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -17,6 +17,7 @@
package com.android.server.pm;
+import static org.hamcrest.Matchers.arrayContaining;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -47,6 +48,7 @@
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,7 +58,9 @@
import org.mockito.MockitoAnnotations;
import java.security.cert.CertificateException;
+import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -635,6 +639,57 @@
appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, target, instrumentation, 0));
}
+ @Test
+ public void testWhoCanSee() throws Exception {
+ final AppsFilter appsFilter =
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ appsFilter.onSystemReady();
+
+ final int systemAppId = Process.FIRST_APPLICATION_UID - 1;
+ final int seesNothingAppId = Process.FIRST_APPLICATION_UID;
+ final int hasProviderAppId = Process.FIRST_APPLICATION_UID + 1;
+ final int queriesProviderAppId = Process.FIRST_APPLICATION_UID + 2;
+ PackageSetting system = simulateAddPackage(appsFilter, pkg("some.system.pkg"), systemAppId);
+ PackageSetting seesNothing = simulateAddPackage(appsFilter, pkg("some.system.pkg"),
+ seesNothingAppId);
+ PackageSetting hasProvider = simulateAddPackage(appsFilter,
+ pkgWithProvider("com.some.package", "com.some.authority"), hasProviderAppId);
+ PackageSetting queriesProvider = simulateAddPackage(appsFilter,
+ pkgQueriesProvider("com.some.other.package", "com.some.authority"),
+ queriesProviderAppId);
+
+ final int[] systemFilter =
+ appsFilter.getVisibilityWhitelist(system, new int[]{0}, mExisting).get(0);
+ assertThat(Arrays.asList(systemFilter), arrayContaining(systemAppId));
+
+ final int[] seesNothingFilter =
+ appsFilter.getVisibilityWhitelist(seesNothing, new int[]{0}, mExisting).get(0);
+ assertThat(Arrays.asList(seesNothingFilter),
+ arrayContaining(systemAppId, seesNothingAppId));
+
+ final int[] hasProviderFilter =
+ appsFilter.getVisibilityWhitelist(hasProvider, new int[]{0}, mExisting).get(0);
+ assertThat(Arrays.asList(hasProviderFilter),
+ arrayContaining(systemAppId, hasProviderAppId, queriesProviderAppId));
+
+ int[] queriesProviderFilter =
+ appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0);
+ assertThat(Arrays.asList(queriesProviderFilter),
+ arrayContaining(systemAppId, queriesProviderAppId));
+
+ // provider read
+ appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId);
+
+ // ensure implicit access is included in the filter
+ queriesProviderFilter =
+ appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0);
+ assertThat(Arrays.asList(queriesProviderFilter),
+ arrayContaining(systemAppId, hasProviderAppId, queriesProviderAppId));
+ }
+
+ private void assertThat(List<int[]> asList, Matcher<Integer[]> arrayContainingInAnyOrder) {
+ }
+
private interface WithSettingBuilder {
PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 9cf6702..0a68688 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -18,6 +18,7 @@
import android.content.IIntentReceiver;
import android.os.Bundle;
+import android.util.SparseArray;
import androidx.test.runner.AndroidJUnit4;
@@ -47,7 +48,7 @@
public void sendPackageBroadcast(final String action, final String pkg,
final Bundle extras, final int flags, final String targetPkg,
final IIntentReceiver finishedReceiver, final int[] userIds,
- int[] instantUserIds) {
+ int[] instantUserIds, SparseArray<int[]> broadcastWhitelist) {
}
public void sendPackageAddedForNewUsers(String packageName,
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index a19d919..d760629 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -17,11 +17,15 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+
import android.annotation.NonNull;
+import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
@@ -30,7 +34,6 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
-import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.pm.parsing.ParsingPackage;
@@ -49,6 +52,7 @@
import android.util.DisplayMetrics;
import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -69,9 +73,11 @@
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -90,6 +96,9 @@
private File mTmpDir;
private static final File FRAMEWORK = new File("/system/framework/framework-res.apk");
+ private static final String TEST_APP1_APK = "PackageParserTestApp1.apk";
+ private static final String TEST_APP2_APK = "PackageParserTestApp2.apk";
+ private static final String TEST_APP3_APK = "PackageParserTestApp3.apk";
@Before
public void setUp() throws IOException {
@@ -209,6 +218,61 @@
assertSame(deserialized.getSharedUserId(), deserialized2.getSharedUserId());
}
+ private static PackageParser2 makeParser() {
+ return new PackageParser2(null, false, null, null, null);
+ }
+
+ private File extractFile(String filename) throws Exception {
+ final Context context = InstrumentationRegistry.getTargetContext();
+ final File tmpFile = File.createTempFile(filename, ".apk");
+ try (InputStream inputStream = context.getAssets().openNonAsset(filename)) {
+ Files.copy(inputStream, tmpFile.toPath(), REPLACE_EXISTING);
+ }
+ return tmpFile;
+ }
+
+ /**
+ * Tests AndroidManifest.xml with no android:isolatedSplits attribute.
+ */
+ @Test
+ public void testParseIsolatedSplitsDefault() throws Exception {
+ final File testFile = extractFile(TEST_APP1_APK);
+ try {
+ final ParsedPackage pkg = makeParser().parsePackage(testFile, 0, false);
+ assertFalse("isolatedSplits", pkg.isIsolatedSplitLoading());
+ } finally {
+ testFile.delete();
+ }
+ }
+
+ /**
+ * Tests AndroidManifest.xml with an android:isolatedSplits attribute set to a constant.
+ */
+ @Test
+ public void testParseIsolatedSplitsConstant() throws Exception {
+ final File testFile = extractFile(TEST_APP2_APK);
+ try {
+ final ParsedPackage pkg = makeParser().parsePackage(testFile, 0, false);
+ assertTrue("isolatedSplits", pkg.isIsolatedSplitLoading());
+ } finally {
+ testFile.delete();
+ }
+ }
+
+ /**
+ * Tests AndroidManifest.xml with an android:isolatedSplits attribute set to a resource.
+ */
+ @Test
+ public void testParseIsolatedSplitsResource() throws Exception {
+ final File testFile = extractFile(TEST_APP3_APK);
+ try {
+ final ParsedPackage pkg = makeParser().parsePackage(testFile, 0, false);
+ assertTrue("isolatedSplits", pkg.isIsolatedSplitLoading());
+ } finally {
+ testFile.delete();
+ }
+ }
+
/**
* A trivial subclass of package parser that only caches the package name, and throws away
* all other information.
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
index fc5a0ba..7c3efeb 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -84,6 +84,10 @@
oldUserState = new PackageUserState();
oldUserState.suspended = true;
assertThat(testUserState.equals(oldUserState), is(false));
+
+ oldUserState = new PackageUserState();
+ oldUserState.uninstallReason = PackageManager.UNINSTALL_REASON_USER_TYPE;
+ assertThat(testUserState.equals(oldUserState), is(false));
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
index 9e067304..615fa5c 100644
--- a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
@@ -17,6 +17,7 @@
package com.android.server.power;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -29,6 +30,7 @@
import android.content.Context;
import android.hardware.thermal.V2_0.TemperatureThreshold;
+import android.hardware.thermal.V2_0.ThrottlingSeverity;
import android.os.CoolingDevice;
import android.os.IBinder;
import android.os.IPowerManager;
@@ -91,6 +93,7 @@
private static final int INIT_STATUS = Temperature.THROTTLING_NONE;
private ArrayList<Temperature> mTemperatureList = new ArrayList<>();
private ArrayList<CoolingDevice> mCoolingDeviceList = new ArrayList<>();
+ private ArrayList<TemperatureThreshold> mTemperatureThresholdList = initializeThresholds();
private Temperature mSkin1 = new Temperature(0, Temperature.TYPE_SKIN, "skin1",
INIT_STATUS);
@@ -103,6 +106,35 @@
private CoolingDevice mCpu = new CoolingDevice(0, CoolingDevice.TYPE_BATTERY, "cpu");
private CoolingDevice mGpu = new CoolingDevice(0, CoolingDevice.TYPE_BATTERY, "gpu");
+ private ArrayList<TemperatureThreshold> initializeThresholds() {
+ ArrayList<TemperatureThreshold> thresholds = new ArrayList<>();
+
+ TemperatureThreshold skinThreshold = new TemperatureThreshold();
+ skinThreshold.type = Temperature.TYPE_SKIN;
+ skinThreshold.name = "skin1";
+ skinThreshold.hotThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/];
+ for (int i = 0; i < skinThreshold.hotThrottlingThresholds.length; ++i) {
+ // Sets NONE to 25.0f, SEVERE to 40.0f, and SHUTDOWN to 55.0f
+ skinThreshold.hotThrottlingThresholds[i] = 25.0f + 5.0f * i;
+ }
+ thresholds.add(skinThreshold);
+
+ TemperatureThreshold cpuThreshold = new TemperatureThreshold();
+ cpuThreshold.type = Temperature.TYPE_CPU;
+ cpuThreshold.name = "cpu";
+ cpuThreshold.hotThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/];
+ for (int i = 0; i < cpuThreshold.hotThrottlingThresholds.length; ++i) {
+ if (i == ThrottlingSeverity.SEVERE) {
+ cpuThreshold.hotThrottlingThresholds[i] = 95.0f;
+ } else {
+ cpuThreshold.hotThrottlingThresholds[i] = Float.NaN;
+ }
+ }
+ thresholds.add(cpuThreshold);
+
+ return thresholds;
+ }
+
ThermalHalFake() {
mTemperatureList.add(mSkin1);
mTemperatureList.add(mSkin2);
@@ -139,7 +171,14 @@
@Override
protected List<TemperatureThreshold> getTemperatureThresholds(boolean shouldFilter,
int type) {
- return new ArrayList<>();
+ List<TemperatureThreshold> ret = new ArrayList<>();
+ for (TemperatureThreshold threshold : mTemperatureThresholdList) {
+ if (shouldFilter && type != threshold.type) {
+ continue;
+ }
+ ret.add(threshold);
+ }
+ return ret;
}
@Override
@@ -351,4 +390,67 @@
Arrays.asList(mService.mService.getCurrentCoolingDevicesWithType(
CoolingDevice.TYPE_CPU)));
}
+
+ @Test
+ public void testTemperatureWatcherUpdateSevereThresholds() throws RemoteException {
+ ThermalManagerService.TemperatureWatcher watcher = mService.mTemperatureWatcher;
+ watcher.mSevereThresholds.erase();
+ watcher.updateSevereThresholds();
+ assertEquals(1, watcher.mSevereThresholds.size());
+ assertEquals("skin1", watcher.mSevereThresholds.keyAt(0));
+ Float threshold = watcher.mSevereThresholds.get("skin1");
+ assertNotNull(threshold);
+ assertEquals(40.0f, threshold, 0.0f);
+ }
+
+ @Test
+ public void testTemperatureWatcherGetSlopeOf() throws RemoteException {
+ ThermalManagerService.TemperatureWatcher watcher = mService.mTemperatureWatcher;
+ List<ThermalManagerService.TemperatureWatcher.Sample> samples = new ArrayList<>();
+ for (int i = 0; i < 30; ++i) {
+ samples.add(watcher.createSampleForTesting(i, (float) (i / 2 * 2)));
+ }
+ assertEquals(1.0f, watcher.getSlopeOf(samples), 0.01f);
+ }
+
+ @Test
+ public void testTemperatureWatcherNormalizeTemperature() throws RemoteException {
+ ThermalManagerService.TemperatureWatcher watcher = mService.mTemperatureWatcher;
+ assertEquals(0.5f, watcher.normalizeTemperature(25.0f, 40.0f), 0.0f);
+
+ // Temperatures more than 30 degrees below the SEVERE threshold should be clamped to 0.0f
+ assertEquals(0.0f, watcher.normalizeTemperature(0.0f, 40.0f), 0.0f);
+
+ // Temperatures above the SEVERE threshold should not be clamped
+ assertEquals(2.0f, watcher.normalizeTemperature(70.0f, 40.0f), 0.0f);
+ }
+
+ @Test
+ public void testTemperatureWatcherGetForecast() throws RemoteException {
+ ThermalManagerService.TemperatureWatcher watcher = mService.mTemperatureWatcher;
+
+ ArrayList<ThermalManagerService.TemperatureWatcher.Sample> samples = new ArrayList<>();
+
+ // Add a single sample
+ samples.add(watcher.createSampleForTesting(0, 25.0f));
+ watcher.mSamples.put("skin1", samples);
+
+ // Because there are not enough samples to compute the linear regression,
+ // no matter how far ahead we forecast, we should receive the same value
+ assertEquals(0.5f, watcher.getForecast(0), 0.0f);
+ assertEquals(0.5f, watcher.getForecast(5), 0.0f);
+
+ // Add some time-series data
+ for (int i = 1; i < 20; ++i) {
+ samples.add(0, watcher.createSampleForTesting(1000 * i, 25.0f + 0.5f * i));
+ }
+
+ // Now the forecast should vary depending on how far ahead we are trying to predict
+ assertEquals(0.9f, watcher.getForecast(4), 0.02f);
+ assertEquals(1.0f, watcher.getForecast(10), 0.02f);
+
+ // If there are no thresholds, then we shouldn't receive a headroom value
+ watcher.mSevereThresholds.erase();
+ assertTrue(Float.isNaN(watcher.getForecast(0)));
+ }
}
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/Android.bp b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp
new file mode 100644
index 0000000..c409438
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp
@@ -0,0 +1,53 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test_helper_app {
+ name: "PackageParserTestApp1",
+ sdk_version: "current",
+ srcs: ["**/*.java"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ manifest: "AndroidManifestApp1.xml",
+}
+
+android_test_helper_app {
+ name: "PackageParserTestApp2",
+ sdk_version: "current",
+ srcs: ["**/*.java"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ manifest: "AndroidManifestApp2.xml",
+}
+
+android_test_helper_app {
+ name: "PackageParserTestApp3",
+ sdk_version: "current",
+ srcs: ["**/*.java"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ resource_dirs: ["res"],
+ manifest: "AndroidManifestApp3.xml",
+}
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp1.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp1.xml
new file mode 100644
index 0000000..01d335d
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp1.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.servicestests.apps.packageparserapp" >
+
+ <application>
+ <activity android:name=".TestActivity"
+ android:exported="true" />
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp2.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp2.xml
new file mode 100644
index 0000000..567946c
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp2.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.servicestests.apps.packageparserapp"
+ android:isolatedSplits="true" >
+
+ <application>
+ <activity android:name=".TestActivity"
+ android:exported="true" />
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp3.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp3.xml
new file mode 100644
index 0000000..77285a8
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp3.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.servicestests.apps.packageparserapp"
+ android:isolatedSplits="@bool/config_isIsolated" >
+
+ <application>
+ <activity android:name=".TestActivity"
+ android:exported="true" />
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml b/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml
new file mode 100644
index 0000000..6a4cc65
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <bool name="config_isIsolated">true</bool>
+</resources>
\ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/TestActivity.java b/services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/TestActivity.java
new file mode 100644
index 0000000..2eacb96
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/TestActivity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.servicestests.apps.packageparserapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class TestActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ finish();
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java
index c7cef05..0dbbbaa 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java
@@ -47,6 +47,7 @@
public class BubbleExtractorTest extends UiServiceTestCase {
@Mock RankingConfig mConfig;
+ @Mock BubbleExtractor.BubbleChecker mBubbleChecker;
BubbleExtractor mBubbleExtractor;
private String mPkg = "com.android.server.notification";
@@ -141,4 +142,33 @@
assertFalse(r.canBubble());
}
+
+ @Test
+ public void testFlagBubble_true() {
+ when(mConfig.bubblesEnabled()).thenReturn(true);
+ when(mConfig.areBubblesAllowed(mPkg, mUid)).thenReturn(true);
+ NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
+
+ mBubbleExtractor.setBubbleChecker(mBubbleChecker);
+ when(mBubbleChecker.isNotificationAppropriateToBubble(r)).thenReturn(true);
+ mBubbleExtractor.process(r);
+
+ assertTrue(r.canBubble());
+ assertTrue(r.getNotification().isBubbleNotification());
+ }
+
+ @Test
+ public void testFlagBubble_noFlag_previouslyRemoved() {
+ when(mConfig.bubblesEnabled()).thenReturn(true);
+ when(mConfig.areBubblesAllowed(mPkg, mUid)).thenReturn(true);
+ NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
+ r.setFlagBubbleRemoved(true);
+
+ mBubbleExtractor.setBubbleChecker(mBubbleChecker);
+ when(mBubbleChecker.isNotificationAppropriateToBubble(r)).thenReturn(true);
+ mBubbleExtractor.process(r);
+
+ assertTrue(r.canBubble());
+ assertFalse(r.getNotification().isBubbleNotification());
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index d2417f9..f083f0e 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -78,6 +78,7 @@
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.AutomaticZenRule;
import android.app.IActivityManager;
@@ -131,6 +132,7 @@
import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenPolicy;
+import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
@@ -154,6 +156,7 @@
import com.android.internal.logging.InstanceIdSequenceFake;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.util.FastXmlSerializer;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.UiServiceTestCase;
@@ -380,12 +383,20 @@
MockitoAnnotations.initMocks(this);
+ DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
+ when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L);
+ ActivityManagerInternal activityManagerInternal = mock(ActivityManagerInternal.class);
+
LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
LocalServices.removeServiceForTest(WindowManagerInternal.class);
LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
LocalServices.addService(StatusBarManagerInternal.class, mStatusBar);
+ LocalServices.removeServiceForTest(DeviceIdleInternal.class);
+ LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.addService(ActivityManagerInternal.class, activityManagerInternal);
doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
@@ -457,7 +468,8 @@
mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
mGroupHelper, mAm, mAtm, mAppUsageStats,
mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
- mAppOpsManager, mUm, mHistoryManager, mStatsManager);
+ mAppOpsManager, mUm, mHistoryManager, mStatsManager,
+ mock(TelephonyManager.class));
mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
mService.setAudioManager(mAudioManager);
@@ -5592,6 +5604,67 @@
}
@Test
+ public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception {
+ // Bubbles are allowed!
+ setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
+ // Notif with bubble metadata
+ NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
+ "testNotificationBubbleIsFlagRemoved_resetOnUpdate");
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+ nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+ waitForIdle();
+ // Flag shouldn't be modified
+ NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
+ assertFalse(recordToCheck.isFlagBubbleRemoved());
+
+ // Notify we're not a bubble
+ mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
+ waitForIdle();
+ // Flag should be modified
+ recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
+ assertTrue(recordToCheck.isFlagBubbleRemoved());
+
+
+ // Update the notif
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+ nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+ waitForIdle();
+ // And the flag is reset
+ recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
+ assertFalse(recordToCheck.isFlagBubbleRemoved());
+ }
+
+ @Test
+ public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception {
+ // Bubbles are allowed!
+ setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
+ // Notif with bubble metadata
+ NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
+ "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue");
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+ nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+ waitForIdle();
+ // Flag shouldn't be modified
+ NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
+ assertFalse(recordToCheck.isFlagBubbleRemoved());
+
+ // Notify we're not a bubble
+ mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
+ waitForIdle();
+ // Flag should be modified
+ recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
+ assertTrue(recordToCheck.isFlagBubbleRemoved());
+
+ // Notify we are a bubble
+ mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
+ waitForIdle();
+ // And the flag is reset
+ assertFalse(recordToCheck.isFlagBubbleRemoved());
+ }
+
+ @Test
public void testOnBubbleNotificationSuppressionChanged() throws Exception {
// Bubbles are allowed!
setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java
index 1e6270d..fd68046 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java
@@ -60,16 +60,16 @@
@Test
public void testSmallHash() {
- assertEquals(0, NotificationRecordLogger.smallHash(0));
- final int maxHash = NotificationRecordLogger.MAX_HASH;
+ assertEquals(0, SmallHash.hash(0));
+ final int maxHash = SmallHash.MAX_HASH;
assertEquals(0,
- NotificationRecordLogger.smallHash(maxHash));
+ SmallHash.hash(maxHash));
assertEquals(0,
- NotificationRecordLogger.smallHash(17 * maxHash));
+ SmallHash.hash(17 * maxHash));
assertEquals(maxHash - 1,
- NotificationRecordLogger.smallHash(maxHash - 1));
+ SmallHash.hash(maxHash - 1));
assertEquals(maxHash - 1,
- NotificationRecordLogger.smallHash(-1));
+ SmallHash.hash(-1));
}
@Test
@@ -78,10 +78,10 @@
getNotificationRecordPair(0, null).getNotificationIdHash());
assertEquals(1,
getNotificationRecordPair(1, null).getNotificationIdHash());
- assertEquals(NotificationRecordLogger.MAX_HASH - 1,
+ assertEquals(SmallHash.MAX_HASH - 1,
getNotificationRecordPair(-1, null).getNotificationIdHash());
final String tag = "someTag";
- final int hash = NotificationRecordLogger.smallHash(tag.hashCode());
+ final int hash = SmallHash.hash(tag.hashCode());
assertEquals(hash, getNotificationRecordPair(0, tag).getNotificationIdHash());
// We xor the tag and hashcode together before compressing the range. The order of
// operations doesn't matter if id is small.
@@ -89,19 +89,19 @@
getNotificationRecordPair(1, tag).getNotificationIdHash());
// But it does matter for an id with more 1 bits than fit in the small hash.
assertEquals(
- NotificationRecordLogger.smallHash(-1 ^ tag.hashCode()),
+ SmallHash.hash(-1 ^ tag.hashCode()),
getNotificationRecordPair(-1, tag).getNotificationIdHash());
assertNotEquals(-1 ^ hash,
- NotificationRecordLogger.smallHash(-1 ^ tag.hashCode()));
+ SmallHash.hash(-1 ^ tag.hashCode()));
}
@Test
public void testGetChannelIdHash() {
assertEquals(
- NotificationRecordLogger.smallHash(CHANNEL_ID.hashCode()),
+ SmallHash.hash(CHANNEL_ID.hashCode()),
getNotificationRecordPair(0, null).getChannelIdHash());
assertNotEquals(
- NotificationRecordLogger.smallHash(CHANNEL_ID.hashCode()),
+ SmallHash.hash(CHANNEL_ID.hashCode()),
CHANNEL_ID.hashCode());
}
@@ -113,7 +113,7 @@
final String group = "someGroup";
p.r.setOverrideGroupKey(group);
assertEquals(
- NotificationRecordLogger.smallHash(group.hashCode()),
+ SmallHash.hash(group.hashCode()),
p.getGroupIdHash());
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
index 19ff683..3281c3f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -47,6 +47,7 @@
import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
+import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
@@ -153,7 +154,7 @@
mock(DevicePolicyManagerInternal.class), mock(IUriGrantsManager.class),
mock(UriGrantsManagerInternal.class),
mock(AppOpsManager.class), mUm, mock(NotificationHistoryManager.class),
- mock(StatsManager.class));
+ mock(StatsManager.class), mock(TelephonyManager.class));
} catch (SecurityException e) {
if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
throw e;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 4f84ee1..05604b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -69,11 +69,11 @@
stack.moveToFront("moveStackToFront");
// After moving the stack to front, the previous focused should be the last focused.
assertTrue(stack.isFocusedStackOnDisplay());
- assertEquals(prevFocusedStack, display.getLastFocusedStack());
+ assertEquals(prevFocusedStack, display.mTaskContainers.getLastFocusedStack());
stack.moveToBack("moveStackToBack", null /* task */);
// After moving the stack to back, the stack should be the last focused.
- assertEquals(stack, display.getLastFocusedStack());
+ assertEquals(stack, display.mTaskContainers.getLastFocusedStack());
}
/**
@@ -225,7 +225,7 @@
final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
.setStack(alwaysOnTopStack).build();
alwaysOnTopStack.setAlwaysOnTop(true);
- display.positionStackAtTop(alwaysOnTopStack, false /* includingParents */);
+ display.mTaskContainers.positionStackAtTop(alwaysOnTopStack, false /* includingParents */);
assertTrue(alwaysOnTopStack.isAlwaysOnTop());
// Ensure always on top state is synced to the children of the stack.
assertTrue(alwaysOnTopStack.getTopNonFinishingActivity().isAlwaysOnTop());
@@ -239,7 +239,8 @@
final ActivityStack anotherAlwaysOnTopStack = display.createStack(
WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
anotherAlwaysOnTopStack.setAlwaysOnTop(true);
- display.positionStackAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
+ display.mTaskContainers.positionStackAtTop(anotherAlwaysOnTopStack,
+ false /* includingParents */);
assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
int topPosition = display.getStackCount() - 1;
// Ensure the new alwaysOnTop stack is put below the pinned stack, but on top of the
@@ -255,7 +256,8 @@
assertEquals(nonAlwaysOnTopStack, display.getStackAt(topPosition - 3));
anotherAlwaysOnTopStack.setAlwaysOnTop(false);
- display.positionStackAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
+ display.mTaskContainers.positionStackAtTop(anotherAlwaysOnTopStack,
+ false /* includingParents */);
assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
// Ensure, when always on top is turned off for a stack, the stack is put just below all
// other always on top stacks.
@@ -300,7 +302,7 @@
// Reordering stacks while removing stacks.
doAnswer(invocation -> {
- display.positionStackAtTop(stack3, false);
+ display.mTaskContainers.positionStackAtTop(stack3, false);
return true;
}).when(mSupervisor).removeTask(eq(task4), anyBoolean(), anyBoolean(), any());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 12934ee..71ca878 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -613,7 +613,7 @@
// Ensure that we don't move the home stack if it is already behind the top fullscreen stack
int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
assertEquals(fullscreenStack, mDefaultDisplay.getStackAbove(homeStack));
- mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack);
+ mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(homeStack);
assertEquals(homeStackIndex, mDefaultDisplay.getIndexOf(homeStack));
}
@@ -632,7 +632,7 @@
// Ensure that we don't move the home stack if it is already behind the top fullscreen stack
int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
assertEquals(fullscreenStack, mDefaultDisplay.getStackAbove(homeStack));
- mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack);
+ mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(homeStack);
assertEquals(homeStackIndex, mDefaultDisplay.getIndexOf(homeStack));
}
@@ -651,7 +651,7 @@
// Ensure we don't move the home stack if it is already on top
int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
assertNull(mDefaultDisplay.getStackAbove(homeStack));
- mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack);
+ mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(homeStack);
assertEquals(homeStackIndex, mDefaultDisplay.getIndexOf(homeStack));
}
@@ -677,7 +677,7 @@
// Ensure that we move the home stack behind the bottom most fullscreen stack, ignoring the
// pinned stack
assertEquals(fullscreenStack1, mDefaultDisplay.getStackAbove(homeStack));
- mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack);
+ mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(homeStack);
assertEquals(fullscreenStack2, mDefaultDisplay.getStackAbove(homeStack));
}
@@ -702,7 +702,7 @@
// Ensure that we move the home stack behind the bottom most non-translucent fullscreen
// stack
assertEquals(fullscreenStack1, mDefaultDisplay.getStackAbove(homeStack));
- mDefaultDisplay.moveStackBehindBottomMostVisibleStack(homeStack);
+ mDefaultDisplay.mTaskContainers.moveStackBehindBottomMostVisibleStack(homeStack);
assertEquals(fullscreenStack1, mDefaultDisplay.getStackAbove(homeStack));
}
@@ -725,7 +725,7 @@
// Ensure we don't move the home stack behind itself
int homeStackIndex = mDefaultDisplay.getIndexOf(homeStack);
- mDefaultDisplay.moveStackBehindStack(homeStack, homeStack);
+ mDefaultDisplay.mTaskContainers.moveStackBehindStack(homeStack, homeStack);
assertEquals(homeStackIndex, mDefaultDisplay.getIndexOf(homeStack));
}
@@ -748,13 +748,13 @@
final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack1);
+ mDefaultDisplay.mTaskContainers.moveStackBehindStack(homeStack, fullscreenStack1);
assertEquals(fullscreenStack1, mDefaultDisplay.getStackAbove(homeStack));
- mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack2);
+ mDefaultDisplay.mTaskContainers.moveStackBehindStack(homeStack, fullscreenStack2);
assertEquals(fullscreenStack2, mDefaultDisplay.getStackAbove(homeStack));
- mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack4);
+ mDefaultDisplay.mTaskContainers.moveStackBehindStack(homeStack, fullscreenStack4);
assertEquals(fullscreenStack4, mDefaultDisplay.getStackAbove(homeStack));
- mDefaultDisplay.moveStackBehindStack(homeStack, fullscreenStack2);
+ mDefaultDisplay.mTaskContainers.moveStackBehindStack(homeStack, fullscreenStack2);
assertEquals(fullscreenStack2, mDefaultDisplay.getStackAbove(homeStack));
}
@@ -845,9 +845,10 @@
// Home stack and activity are created in ActivityTestsBase#setupActivityManagerService
stack = mDefaultDisplay.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
if (onTop) {
- mDefaultDisplay.positionStackAtTop(stack, false /* includingParents */);
+ mDefaultDisplay.mTaskContainers.positionStackAtTop(stack,
+ false /* includingParents */);
} else {
- mDefaultDisplay.positionStackAtBottom(stack);
+ mDefaultDisplay.mTaskContainers.positionStackAtBottom(stack);
}
} else {
stack = new StackBuilder(mRootWindowContainer)
@@ -1090,7 +1091,7 @@
mDefaultDisplay.registerStackOrderChangedListener(listener);
try {
mStack.mReparenting = true;
- mDefaultDisplay.addStack(mStack, 0);
+ mDefaultDisplay.mTaskContainers.addStack(mStack, 0);
} finally {
mDefaultDisplay.unregisterStackOrderChangedListener(listener);
}
@@ -1105,7 +1106,7 @@
mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
true /* onTop */);
mDefaultDisplay.registerStackOrderChangedListener(listener);
- mDefaultDisplay.positionStackAtBottom(fullscreenStack1);
+ mDefaultDisplay.mTaskContainers.positionStackAtBottom(fullscreenStack1);
} finally {
mDefaultDisplay.unregisterStackOrderChangedListener(listener);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 716369d..9240b22 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -462,9 +462,11 @@
}
ActivityStack build() {
- final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId();
- final ActivityStack stack = mDisplay.createStackUnchecked(mWindowingMode,
- mActivityType, stackId, mOnTop, mInfo, mIntent, false /* createdByOrganizer */);
+ final int stackId = mStackId >= 0 ? mStackId
+ : mDisplay.mTaskContainers.getNextStackId();
+ final ActivityStack stack = mDisplay.mTaskContainers.createStackUnchecked(
+ mWindowingMode, mActivityType, stackId, mOnTop, mInfo, mIntent,
+ false /* createdByOrganizer */);
final ActivityStackSupervisor supervisor = mRootWindowContainer.mStackSupervisor;
if (mCreateActivity) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java
index 3120631..32d7a07 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java
@@ -78,7 +78,7 @@
@Override
public DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content,
DisplayArea.Root root, DisplayArea<? extends WindowContainer> imeContainer,
- DisplayContent.TaskContainers taskContainers) {
+ TaskContainers taskContainers) {
throw new RuntimeException("test stub");
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 218c816..5b96c43 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1088,7 +1088,7 @@
}
assertNull(defaultDisplay.getRootHomeTask());
- assertNotNull(defaultDisplay.getOrCreateRootHomeTask());
+ assertNotNull(defaultDisplay.mTaskContainers.getOrCreateRootHomeTask());
}
@Test
@@ -1104,7 +1104,7 @@
}
assertNull(display.getRootHomeTask());
- assertNotNull(display.getOrCreateRootHomeTask());
+ assertNotNull(display.mTaskContainers.getOrCreateRootHomeTask());
}
@Test
@@ -1113,7 +1113,7 @@
doReturn(false).when(display).supportsSystemDecorations();
assertNull(display.getRootHomeTask());
- assertNull(display.getOrCreateRootHomeTask());
+ assertNull(display.mTaskContainers.getOrCreateRootHomeTask());
}
@Test
@@ -1122,7 +1122,7 @@
doReturn(true).when(display).isUntrustedVirtualDisplay();
assertNull(display.getRootHomeTask());
- assertNull(display.getOrCreateRootHomeTask());
+ assertNull(display.mTaskContainers.getOrCreateRootHomeTask());
}
private boolean isOptionsPanelAtRight(int displayId) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 5e30477..b21ea79 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -22,6 +22,7 @@
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -29,13 +30,18 @@
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
import android.platform.test.annotations.Presubmit;
import android.util.IntArray;
@@ -164,45 +170,51 @@
@Test
public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
- addWindow(TYPE_STATUS_BAR, "statusBar")
+ addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
.getControllableInsetProvider().getSource().setVisible(false);
- addWindow(TYPE_NAVIGATION_BAR, "navBar")
+ addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(false);
- final WindowState app = addWindow(TYPE_APPLICATION, "app");
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
- doNothing().when(policy).startAnimation(anyBoolean(), any());
- policy.updateBarControlTarget(app);
+
+ doAnswer(invocation -> {
+ ((InsetsState) invocation.getArgument(2)).setSourceVisible(ITYPE_STATUS_BAR, true);
+ ((InsetsState) invocation.getArgument(2)).setSourceVisible(ITYPE_NAVIGATION_BAR, true);
+ return null;
+ }).when(policy).startAnimation(anyBoolean(), any(), any());
+
+ policy.updateBarControlTarget(mAppWindow);
policy.showTransient(
IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
final InsetsSourceControl[] controls =
- mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
// The app must get both fake controls.
assertEquals(2, controls.length);
for (int i = controls.length - 1; i >= 0; i--) {
assertNull(controls[i].getLeash());
}
+
+ assertTrue(mDisplayContent.getInsetsStateController().getRawInsetsState()
+ .getSource(ITYPE_STATUS_BAR).isVisible());
+ assertTrue(mDisplayContent.getInsetsStateController().getRawInsetsState()
+ .getSource(ITYPE_NAVIGATION_BAR).isVisible());
}
@Test
public void testShowTransientBars_statusBarCanBeTransient_appGetsStatusBarFakeControl() {
- // Adding app window before setting source visibility is to prevent the visibility from
- // being cleared by InsetsSourceProvider.updateVisibility.
- final WindowState app = addWindow(TYPE_APPLICATION, "app");
-
- addWindow(TYPE_STATUS_BAR, "statusBar")
+ addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
.getControllableInsetProvider().getSource().setVisible(false);
- addWindow(TYPE_NAVIGATION_BAR, "navBar")
+ addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(true);
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
- doNothing().when(policy).startAnimation(anyBoolean(), any());
- policy.updateBarControlTarget(app);
+ doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+ policy.updateBarControlTarget(mAppWindow);
policy.showTransient(
IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
final InsetsSourceControl[] controls =
- mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
// The app must get the fake control of the status bar, and must get the real control of the
// navigation bar.
@@ -219,19 +231,18 @@
@Test
public void testAbortTransientBars_bothCanBeAborted_appGetsBothRealControls() {
- addWindow(TYPE_STATUS_BAR, "statusBar")
+ addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
.getControllableInsetProvider().getSource().setVisible(false);
- addWindow(TYPE_NAVIGATION_BAR, "navBar")
+ addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(false);
- final WindowState app = addWindow(TYPE_APPLICATION, "app");
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
- doNothing().when(policy).startAnimation(anyBoolean(), any());
- policy.updateBarControlTarget(app);
+ doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+ policy.updateBarControlTarget(mAppWindow);
policy.showTransient(
IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
InsetsSourceControl[] controls =
- mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
// The app must get both fake controls.
assertEquals(2, controls.length);
@@ -239,12 +250,12 @@
assertNull(controls[i].getLeash());
}
- final InsetsState state = policy.getInsetsForDispatch(app);
+ final InsetsState state = policy.getInsetsForDispatch(mAppWindow);
state.setSourceVisible(ITYPE_STATUS_BAR, true);
state.setSourceVisible(ITYPE_NAVIGATION_BAR, true);
- policy.onInsetsModified(app, state);
+ policy.onInsetsModified(mAppWindow, state);
- controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+ controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
// The app must get both real controls.
assertEquals(2, controls.length);
@@ -253,6 +264,33 @@
}
}
+ @Test
+ public void testShowTransientBars_abortsWhenControlTargetChanges() {
+ addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
+ .getControllableInsetProvider().getSource().setVisible(false);
+ addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
+ .getControllableInsetProvider().getSource().setVisible(false);
+ final WindowState app = addWindow(TYPE_APPLICATION, "app");
+ final WindowState app2 = addWindow(TYPE_APPLICATION, "app");
+
+ final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
+ doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+ policy.updateBarControlTarget(app);
+ policy.showTransient(
+ IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
+ final InsetsSourceControl[] controls =
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+ policy.updateBarControlTarget(app2);
+ assertFalse(policy.isTransient(ITYPE_STATUS_BAR));
+ assertFalse(policy.isTransient(ITYPE_NAVIGATION_BAR));
+ }
+
+ private WindowState addNonFocusableWindow(int type, String name) {
+ WindowState win = addWindow(type, name);
+ win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+ return win;
+ }
+
private WindowState addWindow(int type, String name) {
final WindowState win = createWindow(null, type, name);
mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 8f3ff52..ae467c0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -120,7 +120,7 @@
.build();
mTestTask.mUserId = TEST_USER_ID;
mTestTask.mLastNonFullscreenBounds = TEST_BOUNDS;
- mTestTask.hasBeenVisible = true;
+ mTestTask.setHasBeenVisible(true);
mTaskWithDifferentComponent = new TaskBuilder(mSupervisor)
.setComponent(ALTERNATIVE_COMPONENT).build();
@@ -346,7 +346,7 @@
.build();
anotherTaskOfTheSameUser.setWindowingMode(WINDOWING_MODE_FREEFORM);
anotherTaskOfTheSameUser.setBounds(200, 300, 400, 500);
- anotherTaskOfTheSameUser.hasBeenVisible = true;
+ anotherTaskOfTheSameUser.setHasBeenVisible(true);
mTarget.saveTask(anotherTaskOfTheSameUser);
stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
@@ -358,7 +358,7 @@
.build();
anotherTaskOfDifferentUser.setWindowingMode(WINDOWING_MODE_FREEFORM);
anotherTaskOfDifferentUser.setBounds(300, 400, 500, 600);
- anotherTaskOfDifferentUser.hasBeenVisible = true;
+ anotherTaskOfDifferentUser.setHasBeenVisible(true);
mTarget.saveTask(anotherTaskOfDifferentUser);
mTarget.onCleanupUser(TEST_USER_ID);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index da3ee39..8846fb8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -1113,7 +1113,6 @@
() -> mService.moveTaskToStack(0, INVALID_STACK_ID, true));
assertSecurityException(expectCallable,
() -> mService.setTaskWindowingModeSplitScreenPrimary(0, true));
- assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0));
assertSecurityException(expectCallable,
() -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
assertSecurityException(expectCallable, () -> mService.getAllStackInfos());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index b3a25302..cfb5bc7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -119,7 +119,7 @@
final DisplayContent defaultDisplay = mRootWindowContainer.getDefaultDisplay();
final ActivityStack homeStack =
defaultDisplay.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
- defaultDisplay.positionStackAtTop(homeStack, false /* includingParents */);
+ defaultDisplay.mTaskContainers.positionStackAtTop(homeStack, false /* includingParents */);
ActivityRecord topRunningHomeActivity = homeStack.topRunningActivity();
if (topRunningHomeActivity == null) {
topRunningHomeActivity = new ActivityBuilder(mService)
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index e841e43..dc354a7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -325,7 +325,8 @@
mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
false);
- verify(display).moveHomeStackToFront(contains(reason));
+ final TaskContainers taskContainers = display.mTaskContainers;
+ verify(taskContainers).moveHomeStackToFront(contains(reason));
}
/**
@@ -352,7 +353,8 @@
mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
false);
- verify(display, never()).moveHomeStackToFront(contains(reason));
+ final TaskContainers taskContainers = display.mTaskContainers;
+ verify(taskContainers, never()).moveHomeStackToFront(contains(reason));
}
/**
@@ -367,7 +369,7 @@
ACTIVITY_TYPE_STANDARD, false /* onTop */));
final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
- display.positionStackAtBottom(targetStack);
+ display.mTaskContainers.positionStackAtBottom(targetStack);
// Assume the stack is not at the topmost position (e.g. behind always-on-top stacks) but it
// is the current top focused stack.
@@ -470,7 +472,7 @@
final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
activity.setState(ActivityState.RESUMED, "test");
- display.positionStackAtBottom(targetStack);
+ display.mTaskContainers.positionStackAtBottom(targetStack);
// Assume the stack is at the topmost position
assertFalse(targetStack.isTopStackOnDisplay());
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 091f493..8c8d3f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -316,7 +316,9 @@
// that the default display is in fullscreen mode.
display.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN);
spyOn(display);
- final ActivityStack homeStack = display.getStack(
+ final TaskContainers taskContainer = display.mTaskContainers;
+ spyOn(taskContainer);
+ final ActivityStack homeStack = taskContainer.getStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
spyOn(homeStack);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index ed635ce..4cc84a6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -96,10 +96,28 @@
return registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
}
+ Task createTask(ActivityStack stack, boolean fakeDraw) {
+ final Task task = createTaskInStack(stack, 0);
+
+ if (fakeDraw) {
+ task.setHasBeenVisible(true);
+ }
+ return task;
+ }
+
+ Task createTask(ActivityStack stack) {
+ // Fake draw notifications for most of our tests.
+ return createTask(stack, true);
+ }
+
+ ActivityStack createStack() {
+ return createTaskStackOnDisplay(mDisplayContent);
+ }
+
@Test
public void testAppearVanish() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer();
task.setTaskOrganizer(organizer);
@@ -110,9 +128,42 @@
}
@Test
+ public void testAppearWaitsForVisibility() throws RemoteException {
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack, false);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+
+ task.setTaskOrganizer(organizer);
+
+ verify(organizer, never()).onTaskAppeared(any());
+ task.setHasBeenVisible(true);
+ assertTrue(stack.getHasBeenVisible());
+
+ verify(organizer).onTaskAppeared(any());
+
+ task.removeImmediately();
+ verify(organizer).onTaskVanished(any());
+ }
+
+ @Test
+ public void testNoVanishedIfNoAppear() throws RemoteException {
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack, false /* hasBeenVisible */);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+
+ // In this test we skip making the Task visible, and verify
+ // that even though a TaskOrganizer is set remove doesn't emit
+ // a vanish callback, because we never emitted appear.
+ task.setTaskOrganizer(organizer);
+ verify(organizer, never()).onTaskAppeared(any());
+ task.removeImmediately();
+ verify(organizer, never()).onTaskVanished(any());
+ }
+
+ @Test
public void testSwapOrganizer() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
@@ -125,8 +176,8 @@
@Test
public void testSwapWindowingModes() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
@@ -139,8 +190,8 @@
@Test
public void testClearOrganizer() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer();
stack.setTaskOrganizer(organizer);
@@ -154,8 +205,8 @@
@Test
public void testUnregisterOrganizer() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer();
stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
@@ -169,12 +220,12 @@
@Test
public void testUnregisterOrganizerReturnsRegistrationToPrevious() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
- final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityStack stack3 = createTaskStackOnDisplay(mDisplayContent);
- final Task task3 = createTaskInStack(stack3, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
+ final ActivityStack stack2 = createStack();
+ final Task task2 = createTask(stack2);
+ final ActivityStack stack3 = createStack();
+ final Task task3 = createTask(stack3);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
// First organizer is registered, verify a task appears when changing windowing mode
@@ -202,9 +253,9 @@
public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException {
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
- final Task task2 = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
+ final Task task2 = createTask(stack);
stack.setWindowingMode(WINDOWING_MODE_PINNED);
verify(organizer, times(1)).onTaskAppeared(any());
@@ -214,8 +265,8 @@
@Test
public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
stack.setWindowingMode(WINDOWING_MODE_PINNED);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
@@ -560,8 +611,8 @@
@Test
public void testTrivialBLASTCallback() throws RemoteException {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
spyOn(task);
@@ -582,8 +633,8 @@
@Test
public void testOverlappingBLASTCallback() throws RemoteException {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
spyOn(task);
@@ -611,8 +662,8 @@
@Test
public void testBLASTCallbackWithWindow() {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
makeWindowVisible(w);
@@ -635,8 +686,8 @@
@Test
public void testBLASTCallbackWithInvisibleWindow() {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
@@ -657,8 +708,8 @@
@Test
public void testBLASTCallbackWithChildWindow() {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
final WindowState child = createWindow(w, TYPE_APPLICATION, "Other Window");
@@ -708,6 +759,8 @@
record.info.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
spyOn(record);
doReturn(true).when(record).checkEnterPictureInPictureState(any(), anyBoolean());
+
+ record.getRootTask().setHasBeenVisible(true);
return record;
}
@@ -755,4 +808,23 @@
assertEquals(3, ratio.getNumerator());
assertEquals(4, ratio.getDenominator());
}
+
+ @Test
+ public void testPreventDuplicateAppear() throws RemoteException {
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+
+ task.setTaskOrganizer(organizer);
+ // setHasBeenVisible was already called once by the set-up code.
+ task.setHasBeenVisible(true);
+ verify(organizer, times(1)).onTaskAppeared(any());
+
+ task.taskOrganizerUnregistered();
+ task.setTaskOrganizer(organizer);
+ verify(organizer, times(2)).onTaskAppeared(any());
+
+ task.removeImmediately();
+ verify(organizer).onTaskVanished(any());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 56c19a4..1ad4079 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -874,11 +874,11 @@
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM);
task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.onConfigurationChanged(task.getParent().getConfiguration());
verify(persister).saveTask(task, task.getDisplayContent());
@@ -890,7 +890,7 @@
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getDisplayContent().setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
final DisplayContent oldDisplay = task.getDisplayContent();
@@ -900,7 +900,7 @@
persister.getLaunchParams(task, null, params);
assertEquals(WINDOWING_MODE_UNDEFINED, params.mWindowingMode);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.removeImmediately();
verify(persister).saveTask(task, oldDisplay);
@@ -915,10 +915,10 @@
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.onConfigurationChanged(task.getParent().getConfiguration());
verify(persister, never()).saveTask(same(task), any());
@@ -930,11 +930,11 @@
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM);
task.getStack().setWindowingMode(WINDOWING_MODE_PINNED);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.onConfigurationChanged(task.getParent().getConfiguration());
verify(persister, never()).saveTask(same(task), any());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 2164de9..67d4016 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -41,6 +41,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.view.InsetsState;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -87,7 +88,7 @@
0 /* systemUiVisibility */, false /* isTranslucent */);
mSurface = new TaskSnapshotSurface(mWm, new Window(), new SurfaceControl(), snapshot, "Test",
createTaskDescription(Color.WHITE, Color.RED, Color.BLUE), sysuiVis, windowFlags, 0,
- taskBounds, ORIENTATION_PORTRAIT, null /* insetsState */);
+ taskBounds, ORIENTATION_PORTRAIT, new InsetsState());
}
private static TaskDescription createTaskDescription(int background, int statusBar,
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index fc8cc96..18737c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -43,6 +43,7 @@
// hard-code to FULLSCREEN for tests.
setWindowingMode(WINDOWING_MODE_FULLSCREEN);
spyOn(this);
+ spyOn(mTaskContainers);
final DisplayRotation displayRotation = getDisplayRotation();
spyOn(displayRotation);
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java
index 9906585..71da8dd 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java
@@ -86,10 +86,11 @@
synchronized(this) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
- values.put(GenericSoundModelContract.KEY_MODEL_UUID, soundModel.uuid.toString());
- values.put(GenericSoundModelContract.KEY_VENDOR_UUID, soundModel.vendorUuid.toString());
- values.put(GenericSoundModelContract.KEY_DATA, soundModel.data);
- values.put(GenericSoundModelContract.KEY_MODEL_VERSION, soundModel.version);
+ values.put(GenericSoundModelContract.KEY_MODEL_UUID, soundModel.getUuid().toString());
+ values.put(GenericSoundModelContract.KEY_VENDOR_UUID,
+ soundModel.getVendorUuid().toString());
+ values.put(GenericSoundModelContract.KEY_DATA, soundModel.getData());
+ values.put(GenericSoundModelContract.KEY_MODEL_VERSION, soundModel.getVersion());
try {
return db.insertWithOnConflict(GenericSoundModelContract.TABLE, null, values,
@@ -140,7 +141,7 @@
// Delete all sound models for the given keyphrase and specified user.
SQLiteDatabase db = getWritableDatabase();
String soundModelClause = GenericSoundModelContract.KEY_MODEL_UUID
- + "='" + soundModel.uuid.toString() + "'";
+ + "='" + soundModel.getUuid().toString() + "'";
try {
return db.delete(GenericSoundModelContract.TABLE, soundModelClause, null) != 0;
} finally {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 7099c09..6c0f2b0 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -195,7 +195,7 @@
}
// Process existing model first.
- if (model != null && !model.getModelId().equals(soundModel.uuid)) {
+ if (model != null && !model.getModelId().equals(soundModel.getUuid())) {
// The existing model has a different UUID, should be replaced.
int status = cleanUpExistingKeyphraseModelLocked(model);
if (status != STATUS_OK) {
@@ -208,7 +208,7 @@
// We need to create a new one: either no previous models existed for given keyphrase id
// or the existing model had a different UUID and was cleaned up.
if (model == null) {
- model = createKeyphraseModelDataLocked(soundModel.uuid, keyphraseId);
+ model = createKeyphraseModelDataLocked(soundModel.getUuid(), keyphraseId);
}
return startRecognition(soundModel, model, callback, recognitionConfig,
@@ -249,7 +249,7 @@
return STATUS_ERROR;
}
if (mModule == null) {
- mModule = SoundTrigger.attachModule(mModuleProperties.id, this, null);
+ mModule = SoundTrigger.attachModule(mModuleProperties.getId(), this, null);
if (mModule == null) {
Slog.w(TAG, "startRecognition cannot attach to sound trigger module");
return STATUS_ERROR;
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 00cb6dc..170bee8 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -358,7 +358,7 @@
public int loadGenericSoundModel(GenericSoundModel soundModel) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
if (!isInitialized()) return STATUS_ERROR;
- if (soundModel == null || soundModel.uuid == null) {
+ if (soundModel == null || soundModel.getUuid() == null) {
Slog.e(TAG, "Invalid sound model");
sEventLogger.log(new SoundTriggerLogger.StringEvent(
@@ -367,24 +367,24 @@
return STATUS_ERROR;
}
if (DEBUG) {
- Slog.i(TAG, "loadGenericSoundModel(): id = " + soundModel.uuid);
+ Slog.i(TAG, "loadGenericSoundModel(): id = " + soundModel.getUuid());
}
sEventLogger.log(new SoundTriggerLogger.StringEvent("loadGenericSoundModel(): id = "
- + soundModel.uuid));
+ + soundModel.getUuid()));
synchronized (mLock) {
- SoundModel oldModel = mLoadedModels.get(soundModel.uuid);
+ SoundModel oldModel = mLoadedModels.get(soundModel.getUuid());
// If the model we're loading is actually different than what we had loaded, we
// should unload that other model now. We don't care about return codes since we
// don't know if the other model is loaded.
if (oldModel != null && !oldModel.equals(soundModel)) {
- mSoundTriggerHelper.unloadGenericSoundModel(soundModel.uuid);
+ mSoundTriggerHelper.unloadGenericSoundModel(soundModel.getUuid());
synchronized (mCallbacksLock) {
- mCallbacks.remove(soundModel.uuid);
+ mCallbacks.remove(soundModel.getUuid());
}
}
- mLoadedModels.put(soundModel.uuid, soundModel);
+ mLoadedModels.put(soundModel.getUuid(), soundModel);
}
return STATUS_OK;
}
@@ -393,7 +393,7 @@
public int loadKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
if (!isInitialized()) return STATUS_ERROR;
- if (soundModel == null || soundModel.uuid == null) {
+ if (soundModel == null || soundModel.getUuid() == null) {
Slog.e(TAG, "Invalid sound model");
sEventLogger.log(new SoundTriggerLogger.StringEvent(
@@ -401,7 +401,7 @@
return STATUS_ERROR;
}
- if (soundModel.keyphrases == null || soundModel.keyphrases.length != 1) {
+ if (soundModel.getKeyphrases() == null || soundModel.getKeyphrases().length != 1) {
Slog.e(TAG, "Only one keyphrase per model is currently supported.");
sEventLogger.log(new SoundTriggerLogger.StringEvent(
@@ -411,24 +411,25 @@
return STATUS_ERROR;
}
if (DEBUG) {
- Slog.i(TAG, "loadKeyphraseSoundModel(): id = " + soundModel.uuid);
+ Slog.i(TAG, "loadKeyphraseSoundModel(): id = " + soundModel.getUuid());
}
sEventLogger.log(new SoundTriggerLogger.StringEvent("loadKeyphraseSoundModel(): id = "
- + soundModel.uuid));
+ + soundModel.getUuid()));
synchronized (mLock) {
- SoundModel oldModel = mLoadedModels.get(soundModel.uuid);
+ SoundModel oldModel = mLoadedModels.get(soundModel.getUuid());
// If the model we're loading is actually different than what we had loaded, we
// should unload that other model now. We don't care about return codes since we
// don't know if the other model is loaded.
if (oldModel != null && !oldModel.equals(soundModel)) {
- mSoundTriggerHelper.unloadKeyphraseSoundModel(soundModel.keyphrases[0].id);
+ mSoundTriggerHelper.unloadKeyphraseSoundModel(
+ soundModel.getKeyphrases()[0].getId());
synchronized (mCallbacksLock) {
- mCallbacks.remove(soundModel.uuid);
+ mCallbacks.remove(soundModel.getUuid());
}
}
- mLoadedModels.put(soundModel.uuid, soundModel);
+ mLoadedModels.put(soundModel.getUuid(), soundModel);
}
return STATUS_OK;
}
@@ -478,9 +479,9 @@
return STATUS_ERROR;
}
int ret;
- switch (soundModel.type) {
+ switch (soundModel.getType()) {
case SoundModel.TYPE_GENERIC_SOUND:
- ret = mSoundTriggerHelper.startGenericRecognition(soundModel.uuid,
+ ret = mSoundTriggerHelper.startGenericRecognition(soundModel.getUuid(),
(GenericSoundModel) soundModel, callback, config);
break;
default:
@@ -545,9 +546,10 @@
return STATUS_ERROR;
}
int ret;
- switch (soundModel.type) {
+ switch (soundModel.getType()) {
case SoundModel.TYPE_GENERIC_SOUND:
- ret = mSoundTriggerHelper.stopGenericRecognition(soundModel.uuid, callback);
+ ret = mSoundTriggerHelper.stopGenericRecognition(
+ soundModel.getUuid(), callback);
break;
default:
Slog.e(TAG, "Unknown model type");
@@ -597,13 +599,13 @@
return STATUS_ERROR;
}
int ret;
- switch (soundModel.type) {
+ switch (soundModel.getType()) {
case SoundModel.TYPE_KEYPHRASE:
ret = mSoundTriggerHelper.unloadKeyphraseSoundModel(
- ((KeyphraseSoundModel)soundModel).keyphrases[0].id);
+ ((KeyphraseSoundModel) soundModel).getKeyphrases()[0].getId());
break;
case SoundModel.TYPE_GENERIC_SOUND:
- ret = mSoundTriggerHelper.unloadGenericSoundModel(soundModel.uuid);
+ ret = mSoundTriggerHelper.unloadGenericSoundModel(soundModel.getUuid());
break;
default:
Slog.e(TAG, "Unknown model type");
@@ -661,16 +663,16 @@
return ret;
}
- switch (soundModel.type) {
+ switch (soundModel.getType()) {
case SoundModel.TYPE_GENERIC_SOUND:
- ret = mSoundTriggerHelper.getGenericModelState(soundModel.uuid);
+ ret = mSoundTriggerHelper.getGenericModelState(soundModel.getUuid());
break;
default:
// SoundModel.TYPE_KEYPHRASE is not supported to increase privacy.
- Slog.e(TAG, "Unsupported model type, " + soundModel.type);
+ Slog.e(TAG, "Unsupported model type, " + soundModel.getType());
sEventLogger.log(new SoundTriggerLogger.StringEvent(
"getModelState(): Unsupported model type, "
- + soundModel.type));
+ + soundModel.getType()));
break;
}
@@ -723,7 +725,7 @@
return STATUS_BAD_VALUE;
}
- return mSoundTriggerHelper.setParameter(soundModel.uuid, modelParam, value);
+ return mSoundTriggerHelper.setParameter(soundModel.getUuid(), modelParam, value);
}
}
@@ -755,7 +757,7 @@
throw new IllegalArgumentException("sound model is not loaded");
}
- return mSoundTriggerHelper.getParameter(soundModel.uuid, modelParam);
+ return mSoundTriggerHelper.getParameter(soundModel.getUuid(), modelParam);
}
}
@@ -786,7 +788,7 @@
return null;
}
- return mSoundTriggerHelper.queryParameter(soundModel.uuid, modelParam);
+ return mSoundTriggerHelper.queryParameter(soundModel.getUuid(), modelParam);
}
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
index be0987d..aaf7a9e 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -162,23 +162,26 @@
synchronized(this) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
- values.put(SoundModelContract.KEY_MODEL_UUID, soundModel.uuid.toString());
- if (soundModel.vendorUuid != null) {
- values.put(SoundModelContract.KEY_VENDOR_UUID, soundModel.vendorUuid.toString());
+ values.put(SoundModelContract.KEY_MODEL_UUID, soundModel.getUuid().toString());
+ if (soundModel.getVendorUuid() != null) {
+ values.put(SoundModelContract.KEY_VENDOR_UUID,
+ soundModel.getVendorUuid().toString());
}
values.put(SoundModelContract.KEY_TYPE, SoundTrigger.SoundModel.TYPE_KEYPHRASE);
- values.put(SoundModelContract.KEY_DATA, soundModel.data);
- values.put(SoundModelContract.KEY_MODEL_VERSION, soundModel.version);
+ values.put(SoundModelContract.KEY_DATA, soundModel.getData());
+ values.put(SoundModelContract.KEY_MODEL_VERSION, soundModel.getVersion());
- if (soundModel.keyphrases != null && soundModel.keyphrases.length == 1) {
- values.put(SoundModelContract.KEY_KEYPHRASE_ID, soundModel.keyphrases[0].id);
+ if (soundModel.getKeyphrases() != null && soundModel.getKeyphrases().length == 1) {
+ values.put(SoundModelContract.KEY_KEYPHRASE_ID,
+ soundModel.getKeyphrases()[0].getId());
values.put(SoundModelContract.KEY_RECOGNITION_MODES,
- soundModel.keyphrases[0].recognitionModes);
+ soundModel.getKeyphrases()[0].getRecognitionModes());
values.put(SoundModelContract.KEY_USERS,
- getCommaSeparatedString(soundModel.keyphrases[0].users));
+ getCommaSeparatedString(soundModel.getKeyphrases()[0].getUsers()));
values.put(SoundModelContract.KEY_LOCALE,
- soundModel.keyphrases[0].locale.toLanguageTag());
- values.put(SoundModelContract.KEY_HINT_TEXT, soundModel.keyphrases[0].text);
+ soundModel.getKeyphrases()[0].getLocale().toLanguageTag());
+ values.put(SoundModelContract.KEY_HINT_TEXT,
+ soundModel.getKeyphrases()[0].getText());
try {
return db.insertWithOnConflict(SoundModelContract.TABLE, null, values,
SQLiteDatabase.CONFLICT_REPLACE) != -1;
@@ -206,7 +209,7 @@
// Delete all sound models for the given keyphrase and specified user.
SQLiteDatabase db = getWritableDatabase();
String soundModelClause = SoundModelContract.KEY_MODEL_UUID
- + "='" + soundModel.uuid.toString() + "'";
+ + "='" + soundModel.getUuid().toString() + "'";
try {
return db.delete(SoundModelContract.TABLE, soundModelClause, null) != 0;
} finally {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 18d5819..ef282ba 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1045,12 +1045,12 @@
return null;
}
- for (SoundTrigger.Keyphrase phrase : model.keyphrases) {
- if (keyphrase.equals(phrase.text)) {
+ for (SoundTrigger.Keyphrase phrase : model.getKeyphrases()) {
+ if (keyphrase.equals(phrase.getText())) {
ArraySet<Locale> locales = new ArraySet<>();
- locales.add(phrase.locale);
- return new KeyphraseMetadata(phrase.id, phrase.text, locales,
- phrase.recognitionModes);
+ locales.add(phrase.getLocale());
+ return new KeyphraseMetadata(phrase.getId(), phrase.getText(), locales,
+ phrase.getRecognitionModes());
}
}
} finally {
@@ -1093,8 +1093,8 @@
KeyphraseSoundModel soundModel =
mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
if (soundModel == null
- || soundModel.uuid == null
- || soundModel.keyphrases == null) {
+ || soundModel.getUuid() == null
+ || soundModel.getKeyphrases() == null) {
Slog.w(TAG, "No matching sound model found in startRecognition");
return SoundTriggerInternal.STATUS_ERROR;
} else {
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
index badff7b..d5851d8 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
@@ -279,6 +279,8 @@
(IIorap remote) -> remote.setTaskListener(new RemoteTaskListener()) );
registerInProcessListenersLocked();
+ Log.i(TAG, "Connected to iorapd native service.");
+
return true;
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index e3baa0a..c993cfa 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -193,13 +193,13 @@
/**
* Broadcast intent action indicating that the current default call screening app has changed.
- *
- * The string extra {@link #EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME} will contain the
- * name of the Component of the previous or the new call screening app.
- *
- * The boolean extra {@link #EXTRA_IS_DEFAULT_CALL_SCREENING_APP} will indicate the component
- * name in the String extra {@link #EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME} is default
- * call screening app or not.
+ * <p>
+ * Note: This intent is NEVER actually broadcast and will be deprecated in the future.
+ * <p>
+ * An app that want to know if it holds the
+ * {@link android.app.role.RoleManager#ROLE_CALL_SCREENING} role can use
+ * {@link android.app.role.RoleManager#isRoleHeld(String)} to confirm if it holds the role or
+ * not.
*/
public static final String ACTION_DEFAULT_CALL_SCREENING_APP_CHANGED =
"android.telecom.action.DEFAULT_CALL_SCREENING_APP_CHANGED";
@@ -207,6 +207,8 @@
/**
* Extra value used with {@link #ACTION_DEFAULT_CALL_SCREENING_APP_CHANGED} broadcast to
* indicate the ComponentName of the call screening app which has changed.
+ * <p>
+ * Note: This extra is NOT used and will be deprecated in the future.
*/
public static final String EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME =
"android.telecom.extra.DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME";
@@ -214,6 +216,8 @@
/**
* Extra value used with {@link #ACTION_DEFAULT_CALL_SCREENING_APP_CHANGED} broadcast to
* indicate whether an app is the default call screening app.
+ * <p>
+ * Note: This extra is NOT used and will be deprecated in the future.
*/
public static final String EXTRA_IS_DEFAULT_CALL_SCREENING_APP =
"android.telecom.extra.IS_DEFAULT_CALL_SCREENING_APP";
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index afb75bb..6273b48 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -816,9 +816,9 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPin(String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 7e02966..1a38a42 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -361,7 +361,8 @@
TelephonyCommonStatsLog.write(TelephonyCommonStatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED,
callingPackage, message, /* isPreinstalled= */ false, false);
}
- Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message);
+ Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message + ":"
+ + subId);
// if the target SDK is pre-Q then check if the calling package would have previously
// had access to device identifiers.
if (callingPackageInfo != null && (
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 0c2f1f3..390a79a 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -68,6 +68,12 @@
/** @hide */
protected String mAlphaShort;
+ // For GSM, WCDMA, TDSCDMA, LTE and NR, Cell Global ID is defined in 3GPP TS 23.003.
+ // For CDMA, its defined as System Id + Network Id + Basestation Id.
+ /** @hide */
+ protected String mGlobalCellId;
+
+
/** @hide */
protected CellIdentity(@Nullable String tag, int type, @Nullable String mcc,
@Nullable String mnc, @Nullable String alphal, @Nullable String alphas) {
@@ -182,6 +188,36 @@
}
/**
+ * @return Global Cell ID
+ * @hide
+ */
+ @Nullable
+ public String getGlobalCellId() {
+ return mGlobalCellId;
+ }
+
+ /**
+ * @param ci a CellIdentity to compare to the current CellIdentity.
+ * @return true if ci has the same technology and Global Cell ID; false, otherwise.
+ * @hide
+ */
+ public boolean isSameCell(@Nullable CellIdentity ci) {
+ if (ci == null) return false;
+ if (this.getClass() != ci.getClass()) return false;
+ if (this.getGlobalCellId() == null || ci.getGlobalCellId() == null) return false;
+ return TextUtils.equals(this.getGlobalCellId(), ci.getGlobalCellId());
+ }
+
+ /** @hide */
+ protected String getPlmn() {
+ if (mMccStr == null || mMncStr == null) return null;
+ return mMccStr + mMncStr;
+ }
+
+ /** @hide */
+ protected abstract void updateGlobalCellId();
+
+ /**
* @return a CellLocation object for this CellIdentity
* @hide
*/
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index e220b07..f21277c 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -75,6 +75,7 @@
mBasestationId = CellInfo.UNAVAILABLE;
mLongitude = CellInfo.UNAVAILABLE;
mLatitude = CellInfo.UNAVAILABLE;
+ mGlobalCellId = null;
}
/**
@@ -106,6 +107,7 @@
} else {
mLongitude = mLatitude = CellInfo.UNAVAILABLE;
}
+ updateGlobalCellId();
}
/** @hide */
@@ -136,6 +138,16 @@
mAlphaLong, mAlphaShort);
}
+ /** @hide */
+ @Override
+ protected void updateGlobalCellId() {
+ mGlobalCellId = null;
+ if (mNetworkId == CellInfo.UNAVAILABLE || mSystemId == CellInfo.UNAVAILABLE
+ || mBasestationId == CellInfo.UNAVAILABLE) return;
+
+ mGlobalCellId = String.format("%04x%04x%04x", mSystemId, mNetworkId, mBasestationId);
+ }
+
/**
* Take the latitude and longitude in 1/4 seconds and see if
* the reported location is on Null Island.
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 203047f..1a91310 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -64,6 +64,7 @@
mArfcn = CellInfo.UNAVAILABLE;
mBsic = CellInfo.UNAVAILABLE;
mAdditionalPlmns = new ArraySet<>();
+ mGlobalCellId = null;
}
/**
@@ -94,6 +95,7 @@
mAdditionalPlmns.add(plmn);
}
}
+ updateGlobalCellId();
}
/** @hide */
@@ -136,6 +138,18 @@
CellInfo.UNAVAILABLE, mMccStr, mMncStr, mAlphaLong, mAlphaShort, mAdditionalPlmns);
}
+ /** @hide */
+ @Override
+ protected void updateGlobalCellId() {
+ mGlobalCellId = null;
+ String plmn = getPlmn();
+ if (plmn == null) return;
+
+ if (mLac == CellInfo.UNAVAILABLE || mCid == CellInfo.UNAVAILABLE) return;
+
+ mGlobalCellId = plmn + String.format("%04x%04x", mLac, mCid);
+ }
+
/**
* @return 3-digit Mobile Country Code, 0..999,
* {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index b4ce162..c37735c 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -76,6 +76,7 @@
mBandwidth = CellInfo.UNAVAILABLE;
mAdditionalPlmns = new ArraySet<>();
mCsgInfo = null;
+ mGlobalCellId = null;
}
/**
@@ -130,6 +131,7 @@
}
}
mCsgInfo = csgInfo;
+ updateGlobalCellId();
}
/** @hide */
@@ -172,6 +174,18 @@
return new CellIdentityLte(this);
}
+ /** @hide */
+ @Override
+ protected void updateGlobalCellId() {
+ mGlobalCellId = null;
+ String plmn = getPlmn();
+ if (plmn == null) return;
+
+ if (mCi == CellInfo.UNAVAILABLE) return;
+
+ mGlobalCellId = plmn + String.format("%07x", mCi);
+ }
+
/**
* @return 3-digit Mobile Country Code, 0..999,
* {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index 69cf7e7d..f0d8780 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -82,6 +82,7 @@
mAdditionalPlmns.add(plmn);
}
}
+ updateGlobalCellId();
}
/** @hide */
@@ -107,6 +108,17 @@
mAdditionalPlmns);
}
+ /** @hide */
+ protected void updateGlobalCellId() {
+ mGlobalCellId = null;
+ String plmn = getPlmn();
+ if (plmn == null) return;
+
+ if (mNci == CellInfo.UNAVAILABLE_LONG) return;
+
+ mGlobalCellId = plmn + String.format("%09x", mNci);
+ }
+
/**
* @return a CellLocation object for this CellIdentity.
* @hide
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 30f98bc..3f95596 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -66,6 +66,7 @@
mUarfcn = CellInfo.UNAVAILABLE;
mAdditionalPlmns = new ArraySet<>();
mCsgInfo = null;
+ mGlobalCellId = null;
}
/**
@@ -100,6 +101,7 @@
}
}
mCsgInfo = csgInfo;
+ updateGlobalCellId();
}
private CellIdentityTdscdma(@NonNull CellIdentityTdscdma cid) {
@@ -142,6 +144,18 @@
return new CellIdentityTdscdma(this);
}
+ /** @hide */
+ @Override
+ protected void updateGlobalCellId() {
+ mGlobalCellId = null;
+ String plmn = getPlmn();
+ if (plmn == null) return;
+
+ if (mLac == CellInfo.UNAVAILABLE || mCid == CellInfo.UNAVAILABLE) return;
+
+ mGlobalCellId = plmn + String.format("%04x%04x", mLac, mCid);
+ }
+
/**
* Get Mobile Country Code in string format
* @return Mobile Country Code in string format, null if unknown
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 9d2cb74..38c4ed4 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -68,6 +68,7 @@
mUarfcn = CellInfo.UNAVAILABLE;
mAdditionalPlmns = new ArraySet<>();
mCsgInfo = null;
+ mGlobalCellId = null;
}
/**
@@ -101,6 +102,7 @@
}
}
mCsgInfo = csgInfo;
+ updateGlobalCellId();
}
/** @hide */
@@ -142,6 +144,18 @@
return new CellIdentityWcdma(this);
}
+ /** @hide */
+ @Override
+ protected void updateGlobalCellId() {
+ mGlobalCellId = null;
+ String plmn = getPlmn();
+ if (plmn == null) return;
+
+ if (mLac == CellInfo.UNAVAILABLE || mCid == CellInfo.UNAVAILABLE) return;
+
+ mGlobalCellId = plmn + String.format("%04x%04x", mLac, mCid);
+ }
+
/**
* @return 3-digit Mobile Country Code, 0..999,
* {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 283e666..2bb4eb1 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -188,12 +188,12 @@
private CellSignalStrength getPrimary() {
// This behavior is intended to replicate the legacy behavior of getLevel() by prioritizing
// newer faster RATs for default/for display purposes.
+ if (mNr.isValid()) return mNr;
if (mLte.isValid()) return mLte;
if (mCdma.isValid()) return mCdma;
if (mTdscdma.isValid()) return mTdscdma;
if (mWcdma.isValid()) return mWcdma;
if (mGsm.isValid()) return mGsm;
- if (mNr.isValid()) return mNr;
return mLte;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5a7b852..4e5be5c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5577,6 +5577,10 @@
* call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
* {@link SecurityException} will be thrown otherwise.
*
+ * This API should be used sparingly -- large numbers of listeners will cause system
+ * instability. If a process has registered too many listeners without unregistering them, it
+ * may encounter an {@link IllegalStateException} when trying to register more listeners.
+ *
* @param listener The {@link PhoneStateListener} object to register
* (or unregister)
* @param events The telephony state(s) of interest to the listener,
@@ -8679,13 +8683,9 @@
return false;
}
- /**
- * @deprecated use {@link #supplyPinReportPinResult(String pin)} instead.
- *
- * @hide */
+ /** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- @Deprecated
public int[] supplyPinReportResult(String pin) {
try {
ITelephony telephony = getITelephony();
@@ -8697,13 +8697,9 @@
return new int[0];
}
- /**
- * @deprecated use {@link #supplyPukReportPinResult(String puk, String pin)} instead.
- *
- * @hide */
+ /** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- @Deprecated
public int[] supplyPukReportResult(String puk, String pin) {
try {
ITelephony telephony = getITelephony();
@@ -12268,6 +12264,17 @@
"android.telephony.extra.NETWORK_COUNTRY";
/**
+ * The extra used with an {@link #ACTION_NETWORK_COUNTRY_CHANGED} to specify the
+ * last known the country code in ISO-3166-1 alpha-2 format.
+ * <p class="note">
+ * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
+ *
+ * @hide
+ */
+ public static final String EXTRA_LAST_KNOWN_NETWORK_COUNTRY =
+ "android.telephony.extra.LAST_KNOWN_NETWORK_COUNTRY";
+
+ /**
* Indicate if the user is allowed to use multiple SIM cards at the same time to register
* on the network (e.g. Dual Standby or Dual Active) when the device supports it, or if the
* usage is restricted. This API is used to prevent usage of multiple SIM card, based on
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 3e1d72c..2b1d9e5 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -74,7 +74,6 @@
public static final int BASE = Protocol.BASE_DATA_CONNECTION_TRACKER;
public static final int EVENT_DATA_SETUP_COMPLETE = BASE + 0;
public static final int EVENT_RADIO_AVAILABLE = BASE + 1;
- public static final int EVENT_RECORDS_LOADED = BASE + 2;
public static final int EVENT_TRY_SETUP_DATA = BASE + 3;
public static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = BASE + 6;
public static final int EVENT_VOICE_CALL_STARTED = BASE + 7;
@@ -94,7 +93,6 @@
public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24;
public static final int EVENT_RESTART_RADIO = BASE + 26;
public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 29;
- public static final int EVENT_ICC_CHANGED = BASE + 33;
public static final int EVENT_DATA_SETUP_COMPLETE_ERROR = BASE + 35;
public static final int CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA = BASE + 36;
public static final int CMD_ENABLE_MOBILE_PROVISIONING = BASE + 37;
@@ -114,7 +112,7 @@
public static final int EVENT_SERVICE_STATE_CHANGED = BASE + 52;
public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53;
public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54;
- public static final int EVENT_UPDATE_CARRIER_CONFIGS = BASE + 55;
+ public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 55;
/***** Constants *****/
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index 784ee85..cf3b03c 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -928,4 +928,10 @@
public Handler getMainThreadHandler() {
throw new UnsupportedOperationException();
}
+
+ /** {@hide} */
+ @Override
+ public boolean isUiContext() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tests/ApkVerityTest/block_device_writer/Android.bp b/tests/ApkVerityTest/block_device_writer/Android.bp
index 65cb364..2760fe8 100644
--- a/tests/ApkVerityTest/block_device_writer/Android.bp
+++ b/tests/ApkVerityTest/block_device_writer/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
// This is a cc_test just because it supports test_suites. This should be converted to something
-// like cc_binary_test_helper once supported.
+// like cc_binary_test_helper once supported, thus auto_gen_config:false below.
cc_test {
// Depending on how the test runs, the executable may be uploaded to different location.
// Before the bug in the file pusher is fixed, workaround by making the name unique.
@@ -47,6 +47,7 @@
},
},
+ auto_gen_config: false,
test_suites: ["general-tests", "pts", "vts-core"],
gtest: false,
}
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 0ad3039..42cee7cc 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -41,10 +41,14 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
+import java.time.format.DateTimeFormatter;
+import java.time.ZonedDateTime;
+import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -738,6 +742,41 @@
return total.contains("root");
}
+ private void stopIorapd() {
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("stop iorapd");
+ sleep(100); // give it extra time to fully stop.
+ }
+
+ private void startIorapd() {
+ String logcatTimeNow = getTimeNowForLogcat();
+ Log.v(TAG, "startIorapd, logcat time: " + logcatTimeNow);
+
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("start iorapd");
+
+ int maxAttempts = 100;
+ int attempt = 0;
+ do {
+ // Ensure that IorapForwardingService fully reconnects to iorapd before proceeding.
+ String needle = "Connected to iorapd native service";
+ String logcatLines = getLogcatSinceTime(logcatTimeNow);
+
+ if (logcatLines.contains(needle)) {
+ break;
+ }
+
+ sleep(1000);
+ attempt++;
+ } while (attempt < maxAttempts);
+
+ if (attempt == maxAttempts) {
+ Log.e(TAG, "Timed out after waiting for iorapd to start");
+ }
+ // Wait a little bit longer for iorapd to settle.
+ sleep(1000);
+ }
+
// Delete all db rows and files associated with a package in iorapd.
// Effectively deletes any raw or compiled trace files, unoptimizing the package in iorap.
private void purgeIorapPackage(String packageName) {
@@ -749,15 +788,65 @@
throw new AssertionError(e);
}
- getInstrumentation().getUiAutomation()
- .executeShellCommand("stop iorapd");
- sleep(100); // give iorapd enough time to stop.
+ Log.v(TAG, "Purge iorap package: " + packageName);
+ stopIorapd();
getInstrumentation().getUiAutomation()
.executeShellCommand(String.format(IORAP_MAINTENANCE_CMD, packageName));
Log.v(TAG, "Executed: " + String.format(IORAP_MAINTENANCE_CMD, packageName));
- getInstrumentation().getUiAutomation()
- .executeShellCommand("start iorapd");
- sleep(2000); // give iorapd enough time to start up.
+ startIorapd();
+ }
+
+ String executeShellCommandWithTempFile(String cmd) {
+ Log.v(TAG, "executeShellCommandWithTempFile, cmd: " + cmd);
+ try {
+ //File outputDir =
+ // InstrumentationRegistry.getInstrumentation().getContext().getCacheDir();
+ File outputFile = File.createTempFile("exec_shell_command", ".sh");
+
+ try {
+ outputFile.setWritable(true);
+ outputFile.setExecutable(true, /*ownersOnly*/false);
+
+ String scriptPath = outputFile.toString();
+
+ // If this works correctly, the next log-line will print 'Success'.
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(scriptPath))) {
+ writer.write(cmd);
+ }
+
+ String resultString = "";
+ try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
+ executeShellCommand(scriptPath);
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(result.getFileDescriptor())))) {
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ resultString += line + "\n";
+ }
+ }
+
+ return resultString;
+ } finally {
+ outputFile.delete();
+ }
+ } catch (IOException e) {
+ throw new AssertionError("Failed to execute shell command: " + cmd, e);
+ }
+ }
+
+ // Get the 'now' timestamp usable with $(adb logcat -v utc -T "time string")
+ String getTimeNowForLogcat() {
+ ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
+
+ // YYYY-MM-DD hh:mm:ss.mmm
+ return utc.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
+ }
+
+ String getLogcatSinceTime(String logcatTime) {
+ // The time has spaces in it but must be passed as a single arg.
+ // Therefore use a temp script file.
+ return executeShellCommandWithTempFile(
+ String.format("logcat -d -v threadtime -v utc -T '%s'", logcatTime));
}
/**
@@ -784,15 +873,12 @@
throw new AssertionError(e);
}
- getInstrumentation().getUiAutomation()
- .executeShellCommand("stop iorapd");
+ stopIorapd();
getInstrumentation().getUiAutomation()
.executeShellCommand(String.format("setprop iorapd.perfetto.enable %b", enable));
getInstrumentation().getUiAutomation()
.executeShellCommand(String.format("setprop iorapd.readahead.enable %b", enable));
- getInstrumentation().getUiAutomation()
- .executeShellCommand("start iorapd");
- sleep(3000); // give enough time for iorapd to start back up.
+ startIorapd();
if (enable) {
mIorapStatus = IorapStatus.ENABLED;
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 2957192..d011dbb 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -1123,6 +1123,28 @@
assertThat(testController.getSyncRequests()).isEqualTo(expectedSyncRequests);
}
+ /**
+ * Ensure that the failure history of a package is preserved when making duplicate calls to
+ * observe the package.
+ */
+ @Test
+ public void testFailureHistoryIsPreserved() {
+ PackageWatchdog watchdog = createWatchdog();
+ TestObserver observer = new TestObserver(OBSERVER_NAME_1);
+ watchdog.startObservingHealth(observer, List.of(APP_A), SHORT_DURATION);
+ for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) {
+ watchdog.onPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
+ }
+ mTestLooper.dispatchAll();
+ assertThat(observer.mMitigatedPackages).isEmpty();
+ watchdog.startObservingHealth(observer, List.of(APP_A), LONG_DURATION);
+ watchdog.onPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
+ mTestLooper.dispatchAll();
+ assertThat(observer.mMitigatedPackages).isEqualTo(List.of(APP_A));
+ }
+
private void adoptShellPermissions(String... permissions) {
InstrumentationRegistry
.getInstrumentation()
diff --git a/tests/RollbackTest/lib/src/com/android/tests/rollback/host/WatchdogEventLogger.java b/tests/RollbackTest/lib/src/com/android/tests/rollback/host/WatchdogEventLogger.java
index 317d67e..8873150 100644
--- a/tests/RollbackTest/lib/src/com/android/tests/rollback/host/WatchdogEventLogger.java
+++ b/tests/RollbackTest/lib/src/com/android/tests/rollback/host/WatchdogEventLogger.java
@@ -36,8 +36,10 @@
}
public void stop() {
- mReceiver.stop();
- mReceiver.clear();
+ if (mReceiver != null) {
+ mReceiver.stop();
+ mReceiver.clear();
+ }
}
/**
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
index b185a26..9324ba0 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
@@ -250,10 +250,12 @@
boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(soundModel);
if (status) {
- postToast("Successfully loaded " + modelInfo.name + ", UUID=" + soundModel.uuid);
+ postToast("Successfully loaded " + modelInfo.name + ", UUID="
+ + soundModel.getUuid());
setModelState(modelInfo, "Loaded");
} else {
- postErrorToast("Failed to load " + modelInfo.name + ", UUID=" + soundModel.uuid + "!");
+ postErrorToast("Failed to load " + modelInfo.name + ", UUID="
+ + soundModel.getUuid() + "!");
setModelState(modelInfo, "Failed to load");
}
}
@@ -275,11 +277,12 @@
modelInfo.detector = null;
boolean status = mSoundTriggerUtil.deleteSoundModel(modelUuid);
if (status) {
- postToast("Successfully unloaded " + modelInfo.name + ", UUID=" + soundModel.uuid);
+ postToast("Successfully unloaded " + modelInfo.name + ", UUID="
+ + soundModel.getUuid());
setModelState(modelInfo, "Unloaded");
} else {
postErrorToast("Failed to unload " +
- modelInfo.name + ", UUID=" + soundModel.uuid + "!");
+ modelInfo.name + ", UUID=" + soundModel.getUuid() + "!");
setModelState(modelInfo, "Failed to unload");
}
}
@@ -299,7 +302,8 @@
GenericSoundModel updated = createNewSoundModel(modelInfo);
boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(updated);
if (status) {
- postToast("Successfully reloaded " + modelInfo.name + ", UUID=" + modelInfo.modelUuid);
+ postToast("Successfully reloaded " + modelInfo.name + ", UUID="
+ + modelInfo.modelUuid);
setModelState(modelInfo, "Reloaded");
} else {
postErrorToast("Failed to reload "
@@ -321,7 +325,8 @@
modelUuid, new DetectorCallback(modelInfo));
}
- postMessage("Starting recognition for " + modelInfo.name + ", UUID=" + modelInfo.modelUuid);
+ postMessage("Starting recognition for " + modelInfo.name + ", UUID="
+ + modelInfo.modelUuid);
if (modelInfo.detector.startRecognition(modelInfo.captureAudio ?
SoundTriggerDetector.RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO :
SoundTriggerDetector.RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS)) {
@@ -495,7 +500,8 @@
if (properties.containsKey("dataFile")) {
File modelDataFile = new File(
- getFilesDir().getPath() + "/" + properties.getProperty("dataFile"));
+ getFilesDir().getPath() + "/"
+ + properties.getProperty("dataFile"));
modelInfo.modelData = new byte[(int) modelDataFile.length()];
FileInputStream input = new FileInputStream(modelDataFile);
input.read(modelInfo.modelData, 0, modelInfo.modelData.length);
@@ -602,12 +608,14 @@
FileOutputStream fos = null;
try {
fos = new FileOutputStream( new File(
- getFilesDir() + File.separator + mModelInfo.name.replace(' ', '_') +
- "_capture_" + format.getChannelCount() + "ch_" +
- format.getSampleRate() + "hz_" + encoding + ".pcm"));
+ getFilesDir() + File.separator
+ + mModelInfo.name.replace(' ', '_')
+ + "_capture_" + format.getChannelCount() + "ch_"
+ + format.getSampleRate() + "hz_" + encoding + ".pcm"));
} catch (IOException e) {
Log.e(TAG, "Failed to open output for saving PCM data", e);
- postErrorToast("Failed to open output for saving PCM data: " + e.getMessage());
+ postErrorToast("Failed to open output for saving PCM data: "
+ + e.getMessage());
}
// Inform the user we're recording.
@@ -690,7 +698,8 @@
AudioFormat format = event.getCaptureAudioFormat();
result = result + "AudioFormat: " + ((format == null) ? "null" : format.toString());
byte[] triggerAudio = event.getTriggerAudio();
- result = result + ", TriggerAudio: " + (triggerAudio == null ? "null" : triggerAudio.length);
+ result = result + ", TriggerAudio: "
+ + (triggerAudio == null ? "null" : triggerAudio.length);
byte[] data = event.getData();
result = result + ", Data: " + (data == null ? "null" : data.length);
if (data != null) {
diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java
index c900eae..e36f398 100644
--- a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java
@@ -16,7 +16,6 @@
package android.hardware.soundtrigger;
-import android.hardware.soundtrigger.SoundTrigger;
import android.hardware.soundtrigger.SoundTrigger.ConfidenceLevel;
import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
@@ -51,10 +50,10 @@
Keyphrase unparceled = Keyphrase.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(keyphrase.id, unparceled.id);
- assertNull(unparceled.users);
- assertEquals(keyphrase.locale, unparceled.locale);
- assertEquals(keyphrase.text, unparceled.text);
+ assertEquals(keyphrase.getId(), unparceled.getId());
+ assertNull(unparceled.getUsers());
+ assertEquals(keyphrase.getLocale(), unparceled.getLocale());
+ assertEquals(keyphrase.getText(), unparceled.getText());
}
@SmallTest
@@ -71,10 +70,10 @@
Keyphrase unparceled = Keyphrase.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(keyphrase.id, unparceled.id);
- assertTrue(Arrays.equals(keyphrase.users, unparceled.users));
- assertEquals(keyphrase.locale, unparceled.locale);
- assertEquals(keyphrase.text, unparceled.text);
+ assertEquals(keyphrase.getId(), unparceled.getId());
+ assertTrue(Arrays.equals(keyphrase.getUsers(), unparceled.getUsers()));
+ assertEquals(keyphrase.getLocale(), unparceled.getLocale());
+ assertEquals(keyphrase.getText(), unparceled.getText());
}
@SmallTest
@@ -91,10 +90,10 @@
Keyphrase unparceled = Keyphrase.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(keyphrase.id, unparceled.id);
- assertTrue(Arrays.equals(keyphrase.users, unparceled.users));
- assertEquals(keyphrase.locale, unparceled.locale);
- assertEquals(keyphrase.text, unparceled.text);
+ assertEquals(keyphrase.getId(), unparceled.getId());
+ assertTrue(Arrays.equals(keyphrase.getUsers(), unparceled.getUsers()));
+ assertEquals(keyphrase.getLocale(), unparceled.getLocale());
+ assertEquals(keyphrase.getText(), unparceled.getText());
}
@SmallTest
@@ -116,10 +115,10 @@
KeyphraseSoundModel unparceled = KeyphraseSoundModel.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(ksm.uuid, unparceled.uuid);
- assertNull(unparceled.data);
- assertEquals(ksm.type, unparceled.type);
- assertTrue(Arrays.equals(keyphrases, unparceled.keyphrases));
+ assertEquals(ksm.getUuid(), unparceled.getUuid());
+ assertNull(unparceled.getData());
+ assertEquals(ksm.getType(), unparceled.getType());
+ assertTrue(Arrays.equals(keyphrases, unparceled.getKeyphrases()));
}
@SmallTest
@@ -141,10 +140,10 @@
KeyphraseSoundModel unparceled = KeyphraseSoundModel.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(ksm.uuid, unparceled.uuid);
- assertEquals(ksm.type, unparceled.type);
- assertTrue(Arrays.equals(ksm.keyphrases, unparceled.keyphrases));
- assertTrue(Arrays.equals(ksm.data, unparceled.data));
+ assertEquals(ksm.getUuid(), unparceled.getUuid());
+ assertEquals(ksm.getType(), unparceled.getType());
+ assertTrue(Arrays.equals(ksm.getKeyphrases(), unparceled.getKeyphrases()));
+ assertTrue(Arrays.equals(ksm.getData(), unparceled.getData()));
}
@SmallTest
@@ -163,10 +162,10 @@
KeyphraseSoundModel unparceled = KeyphraseSoundModel.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(ksm.uuid, unparceled.uuid);
- assertEquals(ksm.type, unparceled.type);
- assertNull(unparceled.keyphrases);
- assertTrue(Arrays.equals(ksm.data, unparceled.data));
+ assertEquals(ksm.getUuid(), unparceled.getUuid());
+ assertEquals(ksm.getType(), unparceled.getType());
+ assertNull(unparceled.getKeyphrases());
+ assertTrue(Arrays.equals(ksm.getData(), unparceled.getData()));
}
@SmallTest
@@ -185,10 +184,10 @@
KeyphraseSoundModel unparceled = KeyphraseSoundModel.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(ksm.uuid, unparceled.uuid);
- assertEquals(ksm.type, unparceled.type);
- assertTrue(Arrays.equals(ksm.keyphrases, unparceled.keyphrases));
- assertTrue(Arrays.equals(ksm.data, unparceled.data));
+ assertEquals(ksm.getUuid(), unparceled.getUuid());
+ assertEquals(ksm.getType(), unparceled.getType());
+ assertTrue(Arrays.equals(ksm.getKeyphrases(), unparceled.getKeyphrases()));
+ assertTrue(Arrays.equals(ksm.getData(), unparceled.getData()));
}
@LargeTest
@@ -212,10 +211,10 @@
KeyphraseSoundModel unparceled = KeyphraseSoundModel.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(ksm.uuid, unparceled.uuid);
- assertEquals(ksm.type, unparceled.type);
- assertTrue(Arrays.equals(ksm.data, unparceled.data));
- assertTrue(Arrays.equals(ksm.keyphrases, unparceled.keyphrases));
+ assertEquals(ksm.getUuid(), unparceled.getUuid());
+ assertEquals(ksm.getType(), unparceled.getType());
+ assertTrue(Arrays.equals(ksm.getData(), unparceled.getData()));
+ assertTrue(Arrays.equals(ksm.getKeyphrases(), unparceled.getKeyphrases()));
}
@SmallTest
diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
index c0583ce..2c3592c 100644
--- a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
@@ -17,7 +17,6 @@
package android.hardware.soundtrigger;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
@@ -37,6 +36,8 @@
import com.android.internal.app.ISoundTriggerService;
+import org.mockito.MockitoAnnotations;
+
import java.io.DataOutputStream;
import java.net.InetAddress;
import java.net.Socket;
@@ -45,8 +46,6 @@
import java.util.Random;
import java.util.UUID;
-import org.mockito.MockitoAnnotations;
-
public class GenericSoundModelTest extends AndroidTestCase {
static final int MSG_DETECTION_ERROR = -1;
static final int MSG_DETECTION_RESUME = 0;
@@ -96,11 +95,11 @@
// Update sound model
soundTriggerService.updateSoundModel(model);
- loadedModelUuids.add(model.uuid);
+ loadedModelUuids.add(model.getUuid());
// Confirm it was updated
GenericSoundModel returnedModel =
- soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
+ soundTriggerService.getSoundModel(new ParcelUuid(model.getUuid()));
assertEquals(model, returnedModel);
}
@@ -110,15 +109,15 @@
// Update sound model
soundTriggerService.updateSoundModel(model);
- loadedModelUuids.add(model.uuid);
+ loadedModelUuids.add(model.getUuid());
// Delete sound model
- soundTriggerService.deleteSoundModel(new ParcelUuid(model.uuid));
- loadedModelUuids.remove(model.uuid);
+ soundTriggerService.deleteSoundModel(new ParcelUuid(model.getUuid()));
+ loadedModelUuids.remove(model.getUuid());
// Confirm it was deleted
GenericSoundModel returnedModel =
- soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
+ soundTriggerService.getSoundModel(new ParcelUuid(model.getUuid()));
assertEquals(null, returnedModel);
}
@@ -134,14 +133,14 @@
// Update and start sound model recognition
soundTriggerService.updateSoundModel(model);
- loadedModelUuids.add(model.uuid);
- int r = soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback,
+ loadedModelUuids.add(model.getUuid());
+ int r = soundTriggerService.startRecognition(new ParcelUuid(model.getUuid()), spyCallback,
config);
assertEquals("Could Not Start Recognition with code: " + r,
android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
// Stop recognition
- r = soundTriggerService.stopRecognition(new ParcelUuid(model.uuid), spyCallback);
+ r = soundTriggerService.stopRecognition(new ParcelUuid(model.getUuid()), spyCallback);
assertEquals("Could Not Stop Recognition with code: " + r,
android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
}
@@ -158,13 +157,13 @@
// Update and start sound model
soundTriggerService.updateSoundModel(model);
- loadedModelUuids.add(model.uuid);
- soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback, config);
+ loadedModelUuids.add(model.getUuid());
+ soundTriggerService.startRecognition(new ParcelUuid(model.getUuid()), spyCallback, config);
// Send trigger to stub HAL
Socket socket = new Socket(InetAddress.getLocalHost(), 14035);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
- out.writeBytes("trig " + model.uuid.toString() + "\r\n");
+ out.writeBytes("trig " + model.getUuid().toString() + "\r\n");
out.flush();
socket.close();
@@ -227,11 +226,12 @@
if (operation == 0 && modelInfo.status == STATUS_UNLOADED) {
// Update and start sound model
soundTriggerService.updateSoundModel(modelInfo.model);
- loadedModelUuids.add(modelInfo.model.uuid);
+ loadedModelUuids.add(modelInfo.model.getUuid());
modelInfo.status = STATUS_LOADED;
} else if (operation == 1 && modelInfo.status == STATUS_LOADED) {
// Start the sound model
- int r = soundTriggerService.startRecognition(new ParcelUuid(modelInfo.model.uuid),
+ int r = soundTriggerService.startRecognition(new ParcelUuid(
+ modelInfo.model.getUuid()),
spyCallback, config);
assertEquals("Could Not Start Recognition with code: " + r,
android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
@@ -240,7 +240,7 @@
// Send trigger to stub HAL
Socket socket = new Socket(InetAddress.getLocalHost(), 14035);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
- out.writeBytes("trig " + modelInfo.model.uuid + "\r\n");
+ out.writeBytes("trig " + modelInfo.model.getUuid() + "\r\n");
out.flush();
socket.close();
@@ -249,19 +249,20 @@
reset(spyCallback);
} else if (operation == 3 && modelInfo.status == STATUS_STARTED) {
// Stop recognition
- int r = soundTriggerService.stopRecognition(new ParcelUuid(modelInfo.model.uuid),
+ int r = soundTriggerService.stopRecognition(new ParcelUuid(
+ modelInfo.model.getUuid()),
spyCallback);
assertEquals("Could Not Stop Recognition with code: " + r,
android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
modelInfo.status = STATUS_LOADED;
} else if (operation == 4 && modelInfo.status != STATUS_UNLOADED) {
// Delete sound model
- soundTriggerService.deleteSoundModel(new ParcelUuid(modelInfo.model.uuid));
- loadedModelUuids.remove(modelInfo.model.uuid);
+ soundTriggerService.deleteSoundModel(new ParcelUuid(modelInfo.model.getUuid()));
+ loadedModelUuids.remove(modelInfo.model.getUuid());
// Confirm it was deleted
- GenericSoundModel returnedModel =
- soundTriggerService.getSoundModel(new ParcelUuid(modelInfo.model.uuid));
+ GenericSoundModel returnedModel = soundTriggerService.getSoundModel(
+ new ParcelUuid(modelInfo.model.getUuid()));
assertEquals(null, returnedModel);
modelInfo.status = STATUS_UNLOADED;
}
diff --git a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java
index 7927ac4..287364f 100644
--- a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java
+++ b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java
@@ -159,36 +159,36 @@
Log.e(TAG, "KeyphraseSoundModel must be non-null");
return false;
}
- if (soundModel.uuid == null) {
+ if (soundModel.getUuid() == null) {
Log.e(TAG, "KeyphraseSoundModel must have a UUID");
return false;
}
- if (soundModel.data == null) {
+ if (soundModel.getData() == null) {
Log.e(TAG, "KeyphraseSoundModel must have data");
return false;
}
- if (soundModel.keyphrases == null || soundModel.keyphrases.length != 1) {
+ if (soundModel.getKeyphrases() == null || soundModel.getKeyphrases().length != 1) {
Log.e(TAG, "Keyphrase must be exactly 1");
return false;
}
- Keyphrase keyphrase = soundModel.keyphrases[0];
- if (keyphrase.id <= 0) {
+ Keyphrase keyphrase = soundModel.getKeyphrases()[0];
+ if (keyphrase.getId() <= 0) {
Log.e(TAG, "Keyphrase must have a valid ID");
return false;
}
- if (keyphrase.recognitionModes < 0) {
+ if (keyphrase.getRecognitionModes() < 0) {
Log.e(TAG, "Recognition modes must be valid");
return false;
}
- if (keyphrase.locale == null) {
+ if (keyphrase.getLocale() == null) {
Log.e(TAG, "Locale must not be null");
return false;
}
- if (keyphrase.text == null) {
+ if (keyphrase.getText() == null) {
Log.e(TAG, "Text must not be null");
return false;
}
- if (keyphrase.users == null || keyphrase.users.length == 0) {
+ if (keyphrase.getUsers() == null || keyphrase.getUsers().length == 0) {
Log.e(TAG, "Keyphrase must have valid user(s)");
return false;
}
diff --git a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
index b357ad0..e4880fd 100644
--- a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
+++ b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
@@ -91,7 +91,7 @@
}
boolean status = mEnrollmentUtil.deleteSoundModel(KEYPHRASE_ID, BCP47_LOCALE);
if (status) {
- Toast.makeText(this, "Successfully un-enrolled, model UUID=" + soundModel.uuid,
+ Toast.makeText(this, "Successfully un-enrolled, model UUID=" + soundModel.getUuid(),
Toast.LENGTH_SHORT)
.show();
} else {
@@ -112,11 +112,11 @@
// Generate a fake model to push.
byte[] data = new byte[2048];
mRandom.nextBytes(data);
- KeyphraseSoundModel updated = new KeyphraseSoundModel(soundModel.uuid,
- soundModel.vendorUuid, data, soundModel.keyphrases);
+ KeyphraseSoundModel updated = new KeyphraseSoundModel(soundModel.getUuid(),
+ soundModel.getVendorUuid(), data, soundModel.getKeyphrases());
boolean status = mEnrollmentUtil.addOrUpdateSoundModel(updated);
if (status) {
- Toast.makeText(this, "Successfully re-enrolled, model UUID=" + updated.uuid,
+ Toast.makeText(this, "Successfully re-enrolled, model UUID=" + updated.getUuid(),
Toast.LENGTH_SHORT)
.show();
} else {
diff --git a/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java
index f4f804a..8480544 100644
--- a/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java
@@ -21,17 +21,31 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Arrays;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ApfCapabilitiesTest {
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getContext();
+ }
+
@Test
public void testConstructAndParcel() {
final ApfCapabilities caps = new ApfCapabilities(123, 456, 789);
@@ -59,4 +73,27 @@
caps = new ApfCapabilities(4 /* apfVersionSupported */, 5, 6);
assertTrue(caps.hasDataAccess());
}
+
+ @Test
+ public void testGetApfDrop8023Frames() {
+ // Get com.android.internal.R.bool.config_apfDrop802_3Frames. The test cannot directly
+ // use R.bool.config_apfDrop802_3Frames because that is not a stable resource ID.
+ final int resId = mContext.getResources().getIdentifier("config_apfDrop802_3Frames",
+ "bool", "android");
+ final boolean shouldDrop8023Frames = mContext.getResources().getBoolean(resId);
+ final boolean actual = ApfCapabilities.getApfDrop8023Frames();
+ assertEquals(shouldDrop8023Frames, actual);
+ }
+
+ @Test
+ public void testGetApfEtherTypeBlackList() {
+ // Get com.android.internal.R.array.config_apfEthTypeBlackList. The test cannot directly
+ // use R.array.config_apfEthTypeBlackList because that is not a stable resource ID.
+ final int resId = mContext.getResources().getIdentifier("config_apfEthTypeBlackList",
+ "array", "android");
+ final int[] blacklistedEtherTypeArray = mContext.getResources().getIntArray(resId);
+ final int[] actual = ApfCapabilities.getApfEtherTypeBlackList();
+ assertNotNull(actual);
+ assertTrue(Arrays.equals(blacklistedEtherTypeArray, actual));
+ }
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 4bfb51b..86d8a82 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -205,6 +205,7 @@
import android.provider.Settings;
import android.security.KeyStore;
import android.system.Os;
+import android.telephony.TelephonyManager;
import android.test.mock.MockContentResolver;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -307,6 +308,8 @@
private static final long TIMESTAMP = 1234L;
+ private static final int NET_ID = 110;
+
private static final String CLAT_PREFIX = "v4-";
private static final String MOBILE_IFNAME = "test_rmnet_data0";
private static final String WIFI_IFNAME = "test_wlan0";
@@ -345,6 +348,7 @@
@Mock IBinder mIBinder;
@Mock LocationManager mLocationManager;
@Mock AppOpsManager mAppOpsManager;
+ @Mock TelephonyManager mTelephonyManager;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -431,6 +435,7 @@
if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
+ if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
return super.getSystemService(name);
}
@@ -1015,6 +1020,7 @@
private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
private VpnInfo mVpnInfo;
+ private Network[] mUnderlyingNetworks;
public MockVpn(int userId) {
super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
@@ -1104,9 +1110,21 @@
return super.getVpnInfo();
}
- private void setVpnInfo(VpnInfo vpnInfo) {
+ private synchronized void setVpnInfo(VpnInfo vpnInfo) {
mVpnInfo = vpnInfo;
}
+
+ @Override
+ public synchronized Network[] getUnderlyingNetworks() {
+ if (mUnderlyingNetworks != null) return mUnderlyingNetworks;
+
+ return super.getUnderlyingNetworks();
+ }
+
+ /** Don't override behavior for {@link Vpn#setUnderlyingNetworks}. */
+ private synchronized void overrideUnderlyingNetworks(Network[] underlyingNetworks) {
+ mUnderlyingNetworks = underlyingNetworks;
+ }
}
private void mockVpn(int uid) {
@@ -2896,7 +2914,7 @@
class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
Parcelable {
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
return true;
}
@@ -2924,7 +2942,7 @@
}
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
if (other instanceof LocalStringNetworkSpecifier) {
return TextUtils.equals(mString,
((LocalStringNetworkSpecifier) other).mString);
@@ -3045,7 +3063,10 @@
});
class NonParcelableSpecifier extends NetworkSpecifier {
- public boolean satisfiedBy(NetworkSpecifier other) { return false; }
+ @Override
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
+ return false;
+ }
};
class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
@Override public int describeContents() { return 0; }
@@ -6795,15 +6816,11 @@
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
- try {
- assertFalse(
- "Mismatched uid/package name should not pass the location permission check",
- mService.checkConnectivityDiagnosticsPermissions(
- Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid,
- mContext.getOpPackageName()));
- } catch (SecurityException e) {
- fail("checkConnectivityDiagnosticsPermissions shouldn't surface a SecurityException");
- }
+ assertFalse(
+ "Mismatched uid/package name should not pass the location permission check",
+ mService.checkConnectivityDiagnosticsPermissions(
+ Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid,
+ mContext.getOpPackageName()));
}
@Test
@@ -6824,9 +6841,10 @@
@Test
public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
+ final Network network = new Network(NET_ID);
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
- null, null, null, null, null, new NetworkCapabilities(), 0,
+ null, null, network, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
@@ -6839,11 +6857,19 @@
info.ownerUid = Process.myUid();
info.vpnIface = "interface";
mMockVpn.setVpnInfo(info);
+ mMockVpn.overrideUnderlyingNetworks(new Network[] {network});
assertTrue(
"Active VPN permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
Process.myPid(), Process.myUid(), naiWithoutUid,
mContext.getOpPackageName()));
+
+ mMockVpn.overrideUnderlyingNetworks(null);
+ assertFalse(
+ "VPN shouldn't receive callback on non-underlying network",
+ mService.checkConnectivityDiagnosticsPermissions(
+ Process.myPid(), Process.myUid(), naiWithoutUid,
+ mContext.getOpPackageName()));
}
@Test
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
index a4610b2..cec59e7 100644
--- a/tools/aapt2/java/AnnotationProcessor.cpp
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -18,6 +18,7 @@
#include <algorithm>
#include <array>
+#include <regex>
#include "text/Unicode.h"
#include "text/Utf8Iterator.h"
@@ -65,14 +66,26 @@
// Treat deprecated specially, since we don't remove it from the source comment.
if (comment.find(sDeprecated) != std::string::npos) {
- annotation_bit_mask_ |= AnnotationRule::kDeprecated;
+ annotation_parameter_map_[AnnotationRule::kDeprecated] = "";
}
for (const AnnotationRule& rule : sAnnotationRules) {
std::string::size_type idx = comment.find(rule.doc_str.data());
if (idx != std::string::npos) {
- annotation_bit_mask_ |= rule.bit_mask;
- comment.erase(comment.begin() + idx, comment.begin() + idx + rule.doc_str.size());
+ // Captures all parameters associated with the specified annotation rule
+ // by matching the first pair of parantheses after the rule.
+ std::regex re(rule.doc_str.to_string() + "\\s*\\((.+)\\)");
+ std::smatch match_result;
+ const bool is_match = std::regex_search(comment, match_result, re);
+ // We currently only capture and preserve parameters for SystemApi.
+ if (is_match && rule.bit_mask == AnnotationRule::kSystemApi) {
+ annotation_parameter_map_[rule.bit_mask] = match_result[1].str();
+ comment.erase(comment.begin() + match_result.position(),
+ comment.begin() + match_result.position() + match_result.length());
+ } else {
+ annotation_parameter_map_[rule.bit_mask] = "";
+ comment.erase(comment.begin() + idx, comment.begin() + idx + rule.doc_str.size());
+ }
}
}
@@ -119,13 +132,19 @@
printer->Println(" */");
}
- if (annotation_bit_mask_ & AnnotationRule::kDeprecated) {
+ if (annotation_parameter_map_.find(AnnotationRule::kDeprecated) !=
+ annotation_parameter_map_.end()) {
printer->Println("@Deprecated");
}
for (const AnnotationRule& rule : sAnnotationRules) {
- if (annotation_bit_mask_ & rule.bit_mask) {
- printer->Println(rule.annotation);
+ const auto& it = annotation_parameter_map_.find(rule.bit_mask);
+ if (it != annotation_parameter_map_.end()) {
+ printer->Print(rule.annotation);
+ if (!it->second.empty()) {
+ printer->Print("(").Print(it->second).Print(")");
+ }
+ printer->Print("\n");
}
}
}
diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h
index ae7bdb0..fdb5846 100644
--- a/tools/aapt2/java/AnnotationProcessor.h
+++ b/tools/aapt2/java/AnnotationProcessor.h
@@ -19,6 +19,7 @@
#include <sstream>
#include <string>
+#include <unordered_map>
#include "androidfw/StringPiece.h"
@@ -70,7 +71,7 @@
std::stringstream comment_;
std::stringstream mAnnotations;
bool has_comments_ = false;
- uint32_t annotation_bit_mask_ = 0;
+ std::unordered_map<uint32_t, std::string> annotation_parameter_map_;
void AppendCommentLine(std::string line);
};
diff --git a/tools/aapt2/java/AnnotationProcessor_test.cpp b/tools/aapt2/java/AnnotationProcessor_test.cpp
index 69f49c8..7d0a4e9 100644
--- a/tools/aapt2/java/AnnotationProcessor_test.cpp
+++ b/tools/aapt2/java/AnnotationProcessor_test.cpp
@@ -61,6 +61,21 @@
EXPECT_THAT(annotations, HasSubstr("This is a system API"));
}
+TEST(AnnotationProcessorTest, EmitsSystemApiAnnotationParamsAndRemovesFromComment) {
+ AnnotationProcessor processor;
+ processor.AppendComment("@SystemApi (p1=k1,p2=k2) This is a system API");
+
+ std::string annotations;
+ StringOutputStream out(&annotations);
+ Printer printer(&out);
+ processor.Print(&printer);
+ out.Flush();
+
+ EXPECT_THAT(annotations, HasSubstr("@android.annotation.SystemApi(p1=k1,p2=k2)"));
+ EXPECT_THAT(annotations, Not(HasSubstr("@SystemApi")));
+ EXPECT_THAT(annotations, HasSubstr("This is a system API"));
+}
+
TEST(AnnotationProcessorTest, EmitsTestApiAnnotationAndRemovesFromComment) {
AnnotationProcessor processor;
processor.AppendComment("@TestApi This is a test API");
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index bf39093..1387bb5 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -454,16 +454,12 @@
return has_attribution_node;
}
-static void populateFieldNumberToAnnotations(const AtomDecl& atomDecl,
- FieldNumberToAnnotations* fieldNumberToAnnotations) {
- for (FieldNumberToAnnotations::const_iterator it = atomDecl.fieldNumberToAnnotations.begin();
- it != atomDecl.fieldNumberToAnnotations.end(); it++) {
+static void populateFieldNumberToAtomDeclSet(const shared_ptr<AtomDecl>& atomDecl,
+ FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet) {
+ for (FieldNumberToAnnotations::const_iterator it = atomDecl->fieldNumberToAnnotations.begin();
+ it != atomDecl->fieldNumberToAnnotations.end(); it++) {
const int fieldNumber = it->first;
- const set<shared_ptr<Annotation>>& insertAnnotationsSource = it->second;
- set<shared_ptr<Annotation>>& insertAnnotationsTarget =
- (*fieldNumberToAnnotations)[fieldNumber];
- insertAnnotationsTarget.insert(insertAnnotationsSource.begin(),
- insertAnnotationsSource.end());
+ (*fieldNumberToAtomDeclSet)[fieldNumber].insert(atomDecl);
}
}
@@ -513,18 +509,19 @@
}
const Descriptor* atom = atomField->message_type();
- AtomDecl atomDecl(atomField->number(), atomField->name(), atom->name());
+ shared_ptr<AtomDecl> atomDecl =
+ make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
if (atomField->options().GetExtension(os::statsd::allow_from_any_uid) == true) {
- atomDecl.whitelisted = true;
+ atomDecl->whitelisted = true;
if (dbg) {
printf("%s is whitelisted\n", atomField->name().c_str());
}
}
- if (atomDecl.code < PULL_ATOM_START_ID &&
+ if (atomDecl->code < PULL_ATOM_START_ID &&
atomField->options().GetExtension(os::statsd::truncate_timestamp)) {
- addAnnotationToAtomDecl(&atomDecl, ATOM_ID_FIELD_NUMBER,
+ addAnnotationToAtomDecl(atomDecl.get(), ATOM_ID_FIELD_NUMBER,
ANNOTATION_ID_TRUNCATE_TIMESTAMP, ANNOTATION_TYPE_BOOL,
AnnotationValue(true));
if (dbg) {
@@ -533,29 +530,33 @@
}
vector<java_type_t> signature;
- errorCount += collate_atom(atom, &atomDecl, &signature);
- if (atomDecl.primaryFields.size() != 0 && atomDecl.exclusiveField == 0) {
+ errorCount += collate_atom(atom, atomDecl.get(), &signature);
+ if (atomDecl->primaryFields.size() != 0 && atomDecl->exclusiveField == 0) {
print_error(atomField, "Cannot have a primary field without an exclusive field: %s\n",
atomField->name().c_str());
errorCount++;
continue;
}
- atoms->decls.insert(atomDecl);
- FieldNumberToAnnotations& fieldNumberToAnnotations = atoms->signatureInfoMap[signature];
- populateFieldNumberToAnnotations(atomDecl, &fieldNumberToAnnotations);
+ FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = atoms->signatureInfoMap[signature];
+ populateFieldNumberToAtomDeclSet(atomDecl, &fieldNumberToAtomDeclSet);
- AtomDecl nonChainedAtomDecl(atomField->number(), atomField->name(), atom->name());
+ atoms->decls.insert(atomDecl);
+
+ shared_ptr<AtomDecl> nonChainedAtomDecl =
+ make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
vector<java_type_t> nonChainedSignature;
- if (get_non_chained_node(atom, &nonChainedAtomDecl, &nonChainedSignature)) {
- atoms->non_chained_decls.insert(nonChainedAtomDecl);
- FieldNumberToAnnotations& fieldNumberToAnnotations =
+ if (get_non_chained_node(atom, nonChainedAtomDecl.get(), &nonChainedSignature)) {
+ FieldNumberToAtomDeclSet& nonChainedFieldNumberToAtomDeclSet =
atoms->nonChainedSignatureInfoMap[nonChainedSignature];
- populateFieldNumberToAnnotations(atomDecl, &fieldNumberToAnnotations);
+ populateFieldNumberToAtomDeclSet(nonChainedAtomDecl,
+ &nonChainedFieldNumberToAtomDeclSet);
+
+ atoms->non_chained_decls.insert(nonChainedAtomDecl);
}
- if (atomDecl.code < PULL_ATOM_START_ID && atomDecl.code > maxPushedAtomId) {
- maxPushedAtomId = atomDecl.code;
+ if (atomDecl->code < PULL_ATOM_START_ID && atomDecl->code > maxPushedAtomId) {
+ maxPushedAtomId = atomDecl->code;
}
}
@@ -563,8 +564,7 @@
if (dbg) {
printf("signatures = [\n");
- for (map<vector<java_type_t>, FieldNumberToAnnotations>::const_iterator it =
- atoms->signatureInfoMap.begin();
+ for (SignatureInfoMap::const_iterator it = atoms->signatureInfoMap.begin();
it != atoms->signatureInfoMap.end(); it++) {
printf(" ");
for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end();
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index 2aedb21..b1cf134 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -110,7 +110,16 @@
}
};
-using FieldNumberToAnnotations = map<int, set<shared_ptr<Annotation>>>;
+struct SharedComparator {
+ template <typename T>
+ inline bool operator()(const shared_ptr<T>& lhs, const shared_ptr<T>& rhs) const {
+ return (*lhs) < (*rhs);
+ }
+};
+
+using AnnotationSet = set<shared_ptr<Annotation>, SharedComparator>;
+
+using FieldNumberToAnnotations = map<int, AnnotationSet>;
/**
* The name and type for an atom field.
@@ -169,11 +178,19 @@
}
};
+using AtomDeclSet = set<shared_ptr<AtomDecl>, SharedComparator>;
+
+// Maps a field number to a set of atoms that have annotation(s) for their field with that field
+// number.
+using FieldNumberToAtomDeclSet = map<int, AtomDeclSet>;
+
+using SignatureInfoMap = map<vector<java_type_t>, FieldNumberToAtomDeclSet>;
+
struct Atoms {
- map<vector<java_type_t>, FieldNumberToAnnotations> signatureInfoMap;
- set<AtomDecl> decls;
- set<AtomDecl> non_chained_decls;
- map<vector<java_type_t>, FieldNumberToAnnotations> nonChainedSignatureInfoMap;
+ SignatureInfoMap signatureInfoMap;
+ AtomDeclSet decls;
+ AtomDeclSet non_chained_decls;
+ SignatureInfoMap nonChainedSignatureInfoMap;
int maxPushedAtomId;
};
diff --git a/tools/stats_log_api_gen/atoms_info_writer.cpp b/tools/stats_log_api_gen/atoms_info_writer.cpp
index 6944752..862fed4 100644
--- a/tools/stats_log_api_gen/atoms_info_writer.cpp
+++ b/tools/stats_log_api_gen/atoms_info_writer.cpp
@@ -62,11 +62,11 @@
fprintf(out,
"const std::set<int> "
"AtomsInfo::kTruncatingTimestampAtomBlackList = {\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end();
- atom++) {
- if (kTruncatingAtomNames.find(atom->name) != kTruncatingAtomNames.end()) {
- const string constant = make_constant_name(atom->name);
- fprintf(out, " %d, // %s\n", atom->code, constant.c_str());
+ for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
+ atomIt++) {
+ if (kTruncatingAtomNames.find((*atomIt)->name) != kTruncatingAtomNames.end()) {
+ const string constant = make_constant_name((*atomIt)->name);
+ fprintf(out, " %d, // %s\n", (*atomIt)->code, constant.c_str());
}
}
@@ -74,13 +74,13 @@
fprintf(out, "\n");
fprintf(out, "const std::set<int> AtomsInfo::kAtomsWithAttributionChain = {\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end();
- atom++) {
- for (vector<AtomField>::const_iterator field = atom->fields.begin();
- field != atom->fields.end(); field++) {
+ for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
+ atomIt++) {
+ for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin();
+ field != (*atomIt)->fields.end(); field++) {
if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- const string constant = make_constant_name(atom->name);
- fprintf(out, " %d, // %s\n", atom->code, constant.c_str());
+ const string constant = make_constant_name((*atomIt)->name);
+ fprintf(out, " %d, // %s\n", (*atomIt)->code, constant.c_str());
break;
}
}
@@ -90,11 +90,11 @@
fprintf(out, "\n");
fprintf(out, "const std::set<int> AtomsInfo::kWhitelistedAtoms = {\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end();
- atom++) {
- if (atom->whitelisted) {
- const string constant = make_constant_name(atom->name);
- fprintf(out, " %d, // %s\n", atom->code, constant.c_str());
+ for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
+ atomIt++) {
+ if ((*atomIt)->whitelisted) {
+ const string constant = make_constant_name((*atomIt)->name);
+ fprintf(out, " %d, // %s\n", (*atomIt)->code, constant.c_str());
}
}
@@ -103,17 +103,17 @@
fprintf(out, "static std::map<int, int> getAtomUidField() {\n");
fprintf(out, " std::map<int, int> uidField;\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end();
- atom++) {
- if (atom->uidField == 0) {
+ for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
+ atomIt++) {
+ if ((*atomIt)->uidField == 0) {
continue;
}
fprintf(out,
"\n // Adding uid field for atom "
"(%d)%s\n",
- atom->code, atom->name.c_str());
- fprintf(out, " uidField[%d /* %s */] = %d;\n", atom->code,
- make_constant_name(atom->name).c_str(), atom->uidField);
+ (*atomIt)->code, (*atomIt)->name.c_str());
+ fprintf(out, " uidField[%d /* %s */] = %d;\n", (*atomIt)->code,
+ make_constant_name((*atomIt)->name).c_str(), (*atomIt)->uidField);
}
fprintf(out, " return uidField;\n");
@@ -128,35 +128,35 @@
"getStateAtomFieldOptions() {\n");
fprintf(out, " std::map<int, StateAtomFieldOptions> options;\n");
fprintf(out, " StateAtomFieldOptions* opt;\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end();
- atom++) {
- if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
+ for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
+ atomIt++) {
+ if ((*atomIt)->primaryFields.size() == 0 && (*atomIt)->exclusiveField == 0) {
continue;
}
fprintf(out,
"\n // Adding primary and exclusive fields for atom "
"(%d)%s\n",
- atom->code, atom->name.c_str());
- fprintf(out, " opt = &(options[%d /* %s */]);\n", atom->code,
- make_constant_name(atom->name).c_str());
- fprintf(out, " opt->primaryFields.reserve(%lu);\n", atom->primaryFields.size());
- for (const auto& field : atom->primaryFields) {
+ (*atomIt)->code, (*atomIt)->name.c_str());
+ fprintf(out, " opt = &(options[%d /* %s */]);\n", (*atomIt)->code,
+ make_constant_name((*atomIt)->name).c_str());
+ fprintf(out, " opt->primaryFields.reserve(%lu);\n", (*atomIt)->primaryFields.size());
+ for (const auto& field : (*atomIt)->primaryFields) {
fprintf(out, " opt->primaryFields.push_back(%d);\n", field);
}
- fprintf(out, " opt->exclusiveField = %d;\n", atom->exclusiveField);
- if (atom->defaultState != INT_MAX) {
- fprintf(out, " opt->defaultState = %d;\n", atom->defaultState);
+ fprintf(out, " opt->exclusiveField = %d;\n", (*atomIt)->exclusiveField);
+ if ((*atomIt)->defaultState != INT_MAX) {
+ fprintf(out, " opt->defaultState = %d;\n", (*atomIt)->defaultState);
} else {
fprintf(out, " opt->defaultState = UNSET_VALUE;\n");
}
- if (atom->resetState != INT_MAX) {
- fprintf(out, " opt->resetState = %d;\n", atom->resetState);
+ if ((*atomIt)->resetState != INT_MAX) {
+ fprintf(out, " opt->resetState = %d;\n", (*atomIt)->resetState);
} else {
fprintf(out, " opt->resetState = UNSET_VALUE;\n");
}
- fprintf(out, " opt->nested = %d;\n", atom->nested);
+ fprintf(out, " opt->nested = %d;\n", (*atomIt)->nested);
}
fprintf(out, " return options;\n");
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
index 5a22b5c..3eabb14 100644
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -22,9 +22,8 @@
namespace android {
namespace stats_log_api_gen {
-static int write_java_q_logger_class(
- FILE* out, const map<vector<java_type_t>, FieldNumberToAnnotations>& signatureInfoMap,
- const AtomDecl& attributionDecl) {
+static int write_java_q_logger_class(FILE* out, const SignatureInfoMap& signatureInfoMap,
+ const AtomDecl& attributionDecl) {
fprintf(out, "\n");
fprintf(out, " // Write logging helper methods for statsd in Q and earlier.\n");
fprintf(out, " private static class QLogger {\n");
@@ -41,47 +40,64 @@
}
static void write_annotations(FILE* out, int argIndex,
- const FieldNumberToAnnotations& fieldNumberToAnnotations) {
- auto it = fieldNumberToAnnotations.find(argIndex);
- if (it == fieldNumberToAnnotations.end()) {
+ const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet) {
+ FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
+ fieldNumberToAtomDeclSet.find(argIndex);
+ if (fieldNumberToAtomDeclSet.end() == fieldNumberToAtomDeclSetIt) {
return;
}
- const set<shared_ptr<Annotation>>& annotations = it->second;
- for (auto& annotation : annotations) {
- // TODO(b/151744250): Group annotations for same atoms.
- // TODO(b/151786433): Write atom constant name instead of atom id literal.
- fprintf(out, " if (code == %d) {\n", annotation->atomId);
- switch (annotation->type) {
- case ANNOTATION_TYPE_INT:
+ const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
+ for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
+ fprintf(out, " if (code == %d) {\n", atomDecl->code);
+ const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex);
+ int resetState = -1;
+ int defaultState = -1;
+ for (const shared_ptr<Annotation>& annotation : annotations) {
+ // TODO(b/151786433): Write atom constant name instead of atom id literal.
+ switch (annotation->type) {
// TODO(b/151776731): Check for reset state annotation and only include
// reset state when field value == default state annotation value.
- // TODO(b/151786433): Write annotation constant name instead of
- // annotation id literal.
- fprintf(out, " builder.addIntAnnotation((byte) %d, %d);\n",
- annotation->annotationId, annotation->value.intValue);
- break;
- case ANNOTATION_TYPE_BOOL:
- // TODO(b/151786433): Write annotation constant name instead of
- // annotation id literal.
- fprintf(out, " builder.addBooleanAnnotation((byte) %d, %s);\n",
- annotation->annotationId, annotation->value.boolValue ? "true" : "false");
- break;
- default:
- break;
+ case ANNOTATION_TYPE_INT:
+ // TODO(b/151786433): Write annotation constant name instead of
+ // annotation id literal.
+ if (ANNOTATION_ID_RESET_STATE == annotation->annotationId) {
+ resetState = annotation->value.intValue;
+ } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
+ defaultState = annotation->value.intValue;
+ } else {
+ fprintf(out, " builder.addIntAnnotation((byte) %d, %d);\n",
+ annotation->annotationId, annotation->value.intValue);
+ }
+ break;
+ case ANNOTATION_TYPE_BOOL:
+ // TODO(b/151786433): Write annotation constant name instead of
+ // annotation id literal.
+ fprintf(out, " builder.addBooleanAnnotation((byte) %d, %s);\n",
+ annotation->annotationId,
+ annotation->value.boolValue ? "true" : "false");
+ break;
+ default:
+ break;
+ }
+ }
+ if (defaultState != -1 && resetState != -1) {
+ fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState);
+ fprintf(out, " builder.addIntAnnotation((byte) %d, %d);\n",
+ ANNOTATION_ID_RESET_STATE, defaultState);
+ fprintf(out, " }\n");
}
fprintf(out, " }\n");
}
}
-static int write_java_methods(
- FILE* out, const map<vector<java_type_t>, FieldNumberToAnnotations>& signatureInfoMap,
- const AtomDecl& attributionDecl, const bool supportQ) {
+static int write_java_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
+ const AtomDecl& attributionDecl, const bool supportQ) {
for (auto signatureInfoMapIt = signatureInfoMap.begin();
signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
// Print method signature.
fprintf(out, " public static void write(int code");
const vector<java_type_t>& signature = signatureInfoMapIt->first;
- const FieldNumberToAnnotations& fieldNumberToAnnotations = signatureInfoMapIt->second;
+ const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
int argIndex = 1;
for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
arg++) {
@@ -120,7 +136,7 @@
// Write atom code.
fprintf(out, "%s builder.setAtomId(code);\n", indent.c_str());
- write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAnnotations);
+ write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet);
// Write the args.
argIndex = 1;
@@ -231,7 +247,7 @@
fprintf(stderr, "Encountered unsupported type.");
return 1;
}
- write_annotations(out, argIndex, fieldNumberToAnnotations);
+ write_annotations(out, argIndex, fieldNumberToAtomDeclSet);
argIndex++;
}
diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp
index 7d22583..d21e270 100644
--- a/tools/stats_log_api_gen/java_writer_q.cpp
+++ b/tools/stats_log_api_gen/java_writer_q.cpp
@@ -53,9 +53,8 @@
fprintf(out, "%sprivate static final int LIST_TYPE_OVERHEAD = 2;\n", indent.c_str());
}
-int write_java_methods_q_schema(
- FILE* out, const map<vector<java_type_t>, FieldNumberToAnnotations>& signatureInfoMap,
- const AtomDecl& attributionDecl, const string& indent) {
+int write_java_methods_q_schema(FILE* out, const SignatureInfoMap& signatureInfoMap,
+ const AtomDecl& attributionDecl, const string& indent) {
int requiredHelpers = 0;
for (auto signatureInfoMapIt = signatureInfoMap.begin();
signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h
index f1cfc44..c511a84 100644
--- a/tools/stats_log_api_gen/java_writer_q.h
+++ b/tools/stats_log_api_gen/java_writer_q.h
@@ -32,9 +32,8 @@
void write_java_q_logging_constants(FILE* out, const string& indent);
-int write_java_methods_q_schema(
- FILE* out, const map<vector<java_type_t>, FieldNumberToAnnotations>& signatureInfoMap,
- const AtomDecl& attributionDecl, const string& indent);
+int write_java_methods_q_schema(FILE* out, const SignatureInfoMap& signatureInfoMap,
+ const AtomDecl& attributionDecl, const string& indent);
void write_java_helpers_for_q_schema_methods(FILE* out, const AtomDecl& attributionDecl,
const int requiredHelpers, const string& indent);
diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp
index 0cf3225..c0d73fa 100644
--- a/tools/stats_log_api_gen/native_writer.cpp
+++ b/tools/stats_log_api_gen/native_writer.cpp
@@ -22,35 +22,53 @@
namespace stats_log_api_gen {
static void write_annotations(FILE* out, int argIndex,
- const FieldNumberToAnnotations& fieldNumberToAnnotations,
+ const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
const string& methodPrefix, const string& methodSuffix) {
- auto fieldNumberToAnnotationsIt = fieldNumberToAnnotations.find(argIndex);
- if (fieldNumberToAnnotationsIt == fieldNumberToAnnotations.end()) {
+ FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
+ fieldNumberToAtomDeclSet.find(argIndex);
+ if (fieldNumberToAtomDeclSet.end() == fieldNumberToAtomDeclSetIt) {
return;
}
- const set<shared_ptr<Annotation>>& annotations = fieldNumberToAnnotationsIt->second;
- for (const shared_ptr<Annotation>& annotation : annotations) {
- // TODO(b/151744250): Group annotations for same atoms.
- // TODO(b/151786433): Write atom constant name instead of atom id literal.
- fprintf(out, " if (code == %d) {\n", annotation->atomId);
- switch (annotation->type) {
- // TODO(b/151776731): Check for reset state annotation and only include
- // reset state when field value == default state annotation value.
- case ANNOTATION_TYPE_INT:
- // TODO(b/151786433): Write annotation constant name instead of
- // annotation id literal.
- fprintf(out, " %saddInt32Annotation(%s%d, %d);\n", methodPrefix.c_str(),
- methodSuffix.c_str(), annotation->annotationId, annotation->value.intValue);
- break;
- case ANNOTATION_TYPE_BOOL:
- // TODO(b/151786433): Write annotation constant name instead of
- // annotation id literal.
- fprintf(out, " %saddBoolAnnotation(%s%d, %s);\n", methodPrefix.c_str(),
- methodSuffix.c_str(), annotation->annotationId,
- annotation->value.boolValue ? "true" : "false");
- break;
- default:
- break;
+ const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
+ for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
+ fprintf(out, " if (code == %d) {\n", atomDecl->code);
+ const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex);
+ int resetState = -1;
+ int defaultState = -1;
+ for (const shared_ptr<Annotation>& annotation : annotations) {
+ // TODO(b/151786433): Write atom constant name instead of atom id literal.
+ switch (annotation->type) {
+ // TODO(b/151776731): Check for reset state annotation and only include
+ // reset state when field value == default state annotation value.
+ case ANNOTATION_TYPE_INT:
+ // TODO(b/151786433): Write annotation constant name instead of
+ // annotation id literal.
+ if (ANNOTATION_ID_RESET_STATE == annotation->annotationId) {
+ resetState = annotation->value.intValue;
+ } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
+ defaultState = annotation->value.intValue;
+ } else {
+ fprintf(out, " %saddInt32Annotation(%s%d, %d);\n",
+ methodPrefix.c_str(), methodSuffix.c_str(),
+ annotation->annotationId, annotation->value.intValue);
+ }
+ break;
+ case ANNOTATION_TYPE_BOOL:
+ // TODO(b/151786433): Write annotation constant name instead of
+ // annotation id literal.
+ fprintf(out, " %saddBoolAnnotation(%s%d, %s);\n", methodPrefix.c_str(),
+ methodSuffix.c_str(), annotation->annotationId,
+ annotation->value.boolValue ? "true" : "false");
+ break;
+ default:
+ break;
+ }
+ }
+ if (defaultState != -1 && resetState != -1) {
+ fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState);
+ fprintf(out, " %saddInt32Annotation(%s%d, %d);\n", methodPrefix.c_str(),
+ methodSuffix.c_str(), ANNOTATION_ID_RESET_STATE, defaultState);
+ fprintf(out, " }\n");
}
fprintf(out, " }\n");
}
@@ -62,7 +80,7 @@
for (auto signatureInfoMapIt = atoms.signatureInfoMap.begin();
signatureInfoMapIt != atoms.signatureInfoMap.end(); signatureInfoMapIt++) {
vector<java_type_t> signature = signatureInfoMapIt->first;
- const FieldNumberToAnnotations& fieldNumberToAnnotations = signatureInfoMapIt->second;
+ const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
// Key value pairs not supported in native.
if (find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != signature.end()) {
continue;
@@ -73,7 +91,7 @@
if (supportQ) {
fprintf(out, " StatsEventCompat event;\n");
fprintf(out, " event.setAtomId(code);\n");
- write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAnnotations, "event.", "");
+ write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "event.", "");
for (vector<java_type_t>::const_iterator arg = signature.begin();
arg != signature.end(); arg++) {
switch (*arg) {
@@ -109,14 +127,14 @@
fprintf(stderr, "Encountered unsupported type.");
return 1;
}
- write_annotations(out, argIndex, fieldNumberToAnnotations, "event.", "");
+ write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "event.", "");
argIndex++;
}
fprintf(out, " return event.writeToSocket();\n");
} else {
fprintf(out, " AStatsEvent* event = AStatsEvent_obtain();\n");
fprintf(out, " AStatsEvent_setAtomId(event, code);\n");
- write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAnnotations, "AStatsEvent_",
+ write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "AStatsEvent_",
"event, ");
for (vector<java_type_t>::const_iterator arg = signature.begin();
arg != signature.end(); arg++) {
@@ -159,7 +177,7 @@
fprintf(stderr, "Encountered unsupported type.");
return 1;
}
- write_annotations(out, argIndex, fieldNumberToAnnotations, "AStatsEvent_",
+ write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "AStatsEvent_",
"event, ");
argIndex++;
}
@@ -209,10 +227,9 @@
}
}
-static void write_native_method_header(
- FILE* out, const string& methodName,
- const map<vector<java_type_t>, FieldNumberToAnnotations>& signatureInfoMap,
- const AtomDecl& attributionDecl) {
+static void write_native_method_header(FILE* out, const string& methodName,
+ const SignatureInfoMap& signatureInfoMap,
+ const AtomDecl& attributionDecl) {
for (auto signatureInfoMapIt = signatureInfoMap.begin();
signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
vector<java_type_t> signature = signatureInfoMapIt->first;
@@ -278,16 +295,17 @@
fprintf(out, "//\n");
fprintf(out, "// Constants for enum values\n");
fprintf(out, "//\n\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end();
- atom++) {
- for (vector<AtomField>::const_iterator field = atom->fields.begin();
- field != atom->fields.end(); field++) {
+ for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
+ atomIt++) {
+ for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin();
+ field != (*atomIt)->fields.end(); field++) {
if (field->javaType == JAVA_TYPE_ENUM) {
- fprintf(out, "// Values for %s.%s\n", atom->message.c_str(), field->name.c_str());
+ fprintf(out, "// Values for %s.%s\n", (*atomIt)->message.c_str(),
+ field->name.c_str());
for (map<int, string>::const_iterator value = field->enumValues.begin();
value != field->enumValues.end(); value++) {
fprintf(out, "const int32_t %s__%s__%s = %d;\n",
- make_constant_name(atom->message).c_str(),
+ make_constant_name((*atomIt)->message).c_str(),
make_constant_name(field->name).c_str(),
make_constant_name(value->second).c_str(), value->first);
}
diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp
index 9878926..c654a1b 100644
--- a/tools/stats_log_api_gen/test_collation.cpp
+++ b/tools/stats_log_api_gen/test_collation.cpp
@@ -30,8 +30,7 @@
/**
* Return whether the map contains a vector of the elements provided.
*/
-static bool map_contains_vector(const map<vector<java_type_t>, FieldNumberToAnnotations>& s,
- int count, ...) {
+static bool map_contains_vector(const SignatureInfoMap& s, int count, ...) {
va_list args;
vector<java_type_t> v;
@@ -110,35 +109,37 @@
JAVA_TYPE_LONG // sint64
);
- set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- EXPECT_EQ(1, atom->code);
- EXPECT_EQ("int_atom", atom->name);
- EXPECT_EQ("IntAtom", atom->message);
- EXPECT_NO_ENUM_FIELD(atom);
- atom++;
+ EXPECT_EQ(4ul, atoms.decls.size());
- EXPECT_EQ(2, atom->code);
- EXPECT_EQ("out_of_order_atom", atom->name);
- EXPECT_EQ("OutOfOrderAtom", atom->message);
- EXPECT_NO_ENUM_FIELD(atom);
- atom++;
+ AtomDeclSet::const_iterator atomIt = atoms.decls.begin();
+ EXPECT_EQ(1, (*atomIt)->code);
+ EXPECT_EQ("int_atom", (*atomIt)->name);
+ EXPECT_EQ("IntAtom", (*atomIt)->message);
+ EXPECT_NO_ENUM_FIELD((*atomIt));
+ atomIt++;
- EXPECT_EQ(3, atom->code);
- EXPECT_EQ("another_int_atom", atom->name);
- EXPECT_EQ("AnotherIntAtom", atom->message);
- EXPECT_NO_ENUM_FIELD(atom);
- atom++;
+ EXPECT_EQ(2, (*atomIt)->code);
+ EXPECT_EQ("out_of_order_atom", (*atomIt)->name);
+ EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message);
+ EXPECT_NO_ENUM_FIELD((*atomIt));
+ atomIt++;
- EXPECT_EQ(4, atom->code);
- EXPECT_EQ("all_types_atom", atom->name);
- EXPECT_EQ("AllTypesAtom", atom->message);
+ EXPECT_EQ(3, (*atomIt)->code);
+ EXPECT_EQ("another_int_atom", (*atomIt)->name);
+ EXPECT_EQ("AnotherIntAtom", (*atomIt)->message);
+ EXPECT_NO_ENUM_FIELD((*atomIt));
+ atomIt++;
+
+ EXPECT_EQ(4, (*atomIt)->code);
+ EXPECT_EQ("all_types_atom", (*atomIt)->name);
+ EXPECT_EQ("AllTypesAtom", (*atomIt)->message);
map<int, string> enumValues;
enumValues[0] = "VALUE0";
enumValues[1] = "VALUE1";
- EXPECT_HAS_ENUM_FIELD(atom, "enum_field", enumValues);
- atom++;
+ EXPECT_HAS_ENUM_FIELD((*atomIt), "enum_field", enumValues);
+ atomIt++;
- EXPECT_TRUE(atom == atoms.decls.end());
+ EXPECT_EQ(atoms.decls.end(), atomIt);
}
/**
@@ -235,10 +236,10 @@
Atoms atoms;
collate_atoms(ListedAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
for (const auto& atomDecl : atoms.decls) {
- if (atomDecl.code == 1) {
- EXPECT_TRUE(atomDecl.whitelisted);
+ if (atomDecl->code == 1) {
+ EXPECT_TRUE(atomDecl->whitelisted);
} else {
- EXPECT_FALSE(atomDecl.whitelisted);
+ EXPECT_FALSE(atomDecl->whitelisted);
}
}
}
@@ -258,33 +259,66 @@
EXPECT_EQ(atoms.signatureInfoMap.size(), 2u);
EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_STRING);
- for (auto signatureInfoMapIt : atoms.signatureInfoMap) {
- vector<java_type_t> signature = signatureInfoMapIt.first;
- const FieldNumberToAnnotations& fieldNumberToAnnotations = signatureInfoMapIt.second;
- if (signature[0] == JAVA_TYPE_STRING) {
- EXPECT_EQ(0u, fieldNumberToAnnotations.size());
- } else if (signature[0] == JAVA_TYPE_INT) {
- EXPECT_EQ(1u, fieldNumberToAnnotations.size());
- EXPECT_NE(fieldNumberToAnnotations.end(), fieldNumberToAnnotations.find(1));
- const set<shared_ptr<Annotation>>& annotations = fieldNumberToAnnotations.at(1);
- EXPECT_EQ(2u, annotations.size());
- for (const shared_ptr<Annotation> annotation : annotations) {
- EXPECT_TRUE(annotation->annotationId == ANNOTATION_ID_IS_UID ||
- annotation->annotationId == ANNOTATION_ID_STATE_OPTION);
- if (ANNOTATION_ID_IS_UID == annotation->annotationId) {
- EXPECT_EQ(1, annotation->atomId);
- EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
- EXPECT_TRUE(annotation->value.boolValue);
- }
- if (ANNOTATION_ID_STATE_OPTION == annotation->annotationId) {
- EXPECT_EQ(3, annotation->atomId);
- EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type);
- EXPECT_EQ(os::statsd::StateField::EXCLUSIVE_STATE, annotation->value.intValue);
- }
- }
- }
- }
+ SignatureInfoMap::const_iterator signatureInfoMapIt;
+ const vector<java_type_t>* signature;
+ const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet;
+ FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt;
+ const AtomDeclSet* atomDeclSet;
+ AtomDeclSet::const_iterator atomDeclSetIt;
+ AtomDecl* atomDecl;
+ FieldNumberToAnnotations* fieldNumberToAnnotations;
+ FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt;
+ const AnnotationSet* annotationSet;
+ AnnotationSet::const_iterator annotationSetIt;
+ Annotation* annotation;
+
+ signatureInfoMapIt = atoms.signatureInfoMap.begin();
+ signature = &(signatureInfoMapIt->first);
+ fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
+ EXPECT_EQ(1ul, signature->size());
+ EXPECT_EQ(JAVA_TYPE_INT, signature->at(0));
+ EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size());
+ fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin();
+ EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first);
+ atomDeclSet = &fieldNumberToAtomDeclSetIt->second;
+ EXPECT_EQ(2ul, atomDeclSet->size());
+ atomDeclSetIt = atomDeclSet->begin();
+ atomDecl = atomDeclSetIt->get();
+ EXPECT_EQ(1, atomDecl->code);
+ fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
+ fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
+ EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
+ annotationSet = &fieldNumberToAnnotationsIt->second;
+ EXPECT_EQ(1ul, annotationSet->size());
+ annotationSetIt = annotationSet->begin();
+ annotation = annotationSetIt->get();
+ EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId);
+ EXPECT_EQ(1, annotation->atomId);
+ EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
+ EXPECT_TRUE(annotation->value.boolValue);
+
+ atomDeclSetIt++;
+ atomDecl = atomDeclSetIt->get();
+ EXPECT_EQ(3, atomDecl->code);
+ fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
+ fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
+ EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
+ annotationSet = &fieldNumberToAnnotationsIt->second;
+ EXPECT_EQ(1ul, annotationSet->size());
+ annotationSetIt = annotationSet->begin();
+ annotation = annotationSetIt->get();
+ EXPECT_EQ(ANNOTATION_ID_STATE_OPTION, annotation->annotationId);
+ EXPECT_EQ(3, annotation->atomId);
+ EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type);
+ EXPECT_EQ(os::statsd::StateField::EXCLUSIVE_STATE, annotation->value.intValue);
+
+ signatureInfoMapIt++;
+ signature = &signatureInfoMapIt->first;
+ fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
+ EXPECT_EQ(1ul, signature->size());
+ EXPECT_EQ(JAVA_TYPE_STRING, signature->at(0));
+ EXPECT_EQ(0ul, fieldNumberToAtomDeclSet->size());
}
TEST(CollationTest, RecognizeModule1Atom) {
@@ -295,31 +329,59 @@
EXPECT_EQ(atoms.decls.size(), 2ul);
EXPECT_EQ(atoms.signatureInfoMap.size(), 1u);
EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
- for (auto signatureInfoMapIt : atoms.signatureInfoMap) {
- vector<java_type_t> signature = signatureInfoMapIt.first;
- const FieldNumberToAnnotations& fieldNumberToAnnotations = signatureInfoMapIt.second;
- EXPECT_EQ(JAVA_TYPE_INT, signature[0]);
- EXPECT_EQ(1u, fieldNumberToAnnotations.size());
- int fieldNumber = 1;
- EXPECT_NE(fieldNumberToAnnotations.end(), fieldNumberToAnnotations.find(fieldNumber));
- const set<shared_ptr<Annotation>>& annotations = fieldNumberToAnnotations.at(fieldNumber);
- EXPECT_EQ(2u, annotations.size());
- for (const shared_ptr<Annotation> annotation : annotations) {
- EXPECT_TRUE(annotation->annotationId == ANNOTATION_ID_IS_UID ||
- annotation->annotationId == ANNOTATION_ID_STATE_OPTION);
- if (ANNOTATION_ID_IS_UID == annotation->annotationId) {
- EXPECT_EQ(1, annotation->atomId);
- EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
- EXPECT_TRUE(annotation->value.boolValue);
- }
- if (ANNOTATION_ID_STATE_OPTION == annotation->annotationId) {
- EXPECT_EQ(3, annotation->atomId);
- EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type);
- EXPECT_EQ(os::statsd::StateField::EXCLUSIVE_STATE, annotation->value.intValue);
- }
- }
- }
+ SignatureInfoMap::const_iterator signatureInfoMapIt;
+ const vector<java_type_t>* signature;
+ const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet;
+ FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt;
+ const AtomDeclSet* atomDeclSet;
+ AtomDeclSet::const_iterator atomDeclSetIt;
+ AtomDecl* atomDecl;
+ FieldNumberToAnnotations* fieldNumberToAnnotations;
+ FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt;
+ const AnnotationSet* annotationSet;
+ AnnotationSet::const_iterator annotationSetIt;
+ Annotation* annotation;
+
+ signatureInfoMapIt = atoms.signatureInfoMap.begin();
+ signature = &(signatureInfoMapIt->first);
+ fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
+ EXPECT_EQ(1ul, signature->size());
+ EXPECT_EQ(JAVA_TYPE_INT, signature->at(0));
+ EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size());
+ fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin();
+ EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first);
+ atomDeclSet = &fieldNumberToAtomDeclSetIt->second;
+ EXPECT_EQ(2ul, atomDeclSet->size());
+ atomDeclSetIt = atomDeclSet->begin();
+ atomDecl = atomDeclSetIt->get();
+ EXPECT_EQ(1, atomDecl->code);
+ fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
+ fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
+ EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
+ annotationSet = &fieldNumberToAnnotationsIt->second;
+ EXPECT_EQ(1ul, annotationSet->size());
+ annotationSetIt = annotationSet->begin();
+ annotation = annotationSetIt->get();
+ EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId);
+ EXPECT_EQ(1, annotation->atomId);
+ EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
+ EXPECT_TRUE(annotation->value.boolValue);
+
+ atomDeclSetIt++;
+ atomDecl = atomDeclSetIt->get();
+ EXPECT_EQ(3, atomDecl->code);
+ fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
+ fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
+ EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
+ annotationSet = &fieldNumberToAnnotationsIt->second;
+ EXPECT_EQ(1ul, annotationSet->size());
+ annotationSetIt = annotationSet->begin();
+ annotation = annotationSetIt->get();
+ EXPECT_EQ(ANNOTATION_ID_STATE_OPTION, annotation->annotationId);
+ EXPECT_EQ(3, annotation->atomId);
+ EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type);
+ EXPECT_EQ(os::statsd::StateField::EXCLUSIVE_STATE, annotation->value.intValue);
}
} // namespace stats_log_api_gen
diff --git a/tools/stats_log_api_gen/utils.cpp b/tools/stats_log_api_gen/utils.cpp
index 0262488..abb8913 100644
--- a/tools/stats_log_api_gen/utils.cpp
+++ b/tools/stats_log_api_gen/utils.cpp
@@ -22,10 +22,10 @@
namespace stats_log_api_gen {
static void build_non_chained_decl_map(const Atoms& atoms,
- std::map<int, set<AtomDecl>::const_iterator>* decl_map) {
- for (set<AtomDecl>::const_iterator atom = atoms.non_chained_decls.begin();
- atom != atoms.non_chained_decls.end(); atom++) {
- decl_map->insert(std::make_pair(atom->code, atom));
+ std::map<int, AtomDeclSet::const_iterator>* decl_map) {
+ for (AtomDeclSet::const_iterator atomIt = atoms.non_chained_decls.begin();
+ atomIt != atoms.non_chained_decls.end(); atomIt++) {
+ decl_map->insert(std::make_pair((*atomIt)->code, atomIt));
}
}
@@ -117,11 +117,11 @@
}
static void write_cpp_usage(FILE* out, const string& method_name, const string& atom_code_name,
- const AtomDecl& atom, const AtomDecl& attributionDecl) {
+ const shared_ptr<AtomDecl> atom, const AtomDecl& attributionDecl) {
fprintf(out, " * Usage: %s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str());
- for (vector<AtomField>::const_iterator field = atom.fields.begin(); field != atom.fields.end();
- field++) {
+ for (vector<AtomField>::const_iterator field = atom->fields.begin();
+ field != atom->fields.end(); field++) {
if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
for (auto chainField : attributionDecl.fields) {
if (chainField.javaType == JAVA_TYPE_STRING) {
@@ -154,27 +154,27 @@
fprintf(out, " */\n");
fprintf(out, "enum {\n");
- std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
+ std::map<int, AtomDeclSet::const_iterator> atom_code_to_non_chained_decl_map;
build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
size_t i = 0;
// Print atom constants
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end();
- atom++) {
- string constant = make_constant_name(atom->name);
+ for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
+ atomIt++) {
+ string constant = make_constant_name((*atomIt)->name);
fprintf(out, "\n");
fprintf(out, " /**\n");
- fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
- write_cpp_usage(out, "stats_write", constant, *atom, attributionDecl);
+ fprintf(out, " * %s %s\n", (*atomIt)->message.c_str(), (*atomIt)->name.c_str());
+ write_cpp_usage(out, "stats_write", constant, *atomIt, attributionDecl);
- auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
+ auto non_chained_decl = atom_code_to_non_chained_decl_map.find((*atomIt)->code);
if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second,
attributionDecl);
}
fprintf(out, " */\n");
char const* const comma = (i == atoms.decls.size() - 1) ? "" : ",";
- fprintf(out, " %s = %d%s\n", constant.c_str(), atom->code, comma);
+ fprintf(out, " %s = %d%s\n", constant.c_str(), (*atomIt)->code, comma);
i++;
}
fprintf(out, "\n");
@@ -245,40 +245,40 @@
void write_java_atom_codes(FILE* out, const Atoms& atoms) {
fprintf(out, " // Constants for atom codes.\n");
- std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
+ std::map<int, AtomDeclSet::const_iterator> atom_code_to_non_chained_decl_map;
build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
// Print constants for the atom codes.
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end();
- atom++) {
- string constant = make_constant_name(atom->name);
+ for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
+ atomIt++) {
+ string constant = make_constant_name((*atomIt)->name);
fprintf(out, "\n");
fprintf(out, " /**\n");
- fprintf(out, " * %s %s<br>\n", atom->message.c_str(), atom->name.c_str());
- write_java_usage(out, "write", constant, *atom);
- auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
+ fprintf(out, " * %s %s<br>\n", (*atomIt)->message.c_str(), (*atomIt)->name.c_str());
+ write_java_usage(out, "write", constant, **atomIt);
+ auto non_chained_decl = atom_code_to_non_chained_decl_map.find((*atomIt)->code);
if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
- write_java_usage(out, "write_non_chained", constant, *non_chained_decl->second);
+ write_java_usage(out, "write_non_chained", constant, **(non_chained_decl->second));
}
fprintf(out, " */\n");
- fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code);
+ fprintf(out, " public static final int %s = %d;\n", constant.c_str(), (*atomIt)->code);
}
fprintf(out, "\n");
}
void write_java_enum_values(FILE* out, const Atoms& atoms) {
fprintf(out, " // Constants for enum values.\n\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end();
- atom++) {
- for (vector<AtomField>::const_iterator field = atom->fields.begin();
- field != atom->fields.end(); field++) {
+ for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
+ atomIt++) {
+ for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin();
+ field != (*atomIt)->fields.end(); field++) {
if (field->javaType == JAVA_TYPE_ENUM) {
- fprintf(out, " // Values for %s.%s\n", atom->message.c_str(),
+ fprintf(out, " // Values for %s.%s\n", (*atomIt)->message.c_str(),
field->name.c_str());
for (map<int, string>::const_iterator value = field->enumValues.begin();
value != field->enumValues.end(); value++) {
fprintf(out, " public static final int %s__%s__%s = %d;\n",
- make_constant_name(atom->message).c_str(),
+ make_constant_name((*atomIt)->message).c_str(),
make_constant_name(field->name).c_str(),
make_constant_name(value->second).c_str(), value->first);
}
@@ -307,8 +307,7 @@
fprintf(out, ");<br>\n");
}
-int write_java_non_chained_methods(
- FILE* out, const map<vector<java_type_t>, FieldNumberToAnnotations>& signatureInfoMap) {
+int write_java_non_chained_methods(FILE* out, const SignatureInfoMap& signatureInfoMap) {
for (auto signatureInfoMapIt = signatureInfoMap.begin();
signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
// Print method signature.
@@ -351,8 +350,7 @@
return 0;
}
-int write_java_work_source_methods(
- FILE* out, const map<vector<java_type_t>, FieldNumberToAnnotations>& signatureInfoMap) {
+int write_java_work_source_methods(FILE* out, const SignatureInfoMap& signatureInfoMap) {
fprintf(out, " // WorkSource methods.\n");
for (auto signatureInfoMapIt = signatureInfoMap.begin();
signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
index 468f323..57b6f62 100644
--- a/tools/stats_log_api_gen/utils.h
+++ b/tools/stats_log_api_gen/utils.h
@@ -67,11 +67,9 @@
void write_java_usage(FILE* out, const string& method_name, const string& atom_code_name,
const AtomDecl& atom);
-int write_java_non_chained_methods(
- FILE* out, const map<vector<java_type_t>, FieldNumberToAnnotations>& signatureInfoMap);
+int write_java_non_chained_methods(FILE* out, const SignatureInfoMap& signatureInfoMap);
-int write_java_work_source_methods(
- FILE* out, const map<vector<java_type_t>, FieldNumberToAnnotations>& signatureInfoMap);
+int write_java_work_source_methods(FILE* out, const SignatureInfoMap& signatureInfoMap);
} // namespace stats_log_api_gen
} // namespace android
diff --git a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
index 6632c16..0d13805 100644
--- a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
@@ -74,7 +74,7 @@
}
@Override
- public boolean satisfiedBy(@Nullable NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) {
if (this == other) {
return true;
}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index 3d946c9..ed54ad1 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -552,7 +552,7 @@
/** @hide */
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
if (this == other) {
return true;
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
index a4b3e86..9ae3bd0 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
@@ -120,7 +120,7 @@
}
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
if (!(other instanceof WifiAwareAgentNetworkSpecifier)) {
return false;
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
index 65ac1ab..3547750 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -212,7 +212,7 @@
/** @hide */
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
// MatchAllNetworkSpecifier is taken care in NetworkCapabilities#satisfiedBySpecifier.
if (other instanceof WifiAwareAgentNetworkSpecifier) {
return ((WifiAwareAgentNetworkSpecifier) other).satisfiesAwareNetworkSpecifier(this);
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
index 0233ee2..d479aac 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
@@ -155,8 +155,8 @@
public void testWifiNetworkAgentSpecifierSatisifiesNullAndAllMatch() {
WifiNetworkAgentSpecifier specifier = createDefaultNetworkAgentSpecifier();
- assertTrue(specifier.satisfiedBy(null));
- assertTrue(specifier.satisfiedBy(new MatchAllNetworkSpecifier()));
+ assertTrue(specifier.canBeSatisfiedBy(null));
+ assertTrue(specifier.canBeSatisfiedBy(new MatchAllNetworkSpecifier()));
}
/**
@@ -170,7 +170,7 @@
WifiNetworkAgentSpecifier specifier1 = createDefaultNetworkAgentSpecifier();
WifiNetworkAgentSpecifier specifier2 = createDefaultNetworkAgentSpecifier();
- assertTrue(specifier2.satisfiedBy(specifier1));
+ assertTrue(specifier2.canBeSatisfiedBy(specifier1));
}
/**
@@ -196,8 +196,8 @@
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -224,8 +224,8 @@
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -252,8 +252,8 @@
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -283,8 +283,8 @@
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -315,8 +315,8 @@
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -347,8 +347,8 @@
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -374,8 +374,8 @@
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
index 3b67236..53a7d03 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
@@ -396,8 +396,8 @@
MacAddress.fromString(TEST_BSSID_OUI_MASK)),
wifiConfiguration);
- assertTrue(specifier.satisfiedBy(null));
- assertTrue(specifier.satisfiedBy(new MatchAllNetworkSpecifier()));
+ assertTrue(specifier.canBeSatisfiedBy(null));
+ assertTrue(specifier.canBeSatisfiedBy(new MatchAllNetworkSpecifier()));
}
/**
@@ -424,7 +424,7 @@
MacAddress.fromString(TEST_BSSID_OUI_MASK)),
wifiConfiguration);
- assertTrue(specifier2.satisfiedBy(specifier1));
+ assertTrue(specifier2.canBeSatisfiedBy(specifier1));
}
/**
@@ -453,7 +453,7 @@
MacAddress.fromString(TEST_BSSID_OUI_MASK)),
wifiConfiguration2);
- assertFalse(specifier2.satisfiedBy(specifier1));
+ assertFalse(specifier2.canBeSatisfiedBy(specifier1));
}
/**
@@ -480,7 +480,7 @@
MacAddress.fromString(TEST_BSSID_OUI_MASK)),
wifiConfiguration);
- assertFalse(specifier2.satisfiedBy(specifier1));
+ assertFalse(specifier2.canBeSatisfiedBy(specifier1));
}
/**
@@ -507,6 +507,6 @@
WifiManager.ALL_ZEROS_MAC_ADDRESS),
wifiConfiguration);
- assertFalse(specifier2.satisfiedBy(specifier1));
+ assertFalse(specifier2.canBeSatisfiedBy(specifier1));
}
}
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
index 81b02fa..f2961db 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
@@ -79,7 +79,7 @@
public void testEmptyDoesntMatchAnything() {
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier();
WifiAwareNetworkSpecifier ns = getDummyNetworkSpecifier(6);
- collector.checkThat("No match expected", ns.satisfiedBy(dut), equalTo(false));
+ collector.checkThat("No match expected", ns.canBeSatisfiedBy(dut), equalTo(false));
}
/**
@@ -91,8 +91,8 @@
WifiAwareNetworkSpecifier nsThis = getDummyNetworkSpecifier(6);
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(nsThis);
WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(8);
- collector.checkThat("Match expected", nsThis.satisfiedBy(dut), equalTo(true));
- collector.checkThat("No match expected", nsOther.satisfiedBy(dut), equalTo(false));
+ collector.checkThat("Match expected", nsThis.canBeSatisfiedBy(dut), equalTo(true));
+ collector.checkThat("No match expected", nsOther.canBeSatisfiedBy(dut), equalTo(false));
}
/**
@@ -113,9 +113,9 @@
WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(10000);
for (WifiAwareNetworkSpecifier nsThis: nsSet) {
- collector.checkThat("Match expected", nsThis.satisfiedBy(dut), equalTo(true));
+ collector.checkThat("Match expected", nsThis.canBeSatisfiedBy(dut), equalTo(true));
}
- collector.checkThat("No match expected", nsOther.satisfiedBy(dut), equalTo(false));
+ collector.checkThat("No match expected", nsOther.canBeSatisfiedBy(dut), equalTo(false));
}
/**
@@ -137,7 +137,7 @@
WifiAwareAgentNetworkSpecifier newNs = new WifiAwareAgentNetworkSpecifier(
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
- collector.checkThat("Match expected", oldNs.satisfiedBy(newNs), equalTo(true));
+ collector.checkThat("Match expected", oldNs.canBeSatisfiedBy(newNs), equalTo(true));
}
/**
@@ -159,7 +159,7 @@
WifiAwareAgentNetworkSpecifier oldNs = new WifiAwareAgentNetworkSpecifier(
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
- collector.checkThat("Match unexpected", oldNs.satisfiedBy(newNs), equalTo(false));
+ collector.checkThat("Match unexpected", oldNs.canBeSatisfiedBy(newNs), equalTo(false));
}
// utilities